动态插入语句需要返回插入的ID

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态插入语句需要返回插入的ID相关的知识,希望对你有一定的参考价值。

我有一个触发器我已经完成,在触发操作期间,我将一些记录插入主表中,然后我需要使用主表中的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
答案

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语句中返回的值。

以上是关于动态插入语句需要返回插入的ID的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 在函数或存储过程中执行一条插入语句并返回主键ID值

mysql xdevapi nodejs:返回插入的行auto_increment id

使用SQLServer2005插入一条数据时返回当前插入数据的ID

sql server返回插入记录的ID(多条记录)

Mysql批量插入返回Id错乱(原因分析)

oracle数据库,表中有id(自增字段,主键), insert 语句插入一条记录后要求,返回当前插入记录的id値。