暫且不論您爲什麼要這樣做的問題,動態操縱inserted
的DDL將不起作用,因爲inserted
和deleted
表只能在觸發器的代碼中訪問。動態SQL運行在它自己的執行上下文中(而不是它被調用的上下文),所以你會得到一個object not found
錯誤。
編輯:
假設這個問題涉及到類似主題的otherrecent的問題,這裏有接近使用觸發器在Data1
三分用表Field...
列這個問題的一種方式(但這個例子是可擴展的,在更多專欄上工作)。
觸發的工作原理是PIVOT
荷蘭國際集團的Fields
表合併到一列每ObjectId
,然後加入此到inserted
表和插入Field
Ñ值與相關Fields.NotNull
值進行比較。該代碼將NotNull
值轉換爲字符串以便於理解,但您可以同樣使用bit
值。
該代碼將在同一批次中支持INSERT
或UPDATE
多於一個值ObjectId
。
--create schema
CREATE TABLE fields (ObjectId int , FieldNumber int , NotNull bit)
INSERT fields (ObjectId, FieldNumber, NotNull)
VALUES
(100,1,1),(100,2,1),(100,3,0),
(200,1,1),(200,2,1),(200,3,1)
CREATE TABLE Data1 (ObjectId int , Field1 int ,Field2 int ,Field3 int)
GO
CREATE TRIGGER [dbo].[tr_INSERT_UPDATE_Data1]
ON [dbo].[Data1]
AFTER INSERT, UPDATE
AS
IF EXISTS (SELECT *
FROM inserted AS i
JOIN ( SELECT ObjectId, Field1,Field2,Field3
FROM (
SELECT ObjectId, CONCAT('Field',FieldNumber) AS colName,
CASE WHEN NotNull = 1 THEN 'NOT NULL' ELSE 'NULL' END AS NotNull
FROM fields
) AS s
PIVOT
(
MAX(NotNull)
FOR colName IN (Field1,Field2,Field3)
) AS p
) AS f
ON f.ObjectId = i.ObjectId
WHERE (f.Field1 = 'NOT NULL' AND i.Field1 IS NULL)
OR (f.Field2 = 'NOT NULL' AND i.Field2 IS NULL)
OR (f.Field3 = 'NOT NULL' AND i.Field3 IS NULL)
)
THROW 50001, 'Cannot insert NULL into a field marked NOT NULL',1
GO
--Tests
--1 insert good data
INSERT Data1 (ObjectId, Field1,Field2,Field3)
VALUES (100,1,2,3)
--2 NULL blocked for ObjectId 100, Field1 NULL
INSERT Data1 (ObjectId, Field1,Field2,Field3)
VALUES (100,NULL,2,3)
--3 NULL blocked for ObjectId 100, Field2 NULL
INSERT Data1 (ObjectId, Field1,Field2,Field3)
VALUES (100,1,NULL,3)
--4 insert good data (Field3 NULL permitted)
INSERT Data1 (ObjectId, Field1,Field2,Field3)
VALUES (100,1,2,NULL)
--4 multiple ObjectIds supported - NULL blocked for all ObjectId 200 fields
INSERT Data1 (ObjectId, Field1,Field2,Field3)
VALUES (100,1,2,3),
(200,NULL,NULL,NULL)
爲什麼你想改變插入的表?把它想象成一個特殊的表變量,sql維護着保存插入或更新到表中的新值。改變它不會改變DML操作,並且改變該表中的數據不會改變DML操作所在的表。另外,如果它是NULL,則將其設置爲NOT NULL,如果允許的話,只會引發錯誤。似乎真正的問題是我需要做X(例如,確保插入的值不爲空?)..... – Matt
這聽起來像一個可怕的壞主意,以改變你的數據庫模式**在飛行**內觸發.......你需要重新思考你的方法,這不是一個處理這些要求的好方法! –
這確實是一個**可怕的**想法。你正在試圖解決的實際問題是什麼?爲什麼需要動態更改表的NOT NULL屬性? Plus:只有觸發器的運行時才存在'inserted'「table」(變量)。所以修改它沒有意義。 –