Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Подскажите как победить ? / 11 сообщений из 11, страница 1 из 1
15.10.2002, 11:50:21
    #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
15.10.2002, 12:05:43
    #32058307
Luchkin Dmitry
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите как победить ?
С View, извините, не работал. Поэтому имхо:
или 1) перерисовать view, чтобы показал "свежие" данные
или 2) в View показывать вместо поля Orders.giv поле из временной таблицы - копии Orders.
Может кто умнее что-то лучшее подскажет...
...
Рейтинг: 0 / 0
15.10.2002, 12:15:31
    #32058314
VVG_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите как победить ?
А группировать deleted по OrderID разве нельзя?
...
Рейтинг: 0 / 0
15.10.2002, 12:58:23
    #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
15.10.2002, 13:00:11
    #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
15.10.2002, 13:00:28
    #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
15.10.2002, 13:02:47
    #32058340
mvg_first
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите как победить ?
Тьфу ты блин, опять неправильно указал теперь забыл указать Group By но я думаю все поняли общую мысль :)
...
Рейтинг: 0 / 0
15.10.2002, 13:34:18
    #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
15.10.2002, 14:45:13
    #32058396
VVG_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите как победить ?
А на табличке OrderLinks есть primary key?
...
Рейтинг: 0 / 0
16.10.2002, 08:17:19
    #32058608
Mavr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите как победить ?
Да, я написал же, что в ней составной Primary Key: OrderID+SoprID
...
Рейтинг: 0 / 0
16.10.2002, 11:48:56
    #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
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Подскажите как победить ? / 11 сообщений из 11, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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