SQL Server 2012 - 触发器:操作数类型冲突:int与唯一标识符不兼容

时间:2017-09-04 09:45:17

标签: sql sql-server tsql sql-server-2012

我正在编写一个审计触发器,它将表中发生的每个更改保存在另一个表中。但是当我尝试更改Users表时,我收到此错误:

  

操作数类型碰撞:int与唯一标识符

不兼容

Users表包含uniqueidentifier列等。

以下是发生错误的代码部分:

ALTER TRIGGER [dbo].[UsersLogger] 
ON [dbo].[Users] 
FOR INSERT, DELETE, UPDATE
AS 
BEGIN
    DECLARE @audit_oldvalue sql_variant;
    DECLARE @audit_value sql_variant;
    DECLARE @audit_field varchar(100);
    DECLARE @sql nvarchar(max);
    DECLARE @ParmDefinition nvarchar(max) ;
    DECLARE @OutString varchar(max) ;
    DECLARE @converted_uid nvarchar(50);

    DECLARE @qid int ;
    DECLARE @Cinfo VARBINARY(128)  

    SELECT @Cinfo = Context_Info()  

    IF @Cinfo = 0x55555  
         RETURN  

    DECLARE @Action as char(1);
    SET @Action = (CASE WHEN EXISTS(SELECT * FROM INSERTED)
                         AND EXISTS(SELECT * FROM DELETED)
                        THEN 'U'  -- Set Action to Updated.
                        ELSE NULL -- Skip. It may have been a "failed delete".   
                    END)

    SET @OutString = '' 

    SELECT * 
    INTO #tempTrigT 
    FROM 
        (SELECT * 
         FROM deleted 
         WHERE @Action IN ( 'U', 'D')) A 
    UNION 
    (SELECT * 
     FROM inserted 
     WHERE @Action = 'I') 

    SET @sql = '' 

if @Action = 'U'
BEGIN
Select @sql = @sql + 'Case when IsNull(i.[' + Column_Name +  
'],0) = IsNull(d.[' + Column_name + '],0) then ''''  
 else ' + quotename(Column_Name, char(39)) + ' + '',''' + ' end +' 
from information_schema.columns  
where table_name = 'Users' and column_name <>'rowguid' and column_name <>'modifieddate'
set @ParmDefinition = '@OutString varchar(max) OUTPUT' 
set @sql = 'Select @OutString = '  
+ Substring(@sql,1 , len(@sql) -1) +  
' From dbo.Users i  ' 
+ ' inner join #tempTrigT d on 
i.id = d.id'  
exec sp_executesql @sql, @ParmDefinition, @OutString OUT 

END

 DECLARE @Items VARCHAR(max)

 set @Items = @OutString;

 DECLARE @Item VARCHAR(50)
 DECLARE @Pos INT
 DECLARE @Loop BIT
 SELECT @Loop = CASE WHEN LEN(@OutString) > 0 THEN 1 ELSE 0 END
 WHILE (SELECT @Loop) = 1
 BEGIN
 SELECT @Pos = CHARINDEX(',', @OutString, 1)
 IF @Pos > 0
 BEGIN
 SELECT @Item = SUBSTRING(@OutString, 1, @Pos - 1)
 SELECT @OutString = SUBSTRING(@OutString, @Pos + 1, LEN(@OutString) - @Pos)

IF (TRY_CONVERT(UNIQUEIDENTIFIER, @Item) is not null)
begin
    select @Item = convert(nvarchar(50), @Item)
end

1 个答案:

答案 0 :(得分:1)

如果我不得不猜测,我会责备它

Select @sql = @sql + 'Case when IsNull(i.[' + Column_Name +  
'],0) = IsNull(d.[' + Column_name + '],0) then ''''  
 else ' + quotename(Column_Name, char(39)) + ' + '',''' + ' end +' 
from information_schema.columns  
where table_name = 'Users' and column_name <>'rowguid' and column_name <>'modifieddate'

这是因为您在ISNULL列上执行UNIQUEIDENTIIFIER并将值设置为INT。您可以从ISNULL(i.[ColumnName], 0)更改为ISNULL(i.[ColumnName], '')但是,假设表中的所有列都是字符串适用的数据类型。否则,您可以使用该表中的ISNULL列对[DATA_TYPE]函数的替换值执行一些条件逻辑。