如何动态更改触发器中插入的表

时间:2016-12-02 03:31:03

标签: sql sql-server sql-server-2016

我试图在触发器中动态更改插入的表。我需要动态创建一个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

1 个答案:

答案 0 :(得分:1)

不考虑为什么要这样做的问题,动态操作inserted的DDL将不起作用,因为inserteddeleted表只能在代码中访问触发。动态SQL在其自己的执行上下文(而不是调用它的上下文)中运行,因此您收到object not found错误。

修改:

假设此问题与您关于类似主题的other recent个问题有关,这里是使用Data1表上有三个Field...列的触发器来解决此问题的一种方法(但是此示例可扩展以处理更多列)。

触发器按PIVOTFields个表运行一个列,然后将其连接到ObjectId表,并比较插入的inserted表的值带有相关Field值的1}} n 。该代码会将Fields.NotNull值转换为字符串,以便于理解,但您也可以使用NotNull值。

该代码将在同一批次中支持bitINSERT多个UPDATE值。

ObjectId