我有一个已经完成的触发器,并且在触发器操作期间,我将一些记录插入到主表中,然后需要使用主表中的ID将一些记录插入到明细表中。
我不确定插入后如何从主表中获取ID,以便可以在明细表中使用。这是我的触发代码:
IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME= 'DATA_HIL_Master')
BEGIN
DECLARE @sql NVARCHAR(MAX),
@TABLE_NAME sysname
SET NOCOUNT ON
SELECT @TABLE_NAME = MIN(TABLE_NAME)
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME != 'sysdiagrams'
AND TABLE_NAME != 'Audit'
AND TABLE_NAME = 'ADM_Gate'
WHILE @TABLE_NAME IS NOT NULL
BEGIN
EXEC('IF OBJECT_ID (''' + @TABLE_NAME + '_ChangeTracking'', ''TR'') IS NOT NULL DROP TRIGGER ' + @TABLE_NAME + '_ChangeTracking')
SELECT @sql =
'create trigger ' + @TABLE_NAME + '_ChangeTracking on ' + @TABLE_NAME + ' for insert, update, delete
as
declare @bit int ,
@field int ,
@maxfield int ,
@char int ,
@fieldname varchar(128) ,
@TableName varchar(128) ,
@PKCols varchar(1000) ,
@sql nvarchar(max),
@Type int ,
@PKFieldSelect varchar(1000),
@PKValueSelect varchar(1000),
@MasterId nvarchar(1)
select @TableName = ''' + @TABLE_NAME + '''
if exists (select * from inserted)
if exists (select * from deleted)
select @Type = 2
else
select @Type = 3
else
select @Type = 1
select * into #ins from inserted
select * into #del from deleted
select @PKCols = coalesce(@PKCols + '' and'', '' on'') + '' i.'' + c.COLUMN_NAME + '' = d.'' + c.COLUMN_NAME
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE c on c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME and c.TABLE_NAME = pk.TABLE_NAME
where pk.TABLE_NAME = @TableName
and CONSTRAINT_TYPE = ''PRIMARY KEY''
select @PKFieldSelect = coalesce(@PKFieldSelect + ''+'', '''') + '''''''' + COLUMN_NAME + ''''''''
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE c on c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME and c.TABLE_NAME = pk.TABLE_NAME
WHERE pk.TABLE_NAME = @TableName
AND CONSTRAINT_TYPE = ''PRIMARY KEY''
select @PKValueSelect = coalesce(@PKValueSelect+''+'','''') + ''convert(varchar(100), coalesce(i.'' + COLUMN_NAME + '',d.'' + COLUMN_NAME + ''))''
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE c on c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME and c.TABLE_NAME = pk.TABLE_NAME
where pk.TABLE_NAME = @TableName
and CONSTRAINT_TYPE = ''PRIMARY KEY''
select @sql = ''insert DATA_HIL_Master (OperationType, ReferenceTable, ReferenceId, Last_UserId_Log, Last_WorkstationId_Log, Last_DateTime_Log)''
if @Type = 1
select @sql = @sql + '' select 1 ''
if @Type = 2
select @sql = @sql + '' select 2 ''
if @Type = 3
select @sql = @sql + '' select 3''
select @sql = @sql + '', '''''' + @TableName + ''''''''
select @sql = @sql + '','' + @PKValueSelect
select @sql = @sql + '',convert(varchar(1000),i.Last_UserId_Log)''
select @sql = @sql + '',convert(varchar(1000),i.Last_WorkstationId_Log)''
select @sql = @sql + '',convert(varchar(1000),i.Last_DateTime_Log)''
select @sql = @sql + '' from #ins i full outer join #del d''
select @sql = @sql + @PKCols
EXECUTE sp_executesql @sql
select @MasterId
select @field = 0,
@maxfield = max(ORDINAL_POSITION)
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = @TableName
while @field < @maxfield
begin
select @field = min(ORDINAL_POSITION)
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = @TableName
and ORDINAL_POSITION > @field
select @bit = (@field - 1 )% 8 + 1
select @bit = power(2,@bit - 1)
select @char = ((@field - 1) / 8) + 1
if substring(COLUMNS_UPDATED(),@char, 1) & @bit > 0 or @Type in (1,3)
begin
select @fieldname = COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @TableName and ORDINAL_POSITION = @field
select @sql = ''insert data_HIL_Detail (MasterId, ColumnName, OriginalValue, ModifiedValue)''
select @sql = @sql + '' select convert(varchar(1000),'' + @MasterId + '')''
select @sql = @sql + '','''''' + @fieldname + ''''''''
select @sql = @sql + '', convert(varchar(1000),d.'' + @fieldname + '')''
select @sql = @sql + '', convert(varchar(1000),i.'' + @fieldname + '')''
select @sql = @sql + '' from #ins i full outer join #del d''
select @sql = @sql + @PKCols
select @sql = @sql + '' where i.'' + @fieldname + '' <> d.'' + @fieldname
select @sql = @sql + '' or (i.'' + @fieldname + '' is null and d.'' + @fieldname + '' is not null)''
select @sql = @sql + '' or (i.'' + @fieldname + '' is not null and d.'' + @fieldname + '' is null)''
select @sql
end
END '
SELECT @sql
EXEC(@sql)
SELECT @TABLE_NAME = MIN(TABLE_NAME)
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME> @TABLE_NAME
AND TABLE_TYPE= 'BASE TABLE'
AND TABLE_NAME!= 'sysdiagrams'
AND TABLE_NAME!= 'Audit'
AND TABLE_NAME = 'ADM_Gate'
END
END
答案 0 :(得分:0)
WEI_DBA上面提到了SCOPE_IDENTITY()
,但是有一个复杂性会影响您,因为sp_executeSQL
语句执行的代码实际上与触发器不在同一范围内。但是,通过在sp_executeSQL
调用中使用OUTPUT参数,可以轻松解决此问题。您使用NVARCHAR(1)
数据类型作为ID,然后将其强制转换为VARCHAR(1000)
并没有多大意义,但在本示例中,我将使用它。考虑一下您的触发器中的这段代码摘录。我将其重写为使用也称为@MasterID的输出参数:
select @sql = @sql + '' from #ins i full outer join #del d''
select @sql = @sql + @PKCols + ''; SET @MasterId = SCOPE_IDENTITY() -- Or whatever your ID is''
DECLARE @Parms nvarchar(40)
SET @Parms = N''@MasterId Nvarchar(1) OUTPUT'';
EXECUTE sp_executesql @sql, @Parms, @MasterId = @MasterId Output
-- select @MasterId -- @MasterId is set to the @MasterId returned by sp_executesql
这时,@ MasterId具有动态SQL语句中代码返回的值。