简体   繁体   English

创建触发器的问题。 每个表中的列名必须是唯一的。 微软SQL

[英]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:是因为它可能:

  • You should specify the schema name everywhere.您应该在任何地方指定架构名称。
  • Don't pull the most recent table from 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命令相关的信息。
  • Object names can be up to nvarchar(128) , you can use the alias sysname Object 名称最多可以为nvarchar(128) ,您可以使用别名sysname
  • Use QUOTENAME to quote object names correctly.使用QUOTENAME正确引用 object 名称。
  • The DML trigger needs to join on the primary key, which may not be 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.

相关问题 每个表中的列名必须唯一。 在SQL Server中将表数据从一个表复制到另一个表时 - Column names in each table must be unique. while copy table data from one table to another in sql server 每个表中的列名必须唯一。 表&#39;CONSUMO.DBO.ARCHIVOBOL082017&#39;中的列名&#39;MntNeto&#39;被多次指定 - Column names in each table must be unique. Column name 'MntNeto' in table 'CONSUMO.DBO.ARCHIVOBOL082017' is specified more than once 错误:每个表中的列名必须是唯一的 - Error: Column names in each table must be unique 每个表中的列名必须是唯一的例外 - Column names in each table must be unique exception 创建视图错误列名称必须唯一 - Creating view error column names must be unique 如何使用触发器在表列中插入日期。 (ORACLE) - How to insert date in a table column with a trigger. (ORACLE) Create VIEW error Column names in each view or function must be unique - Create VIEW error Column names in each view or function must be unique MySQL触发器。 如何在有限的时间内存储表中的每一行数据? - MySQL trigger. How to store each row of data in table for a limited time? 无法创建视图,但其他语句运行正常。 每个视图中的列名或 function 必须是唯一的 - Unable to Create View but otherwise statement is running OK. Column names in each view or function must be unique 列“ ID”被限制为唯一。 价值已经存在 - Column 'ID' is constrained to be unique. Value is already present
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM