2016-12-02 56 views
0

我試圖在觸發器中動態更改插入的表格。我需要動態地創建一個NOT NULL約束。我查詢一個Fields表來檢索NOT NULL字段。然後,我創建一個基於NOT NULL字段的ALTER DDL查詢。當我執行ALTER語句時,它給了我這個錯誤。如何在動態觸發器中更改插入的表格

找不到「插入」,因爲它不存在或您 沒有權限

這裏的對象是我一起工作的代碼:

ALTER TRIGGER [dbo].[tr_INSERT_UPDATE_Data1] 
ON [dbo].[Data1] 
AFTER INSERT, UPDATE 
as 

DECLARE @ObjectId INT 
DECLARE @AlterQueryStr NVARCHAR(MAX) 

SELECT TOP 1 @ObjectId = object_id FROM inserted 

SELECT FieldNumber 
INTO #NotNullFieldNumbers 
FROM dbo.Fields 
WHERE ObjectId = @ObjectId AND NotNull = 1 

IF EXISTS(SELECT * FROM #NotNullFieldNumbers) 
BEGIN 
    DECLARE @AlterTableTemp NVARCHAR(MAX) 

    SELECT @AlterTableTemp = STUFF((SELECT ';' + 'ALTER TABLE inserted ALTER COLUMN Field' + cast([FieldNumber] as VARCHAR(100)) + ' VARCHAR(MAX) NOT NULL' 
       FROM #NotNullFieldNumbers 
       FOR 
       XML PATH('') 
      ), 1, 1, '') 

    EXEC sp_executesql @AlterTableTemp 

END 
+2

爲什麼你想改變插入的表?把它想象成一個特殊的表變量,sql維護着保存插入或更新到表中的新值。改變它不會改變DML操作,並且改變該表中的數據不會改變DML操作所在的表。另外,如果它是NULL,則將其設置爲NOT NULL,如果允許的話,只會引發錯誤。似乎真正的問題是我需要做X(例如,確保插入的值不爲空?)..... – Matt

+5

這聽起來像一個可怕的壞主意,以改變你的數據庫模式**在飛行**內觸發.......你需要重新思考你的方法,這不是一個處理這些要求的好方法! –

+3

這確實是一個**可怕的**想法。你正在試圖解決的實際問題是什麼?爲什麼需要動態更改表的NOT NULL屬性? Plus:只有觸發器的運行時才存在'inserted'「table」(變量)。所以修改它沒有意義。 –

回答

1

暫且不論您爲什麼要這樣做的問題,動態操縱inserted的DDL將不起作用,因爲inserteddeleted表只能在觸發器的代碼中訪問。動態SQL運行在它自己的執行上下文中(而不是它被調用的上下文),所以你會得到一個object not found錯誤。

編輯:

假設這個問題涉及到類似主題的otherrecent的問題,這裏有接近使用觸發器在Data1三分用表Field...列這個問題的一種方式(但這個例子是可擴展的,在更多專欄上工作)。

觸發的工作原理是PIVOT荷蘭國際集團的Fields表合併到一列每ObjectId,然後加入此到inserted表和插入FieldÑ值與相關Fields.NotNull值進行比較。該代碼將NotNull值轉換爲字符串以便於理解,但您可以同樣使用bit值。

該代碼將在同一批次中支持INSERTUPDATE多於一個值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) 
相關問題