0

J'ai plusieurs tables avec des colonnes nvarchar (max). Je construis un trigger qui essaie de stocker les cellules dans sql_Variant. Nvarchar (max) ne peut pas être stocké dans sql_variant. Comment puis-je vérifier si c'est nvarchar (max) et puis le convertir en nvarchar (4000) afin que je puisse éviter cela?Déclencheur SQL: modification de la taille de nvarchar

EDIT: Très probablement l'erreur se produit ici:

set @sql = 'select @audit_oldvalue=[' [email protected] +'] from #tempTrigT'; 

Parce que @audit_oldvalue est sql_variant mais [ '+ @ + article'] de #tempTrigT peut être nvarchar (max)

Si je modifier quelque chose dans la table d'entrée, je reçois cette erreur:

operand type clash nvarchar(max) is incompatible with sql_variant

Tables Structure:

table d'entrée

enter image description here

table de sortie

enter image description here

code où je veux convertir:

Select * into #tempTrigT from (select * from deleted where @Action in ('U','D')) A UNION (select * from inserted where @Action ='I') 

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 = 'Forms' and column_name <>'rowguid' and column_name <>'modifieddate' 
--Define output parameter 
set @ParmDefinition = '@OutString varchar(max) OUTPUT' 
--Format sql 
set @sql = 'Select @OutString = ' 
+ Substring(@sql,1 , len(@sql) -1) + 
' From dbo.Forms i ' --Will need to be updated for target schema 
+ ' inner join #tempTrigT d on 
i.id = d.id' --Will need to be updated for target schema 
--Execute sql and retrieve desired column list in output parameter 
exec sp_executesql @sql, @ParmDefinition, @OutString OUT 


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) 
---------------------------------- 

set @audit_field = @Item; 

set @sql = 'select @audit_oldvalue=[' [email protected] +'] from #tempTrigT'; --ERROR LINE 
EXEC SP_EXECUTESQL @sql,N'@audit_oldvalue sql_variant OUTPUT',@audit_oldvalue OUTPUT -- If inserted @audit_oldvalue gets the new value 

set @sql = 'select @audit_value=i.[' [email protected] +'] from dbo.Forms i inner join #tempTrigT d on i.id = d.id'; 
EXEC SP_EXECUTESQL @sql,N'@audit_value sql_variant OUTPUT',@audit_value OUTPUT 


if @Action = 'U' 
begin 
    insert into [dbo].[AuditTrailForms]([TSid],[TSField],[OldValue],[NewValue],[changedate],[Change_Action],[Change_user],[Columns_Updated]) 
    select id,@audit_field, @audit_oldvalue, @audit_value,getdate(),@Action, coalesce(ModifiedBy,suser_name()), @Items 
    from inserted 

end 

    END 
ELSE 
BEGIN 
SELECT @Item = @OutString 
SELECT @Loop = 0 
END 
END 
+0

Quels sont les dbms que vous utilisez? – jarlh

+0

@jarih sql server 2012 – aggicd

+0

Avez-vous essayé "CONVERT (nvarchar (4000), @nvarcharmaxparam)"? –

Répondre

1

Vous devriez être en mesure de jeter tout comme VARCHAR (4000).

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

Ou si vous voulez faire ce que pour ces colonnes (je ne crois pas que ce serait un problème à moins que pour des raisons de performance).

Select @sql = @sql + 'Case when IsNull(' 
    + CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN 'CAST(' ELSE '' END 
    + 'i.[' + Column_Name + ']' 
    + CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN ' AS VARCHAR(4000))' ELSE '' END + 
    ',0) = IsNull(' 
    + CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN 'CAST(' ELSE '' END 
    + 'd.[' + Column_name + ']' 
    + CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN ' AS VARCHAR(4000))' ELSE '' END + 
    + ',0) then '''' else ' 
    + quotename(Column_Name, char(39)) + ' + '',''' + ' end +' 
from information_schema.columns 
where table_name = 'Forms' and column_name <>'rowguid' and column_name <>'modifieddate' 
+0

OP a posté des questions concernant ce morceau de code un certain nombre de fois bien que différentes questions, mais n'a pas accepté une réponse dans tout jusqu'à présent (que j'ai vu). Je ne sais pas si OP est clair sur ce qui est réellement nécessaire. (Excuses si pas au bon endroit, pas assez de rep pour ne pouvoir commenter que sur mes propres messages) – PreQL

+0

merci pour vos réponses. J'ai posé différentes questions parce qu'il y avait dans le même morceau de code mais un sujet différent. Bien sûr, j'ai accepté les questions. – aggicd

+0

J'ai testé le 2ème extrait mais je reçois la même erreur à nouveau. Je ne veux pas tout convertir dans VARCHAR (4000) c'est pourquoi j'ai choisi l'extrait # 2 – aggicd