План: Использование триггера INSTEAD OF INSERT
для перенаправления неудачных вставок в таблицу «ожидания».Эти строки остаются в «ожидающей» таблице, пока некоторая дополнительная информация не будет вставлена в другую таблицу;когда эта новая информация становится доступной, ожидающие строки перемещаются в исходное место назначения.
Справочная информация: Сделки регистрируются относительно Холдинга.Служба, обновляющая Сделки, может иметь информацию, которой еще нет в базе данных, такую как сделка по Холдингу, которая еще не была добавлена (пожалуйста, не сосредотачивайтесь на «почему» этой части системы, я могу »изменить это).
Проблема: Триггер INSTEAD OF INSERT
работает, но у меня проблемы с триггером INSTEAD OF UPDATE
.Когда применяется UPDATE
, но строки, подлежащие обновлению, находятся в таблице «в ожидании», таблица INSERTED
в триггере пуста, и поэтому я не могу обновить таблицу «в ожидании».Вот (упрощенный) DDL:
CREATE TABLE [Holding] (
[HoldingID] INTEGER NOT NULL,
[InstrumentID] INTEGER,
CONSTRAINT [PK_Holding] PRIMARY KEY ([HoldingID])
)
GO
CREATE TABLE [Trade] (
[TradeID] INTEGER IDENTITY(1,1) NOT NULL,
[HoldingID] INTEGER NOT NULL,
[BuySell] CHAR(1) NOT NULL,
CONSTRAINT [PK_TradeSummary] PRIMARY KEY ([TradeID])
)
GO
ALTER TABLE [Trade] ADD CONSTRAINT [CC_Trade_BuySell]
CHECK (BuySell = 'B' or BuySell = 'S')
GO
ALTER TABLE [Trade] ADD CONSTRAINT [Holding_Trade]
FOREIGN KEY ([HoldingID]) REFERENCES [Holding] ([HoldingID])
GO
CREATE TABLE [TradePending] (
[TradeID] INTEGER IDENTITY(1,1) NOT NULL,
[HoldingID] INTEGER NOT NULL,
[BuySell] CHAR(1) NOT NULL,
CONSTRAINT [PK_TradePending] PRIMARY KEY ([TradeID])
)
GO
ALTER TABLE [TradePending] ADD CONSTRAINT [CC_TradePending_BuySell]
CHECK (BuySell = 'B' or BuySell = 'S')
GO
-- The INSERT trigger works, when the referenced holding does not exist the row is redirected to the TradePending table.
CREATE TRIGGER [Trg_Trade_Insert]
ON [Trade]
INSTEAD OF INSERT
AS
IF NOT EXISTS (SELECT 1
FROM inserted i INNER JOIN Holding h
ON i.HoldingID = h.HoldingID)
BEGIN
INSERT TradePending(HoldingID, BuySell) SELECT HoldingID, BuySell FROM inserted
END
ELSE
BEGIN
INSERT Trade(HoldingID, BuySell) SELECT HoldingID, BuySell FROM inserted
END
GO
Триггер для выполнения UPDATE
работает, когда строка существует в таблице Trade
, но не, когда строка не существует, виртуальная таблица INSERTED
пустой.Я добавил несколько операторов PRINT
в триггер, чтобы попытаться увидеть, что происходит.
CREATE TRIGGER [dbo].[Trg_Trade_Update]
ON [dbo].[Trade]
INSTEAD OF UPDATE
AS
DECLARE @s char(1)
DECLARE @h int
IF NOT EXISTS (SELECT 1
FROM inserted i INNER JOIN Trade t
ON i.HoldingID = t.HoldingID)
BEGIN
PRINT 'Update TradePending'
SET @h = COALESCE((SELECT i.HoldingID
FROM TradeSummaryPending t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID), 0)
SET @a = COALESCE((SELECT i.BuySell
FROM TradeSummaryPending t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID), 'N')
PRINT 'h=' + CAST(@h AS varchar(1)) + ' s=' + @s
UPDATE TradePending
SET BuySell = i.BuySell
FROM Trade t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID
END
ELSE
BEGIN
PRINT 'Update Trade'
SET @h = (SELECT i.HoldingID
FROM Trade t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID)
SET @s = (SELECT i.BuySell
FROM Trade t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID)
PRINT 'h=' + CAST(@h AS varchar(1)) + ' s=' + @s
UPDATE Trade
SET BuySell = i.BuySell
FROM Trade t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID
END
Вот несколько примеров данных для тестирования:
-- Create a Holding and a Trade, this will be inserted as normal.
INSERT Holding VALUES(1,100)
INSERT TradeSummary VALUES(1,'B')
-- Create a Trade where the Holding does not exists,
-- row redirected to TradePending table.
INSERT TradeSummary values(2,'S')
-- Update the first trade to be a Buy, updates the `Trade` table
UPDATE Trade SET BuySell = 'S' WHERE HoldingID = 1
Выходные данные выполнения обновления:
Update Trade
h=1 s=S
(1 row(s) affected)
(1 row(s) affected)
Теперь обновите строку, которая существует только в таблице TradePending:
UPDATE Trade SET BuySell = 'B' WHERE HoldingID = 2
, что приведет к следующему выводу:
Update TradePending
h=0 s=N
(0 row(s) affected)
(0 row(s) affected)
INSERTED
таблица теперь содержит строки, хотя это триггер INSTEAD OF
и должен быть выполнен до применения SQL к таблице.
Кто-нибудь может объяснить, почему таблица INSERTED
пуста?Я уверен, что решение будет чем-то тривиальным, но я просто не могу заставить его работать.