Удалить триггер для таблицы, оптимизированной для памяти
Я пытаюсь написать триггер удаления для таблицы, оптимизированной для памяти, в SQL Server 2016 RC 2
CREATE TRIGGER [dbo].[TestCascadeDelete]
ON [CAMSII].[dbo].[Table1]
WITH NATIVE_COMPILATION, SCHEMABINDING
FOR DELETE
AS BEGIN ATOMIC WITH
(
TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english'
)
DELETE [dbo].[Table2]
WHERE [dbo].[Table2].Id IN(SELECT Id from DELETED)
END
GO
Когда я выполняю этот запрос, я получаю следующую ошибку. Подзапросы (запросы, вложенные в другой запрос) поддерживаются только в инструкциях SELECT с собственно скомпилированными модулями.
2 ответа
Сегодня я сделал простой трюк, чтобы обойти это, поскольку не могу использовать подзапросы в скомпилированной хранимой процедуре.
Сценарий "Удалить из основных дочерних таблиц":
row exist in parent -> capture id;
while (rowcount <> 0)
begin
delete from child where id = idcaptured;
delete from master where id = idcaptured;
row exist in parent -> capture id;
end;
Обходной путь должен использовать переменную таблицы и перебрать строки с циклом WHILE. Вот пример для ОБНОВЛЕНИЯ с обходным путем ОТ:
DROP TABLE IF EXISTS dbo.table1
GO
DROP TYPE IF EXISTS dbo.type1
GO
CREATE TABLE dbo.table1
(Id INT NOT NULL PRIMARY KEY NONCLUSTERED,
c2 INT NOT NULL,
LastUpdated DATETIME2 NOT NULL DEFAULT (SYSDATETIME()))
WITH (MEMORY_OPTIMIZED=ON)
GO
CREATE TYPE dbo.type1 AS TABLE
(Id INT NOT NULL,
c2 INT NOT NULL,
RowID INT IDENTITY,
INDEX ix_RowID (RowID DESC))
WITH (MEMORY_OPTIMIZED=ON)
GO
CREATE TRIGGER dbo.tr_table1
ON dbo.table1
WITH NATIVE_COMPILATION, SCHEMABINDING
AFTER UPDATE
AS BEGIN ATOMIC WITH
(
TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english'
)
-- original UPDATE with FROM statement:
--UPDATE dbo.table1
--SET LastUpdated = SYSDATETIME()
--FROM dbo.table1 t JOIN Inserted i ON t.Id=i.Id
DECLARE @tv dbo.type1
INSERT @tv (Id, c2)
SELECT Id, c2 FROM Inserted
-- workaround that iterates over the rows in the table variable, simulating a cursor:
DECLARE @max INT = SCOPE_IDENTITY()
DECLARE @i INT = 1
DECLARE @Id INT
WHILE @i <= @max
BEGIN
SELECT @Id = Id
FROM @tv
WHERE RowID=@i
UPDATE dbo.table1
SET LastUpdated = SYSDATETIME()
WHERE Id = @Id
SET @i += 1
END
END
GO
INSERT dbo.table1 (Id, c2) VALUES (1,2)
INSERT dbo.table1 (Id, c2) VALUES (2,2)
GO
SELECT * FROM dbo.table1
GO
UPDATE dbo.table1
SET c2 = 3
GO
SELECT * FROM dbo.table1
GO