このトピックでは、DDL トリガーと DML トリガーとメモリ最適化テーブルについて説明します。
LOGON トリガーとは、LOGON イベントで起動するように定義されたトリガーです。 LOGON トリガーは、メモリ最適化テーブルに影響しません。
DDL トリガー
DDL トリガーとは、自らを定義しているデータベースまたはサーバーに対して CREATE、ALTER、DROP、GRANT、DENY、REVOKE、または UPDATE STATISTICS の各ステートメントを実行したときに起動するように定義されているトリガーです。
データベースまたはサーバーで、CREATE_TABLE イベントまたはこのイベントを含むイベント グループに対応する 1 つ以上の DDL トリガーが定義されている場合は、メモリ最適化テーブルを作成できません。 データベースまたはサーバーで、DROP_TABLE イベントまたはこのイベントを含むイベント グループに対応する 1 つ以上の DDL トリガーが定義されている場合は、メモリ最適化テーブルを削除できません。
CREATE_PROCEDURE、DROP_PROCEDURE、またはこれらのイベントを含むイベント グループに対応する 1 つ以上の DDL トリガーが存在している場合は、ネイティブ コンパイル ストアド プロシージャを作成できません。
DML (データ操作言語) トリガー
DML トリガーは、メモリ最適化テーブルでは定義できません。 ただし、In-Memory OLTP を使用すると、ストアド プロシージャを明示的に使用してデータを挿入、更新、または削除する場合、DML トリガーと同様の効果を得ることができます。 システムにアドホック クエリが含まれている場合は、代わりにこれらのストアド プロシージャを使用して DML トリガーの効果をシミュレートするように変換します。
トリガー イベント (FOR/AFTER または INSTEAD OF) によっては、そのテーブルに対して INSERT、UPDATE、または DELETE を実行する適切なストアド プロシージャにトリガーの内容を含めることができます。 たとえば、AFTER INSERT トリガーを移行する場合、適切な INSERT ステートメントの後にトリガーの内容を含めることで、挿入操作を実行するストアド プロシージャを変更できます。
解釈されたストアド プロシージャまたはネイティブ コンパイル ストアド プロシージャを使用できます。 解釈されたストアド プロシージャ内のほとんどの Transact-SQL コンストラクトは、メモリ最適化テーブルで実行できます。 ただし、ネイティブ コンパイル ストアド プロシージャでは、Transact-SQL コンストラクトのサブセットのみがサポートされます。 メモリ最適化テーブルの Transact-SQL サポートについては、「 Interpreted Transact-SQL を使用した Memory-Optimized テーブルへのアクセス」を参照してください。 ネイティブ コンパイル ストアド プロシージャでの Transact-SQL のサポートについては、「 In-Memory OLTP でサポートされていないTransact-SQL コンストラクト」を参照してください。
メモリ最適化テーブルで DML トリガーの動作をシミュレートする簡単な例を次に示します。
データベースには、CREATE TABLE、CREATE TRIGGER、CREATE PROCEDURE ステートメントとしてスクリプト化された次のオブジェクトが含まれています。
CREATE TABLE OrderDetails
(
OrderId int not null primary key,
ProductId int not null,
SalePrice money not null,
Quantity int not null,
Total money not null,
IsDeleted bit not null DEFAULT (0)
)
GO
CREATE TRIGGER tr_order_details_insteadof_insert
ON OrderDetails
INSTEAD OF INSERT AS
BEGIN
DECLARE @pid int, @qty_buy int, @qty_remain int
SELECT @pid = ProductId, @qty_buy = Quantity FROM inserted
SELECT @qty_remain = Quantity FROM Inventory WHERE ProductId = @pid
IF (@qty_remain <= @qty_buy)
THROW 51000, N'Insufficient inventory!', 1
ELSE
BEGIN
INSERT INTO dbo.OrderDetails (OrderId, ProductId, SalePrice, Quantity, Total)
SELECT OrderId, ProductId, SalePrice, Quantity, Total FROM inserted
UPDATE Inventory SET Quantity = Quantity - @qty_buy WHERE ProductId = @pid
END
END
GO
CREATE TRIGGER tr_order_details_after_update
ON OrderDetails
AFTER UPDATE AS
BEGIN
INSERT INTO UpdateNotifications (OrderId, UpdateTime) SELECT OrderId, GETDATE() FROM inserted
END
GO
CREATE PROCEDURE sp_insert_order_details
@OrderId int, @ProductId int, @SalePrice money, @Quantity int, @total money
AS BEGIN
INSERT INTO dbo.OrderDetails (OrderId, ProductId, SalePrice, Quantity, Total)
VALUES (@OrderId, @ProductId, @SalePrice, @Quantity, @total)
END
GO
CREATE PROCEDURE sp_update_order_details_by_id
@OrderId int, @ProductId int, @SalePrice money, @Quantity int, @Total money
AS BEGIN
UPDATE dbo.OrderDetails
SET ProductId = @ProductId, SalePrice = @SalePrice, Quantity = @Quantity, Total = @total
WHERE OrderId = @OrderId
END
GO
次のオブジェクトは、機能的には移行前の状態と同等です。
CREATE TABLE OrderDetails
(
OrderId int not null PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 1048576),
ProductId int not null,
SalePrice money not null,
Quantity int not null,
Total money not null,
IsDeleted bit not null DEFAULT (0)
) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)
GO
CREATE TABLE Inventory
(
ProductId int not null PRIMARY KEY NONCLUSTERED,
Quantity int not null
) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)
GO
CREATE TABLE UpdateNotifications
(
OrderId int not null,
UpdateTime datetime2 not null
CONSTRAINT pk_updateNotifications PRIMARY KEY NONCLUSTERED (OrderId, UpdateTime)
) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)
GO
CREATE PROCEDURE sp_insert_order_details
@OrderId int, @ProductId int, @SalePrice money, @Quantity int, @total money
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'English')
DECLARE @qty_remain int
SELECT @qty_remain = Quantity FROM dbo.Inventory WHERE ProductId = @ProductId
IF (@qty_remain <= @Quantity)
THROW 51000, N'Insufficient inventory!', 1
ELSE
BEGIN
INSERT INTO dbo.OrderDetails (OrderId, ProductId, SalePrice, Quantity, Total)
VALUES (@OrderId, @ProductId, @SalePrice, @Quantity, @total)
UPDATE dbo.Inventory SET Quantity = Quantity - @Quantity WHERE ProductId = @ProductId
END
END
GO
CREATE PROCEDURE sp_update_order_details_by_id
@OrderId int, @ProductId int, @SalePrice money, @Quantity int, @Total money
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'English')
UPDATE dbo.OrderDetails
SET ProductId = @ProductId, SalePrice = @SalePrice, Quantity = @Quantity, Total = @total
WHERE OrderId = @OrderId
INSERT INTO dbo.UpdateNotifications (OrderId, UpdateTime) VALUES (@OrderId, GETDATE())
END
GO