powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Подскажите как победить ?
11 сообщений из 11, страница 1 из 1
Подскажите как победить ?
    #32058300
Mavr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблема в следующем:
Допустим есть 2 таблицы:

Orders со следующими данными:

OrderID | Giv
1 | 10
2 | 0

OrderLinks:
OrderID | SoprID | Amount
1 | 4 | 5
1 | 8 | 5

Primary Key составной: OrderID + SoprID
Думаю понятно что они связаны по OrderID, а SoprID поле связи с третьей таблицей но это не важно. Поле Giv в таблице Orders должно содержать всегда корректную сумму по полю Amount из таблицы OrderLinks

Есть View:

Код: plaintext
1.
2.
3.
4.
CREATE VIEW dbo.OLnk WITH VIEW_METADATA
AS
SELECT     dbo.OrderLinks.*, dbo.Orders.giv
FROM         dbo.OrderLinks INNER JOIN
                      dbo.Orders ON dbo.OrderLinks.OrderID = dbo.Orders.OrderID


У него есть тригер:

Код: plaintext
1.
2.
3.
4.
5.
6.
CREATE TRIGGER [OLnk_Del] ON [dbo].[OLnk]
INSTEAD OF DELETE
AS
BEGIN
UPDATE o SET o.giv = o.giv-d.amount FROM Orders o INNER JOIN Deleted d ON o.OrderID = d.OrderID
DELETE lnk FROM OrderLinks lnk INNER JOIN Deleted d ON lnk.OrderID = d.OrderID AND lnk.SoprID = d.SoprID
END


Т.е. задумано так что бы когда удаляем записи из OrderLinks, корректно уменьшалось поле Giv в Orders.

Так все и происходит если удаляем по одной записи из приведенного view, если же удаляем более чем одну запись с одинаковым OrderID (данные которые я привел как раз именно в такой ситуации), то возникает следующая ошибка:
Another user has modified the contents of this table or view; the database row you are modifying no longer exists in the database.

В принципе то понятно почему ошибка возникает, потому что поле Giv в одной и тойже записи апдейтися несколько раз, но может есть возможность обойти эти грабли.

Заранее благодарен за ответ !

P.S. Тригер пишется для view'а по сооброжениям не касающихся данной проблемы, и отказываться от view'а не хотелось бы.
...
Рейтинг: 0 / 0
Подскажите как победить ?
    #32058307
Фотография Luchkin Dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С View, извините, не работал. Поэтому имхо:
или 1) перерисовать view, чтобы показал "свежие" данные
или 2) в View показывать вместо поля Orders.giv поле из временной таблицы - копии Orders.
Может кто умнее что-то лучшее подскажет...
...
Рейтинг: 0 / 0
Подскажите как победить ?
    #32058314
Фотография VVG_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А группировать deleted по OrderID разве нельзя?
...
Рейтинг: 0 / 0
Подскажите как победить ?
    #32058336
mvg_first
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А по моему если строку
Код: plaintext
1.
UPDATE o SET o.giv = o.giv-d.amount FROM Orders o INNER JOIN Deleted d ON o.OrderID = d.OrderID

заменить на
Код: plaintext
1.
2.
UPDATE o SET o.giv = o.giv-d.amount FROM (SELECT OrderId, SUM(Amount) Amount FROM Orders) d
WHERE o.OrderID = d.OrderID

Будет работать :)
...
Рейтинг: 0 / 0
Подскажите как победить ?
    #32058338
Mavr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да решение здравое поменял в тригере Update:

Код: plaintext
1.
2.
UPDATE o SET o.giv=o.giv-d.amount FROM Orders o
INNER JOIN (SELECT Deleted.OrderID, SUM(Deleted.Amount) AS Amount FROM Deleted
GROUP BY Deleted.OrderID) d ON o.OrderID = d.OrderID

и должно было бы сработать, но почему-то не сработало, возникла та же ошибка, только теперь я не совсем понимаю почему, подозреваю что ошибка возникает из-за того что во view включено поле giv ...
Так и есть убрал из view поле giv, но оставил INNER JOIN и все сработало и даже в старом варианте без группировки по OrderID, т.е. получается что изначально проблема была в том что во view включено поле giv которое изменяется во время удаления.
И как с этим дальше бороться, view мне нужен с этим полем.
...
Рейтинг: 0 / 0
Подскажите как победить ?
    #32058339
mvg_first
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сорри обшибся строка должна выглядеть так
Код: plaintext
1.
2.
UPDATE o SET o.giv = o.giv-d.amount FROM (SELECT OrderId, SUM(Amount) Amount FROM Deleted) d
WHERE o.OrderID = d.OrderID
...
Рейтинг: 0 / 0
Подскажите как победить ?
    #32058340
mvg_first
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тьфу ты блин, опять неправильно указал теперь забыл указать Group By но я думаю все поняли общую мысль :)
...
Рейтинг: 0 / 0
Подскажите как победить ?
    #32058363
Mavr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да решение здравое поменял в тригере Update:

Код: plaintext
1.
2.
UPDATE o SET o.giv=o.giv-d.amount FROM Orders o
INNER JOIN (SELECT Deleted.OrderID, SUM(Deleted.Amount) AS Amount FROM Deleted
GROUP BY Deleted.OrderID) d ON o.OrderID = d.OrderID

и должно было бы сработать, но почему-то не сработало, возникла та же ошибка, только теперь я не совсем понимаю почему, подозреваю что ошибка возникает из-за того что во view включено поле giv ...
Так и есть убрал из view поле giv, но оставил INNER JOIN и все сработало и даже в старом варианте без группировки по OrderID, т.е. получается что изначально проблема была в том что во view включено поле giv которое изменяется во время удаления.
И как с этим дальше бороться, view мне нужен с этим полем.

Mvg_First я понял твой вариант ты имел в виду вот так:

Код: plaintext
UPDATE Orders SET Orders.giv=Orders.giv-d.amount FROM (SELECT OrderLinks.OrderID, SUM(OrderLinks.Amount) AS Amount FROM OrderLinks GROUP BY OrderLinks.OrderID) d  WHERE Orders.OrderID = d.OrderID


То же самое если убрать из view поле giv то все работает если нет то проблема.
...
Рейтинг: 0 / 0
Подскажите как победить ?
    #32058396
Фотография VVG_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А на табличке OrderLinks есть primary key?
...
Рейтинг: 0 / 0
Подскажите как победить ?
    #32058608
Mavr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, я написал же, что в ней составной Primary Key: OrderID+SoprID
...
Рейтинг: 0 / 0
Подскажите как победить ?
    #32058691
Фотография VVG_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну не знаю, при таких условиях:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
CREATE TABLE [dbo].[orderlinks] (
	[OrderID] [int] NOT NULL ,
	[SoprID] [int] NOT NULL ,
	[Amount] [int] NULL 
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[orders] (
	[OrderID] [int] NOT NULL ,
	[Giv] [int] NULL 
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[orderlinks] WITH NOCHECK ADD 
	CONSTRAINT [PK_orderlinks] PRIMARY KEY  CLUSTERED 
	(
		[OrderID],
		[SoprID]
	)  ON [PRIMARY] 
GO

ALTER TABLE [dbo].[orders] WITH NOCHECK ADD 
	CONSTRAINT [PK_orders] PRIMARY KEY  CLUSTERED 
	(
		[OrderID]
	)  ON [PRIMARY] 
GO

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO

CREATE VIEW dbo.OLnk WITH VIEW_METADATA
AS
SELECT     dbo.OrderLinks.*, dbo.Orders.giv
FROM         dbo.OrderLinks INNER JOIN
                      dbo.Orders ON dbo.OrderLinks.OrderID = dbo.Orders.OrderID

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO

CREATE TRIGGER [OLnk_Del] ON [dbo].[OLnk]
INSTEAD OF DELETE
AS
BEGIN
UPDATE o SET o.giv=o.giv-d.amount FROM Orders o
INNER JOIN (SELECT Deleted.OrderID, SUM(Deleted.Amount) AS Amount FROM Deleted
GROUP BY Deleted.OrderID) d ON o.OrderID = d.OrderID
DELETE lnk FROM OrderLinks lnk INNER JOIN Deleted d ON lnk.OrderID = d.OrderID AND lnk.SoprID = d.SoprID
END

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

у меня все работает идеально.

Код: plaintext
1.
2.
3.
4.
5.
6.
insert into orders select  1 , 10  union select  2 , 0 
insert into orderlinks select  1 , 4 , 5  union select  1 , 8 , 5 

delete from dbo.OLnk where orderid= 1 

select * from orders
select * from orderlinks

Результат:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
OrderID     Giv         
 ----------- ----------- 
 
 1             0 
 2             0 

( 2  row(s) affected)

OrderID     SoprID      Amount      
 ----------- ----------- ----------- 
 

( 0  row(s) affected)
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Подскажите как победить ?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]