[英]Problem with creating trigger. Column names in each table must be unique. MsSQL
I have this trigger which has to work on CREATE_TABLE
and should check if there is column updated_at
in table.我有这个触发器,它必须在CREATE_TABLE
上工作,并且应该检查表中是否有列updated_at
。 If not, create one and set another trigger.如果没有,请创建一个并设置另一个触发器。
This is how it looks like:这是它的样子:
CREATE TRIGGER UpdatedAtFiled ON DATABASE
FOR CREATE_TABLE
AS
BEGIN
DECLARE @createdTableName VARCHAR(50), @column VARCHAR(50), @triggerName VARCHAR(50), @execTrigger VARCHAR(300), @sqlcmd VARCHAR(100), @ColumnWasCreated INT, @Itr INT;
SET @Itr = 0;
SET @ColumnWasCreated = 0;
SELECT @createdTableName = name FROM sys.Tables ORDER BY create_date
WHILE (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @createdTableName) > @Itr
BEGIN
SELECT @column = COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @createdTableName ORDER BY COLUMN_NAME OFFSET @Itr ROWS FETCH NEXT 1 ROWS ONLY;
SET @triggerName = 'TRIGGER_' + CONVERT(VARCHAR(20), @createdTableName);
SET @execTrigger = 'CREATE TRIGGER ' + @triggerName + ' ON ' + @createdTableName +
' FOR UPDATE as UPDATE T SET updated_at = GETDATE() ' + ' FROM ' +
@createdTableName + ' AS T JOIN inserted AS i ON T.id = i.id;';
IF (@column != 'updated_at' AND @ColumnWasCreated <= 0)
SET @sqlcmd = 'ALTER TABLE ' + @createdTableName + ' ADD updated_at DATETIME NOT NULL DEFAULT GETDATE()';
EXEC(@sqlcmd)
EXEC(@execTrigger)
SET @ColumnWasCreated = 1;
SET @Itr = @Itr + 1;
END
END
And every time I create table I get an error:每次创建表时都会出现错误:
CREATE TABLE test(id INT PRIMARY KEY IDENTITY (1, 1), name VARCHAR(20))
[S0004][2705] Line 1: Column names in each table must be unique. [S0004][2705] 第 1 行:每个表中的列名必须是唯一的。 Column name 'updated_at' in table 'test' is specified more than once.`表“test”中的列名“updated_at”被指定了多次。`
I guess, there is problem in this conditional, but I'm not sure:我想,这个条件有问题,但我不确定:
IF (@column != 'updated_at' AND @ColumnWasCreated <= 0)
I literally can't find the error.我真的找不到错误。 What's wrong?怎么了? How can I fix that?我该如何解决?
I will preface this by saying that I think using a trigger for this is a bad idea.我会先说我认为为此使用触发器是一个坏主意。 There are a number of other solutions to this, not least just making sure you do this correctly for each table in the first place.对此还有许多其他解决方案,尤其是首先要确保为每个表正确执行此操作。
Be that as it may:是因为它可能:
sys.tables
, instead use EVENTDATA
to get the info which relates to the particular CREATE TABLE
command that was executed.不要从sys.tables
中提取最新的表,而是使用EVENTDATA
来获取与执行的特定CREATE TABLE
命令相关的信息。nvarchar(128)
, you can use the alias sysname
Object 名称最多可以为nvarchar(128)
,您可以使用别名sysname
QUOTENAME
to quote object names correctly.使用QUOTENAME
正确引用 object 名称。id
and may be more than one column. DML 触发器需要加入主键,主键可能不是id
,可能不止一列。CREATE TRIGGER UpdatedAtFiled ON DATABASE
FOR CREATE_TABLE
AS
DECLARE @tableName sysname = EVENTDATA().value('(/EVENT_INSTANCE/ObjectName)[1]','sysname');
DECLARE @schemaName sysname = EVENTDATA().value('(/EVENT_INSTANCE/SchemaName)[1]','sysname');
DECLARE @sql nvarchar(max);
IF NOT EXISTS (SELECT 1
FROM sys.columns c
JOIN sys.tables t ON t.object_id = c.object_id
JOIN sys.schemas s ON s.schema_id = t.schema_id
WHERE s.name = @schemaName
AND t.name = @tableName
AND c.name = 'updated_at')
BEGIN
SET @sql = '
ALTER TABLE ' + QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName) + '
ADD updated_at DATETIME NOT NULL DEFAULT GETDATE();
';
EXEC sp_executesql @sql;
END
SET @sql = '
CREATE TRIGGER ' + QUOTENAME('TRIGGER_' + @tableName) + ' ON ' + QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName) + '
FOR UPDATE AS
IF @@ROWCOUNT = 0
RETURN;
UPDATE T
SET updated_at = GETDATE()
FROM ' + QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName) + ' AS T
JOIN inserted AS i ON ('
+ (
SELECT STRING_AGG('T.' + QUOTENAME(c.name) + ' = i.' + QUOTENAME(c.name), ' AND ')
FROM sys.tables t
JOIN sys.schemas s ON s.schema_id = t.schema_id
JOIN sys.indexes i ON i.object_id = t.object_id
JOIN sys.index_columns ic ON ic.object_id = i.object_id
AND ic.index_id = i.index_id
JOIN sys.columns c ON t.object_id = c.object_id
AND c.column_id = ic.column_id
WHERE i.is_primary_key = 1
)
+ ');
';
EXEC sp_executesql @sql;
GO
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.