MSSQL 中的 INSERT 触发器:按变量的目标表

Posted

技术标签:

【中文标题】MSSQL 中的 INSERT 触发器:按变量的目标表【英文标题】:INSERT Trigger in MSSQL: destination table by Variable 【发布时间】:2014-09-18 09:19:13 【问题描述】:

多个程序/进程将它们的历史记录插入一个(非常大的)历史记录表 (tbl_History)。我无法改变这一点。我必须在插入时将它们分类到“正确的”历史表中。这些不同的历史表确实已经存在。那我就不创作了。但是通过参数“his_ID”我可以检查,女巫表是正确的目标表。

所以我在这个表中添加了一个触发器。这个有效:

CREATE TRIGGER [dbo].[Trigger_tbl_History_Insert]
ON [dbo].[tbl_History]
AFTER INSERT
AS
BEGIN

    INSERT INTO [tbl_Historyef33894e-3fda-4833-b1e6-efa5cb9ce8ee] SELECT * FROM inserted;
END

但现在我想通过新插入行中的变量来决定目标表。我是这么想的:

CREATE TRIGGER [dbo].[Trigger_tbl_History_Insert]
ON [dbo].[tbl_History]
AFTER INSERT
AS

BEGIN
    DECLARE @hisID varchar(max);
    SELECT @hisID = inserted.his_ID FROM inserted;
    INSERT INTO [tbl_History + @hisID ] SELECT * FROM inserted;
END

显然它不是这样工作的。 :-) 有没有办法做到这一点?

以下方法不能完全正确地工作:

CREATE TRIGGER [dbo].[Trigger_tbl_History_Insert]
ON [dbo].[tbl_History]
AFTER INSERT
AS

BEGIN
    DECLARE @hisID varchar(max);
    SELECT @hisID = inserted.his_ID FROM inserted;
    EXEC ('INSERT INTO tbl_History' + @hisID + '  SELECT * FROM inserted');
END

创建错误:“'-' 附近的语法不正确”

CREATE TRIGGER [dbo].[Trigger_tbl_History_Insert]
ON [dbo].[tbl_History]
AFTER INSERT
AS

BEGIN
    DECLARE @hisID varchar(max);
    SELECT @hisID = inserted.his_ID FROM inserted;
    EXEC ('INSERT INTO [tbl_History' + @hisID + ']  SELECT * FROM inserted');
END

创建错误:“无效的对象名称'插入'。”

【问题讨论】:

你的意思是在每次插入后你想将数据保存到 [tbl_History + @hisID ] 对吗??如果您的回答是肯定的,那么这意味着在每次插入时它都会根据 id 创建新表并保存数据!!! 我不确定你是否可以使用,但将Insert放入动态代码中...... 首先是,然后不是。 ;-) 它不会创建新表。该表确实已经存在。几个程序/进程将它们的历史插入到一个单一的历史表中。我无法改变这一点。我必须在插入时将它们分类到“正确的”历史表中。我现在会在帖子中添加这个解释。 @Tagamoga:你的意思是说 [tbl_History123] 已经创建或存在。您只需要通过正确的触发器将数据插入其中???。这里 123 是您的 @hisID 是的,没错。 @hisID 由插入的.his_ID 填充 【参考方案1】:

好吧,在这里我假设名为 [tbl_History123] 的表将存在,其中 123 是变量 @hisID。所以在这种情况下,你可以这样做 -

CREATE TRIGGER [dbo].[Trigger_tbl_History_Insert]
ON [dbo].[tbl_History]
AFTER INSERT
AS

BEGIN
    DECLARE @hisID varchar(max);
    SELECT @hisID = inserted.his_ID FROM inserted;

    EXEC ('INSERT INTO tbl_History' + @hisID + '  SELECT * FROM inserted');

    -- OR you can also do this
    EXEC (
        'SELECT * 
         INTO tbl_History' + @hisID + '
         FROM inserted'
        );

END

已编辑

好的,创建另一个单独的表 - tmpHistoryForID 与您的 [tbl_History123] 具有相同的架构。这用作中介表。所以在触发器中首先将数据插入到这个表中,然后从这个表中插入到你的 [tbl_History123] 表中。像这样-

CREATE TRIGGER [dbo].[Trigger_tbl_History_Insert]
    ON [dbo].[tbl_History]
    AFTER INSERT
    AS

BEGIN
        DECLARE @hisID varchar(max);
        SELECT @hisID = inserted.his_ID FROM inserted;

        INSERT INTO dbo.tmpHistoryForID 
            SELECT * FROM inserted

        EXEC ('INSERT INTO tbl_History' + @hisID + '  SELECT * FROM dbo.tmpHistoryForID');

        TRUNCATE TABLE dbo.tmpHistoryForID

END

【讨论】:

非常感谢您的帮助,但仍然没有运行。不幸发生以下错误:“'-' 附近的语法不正确。”当我将 EXEC 行更改为 'EXEC ('INSERT INTO [tbl_History' + @hisID + '] SELECT * FROM inserted');'它告诉我:“无效的对象名称'插入'。”我也会将其添加到帖子中... EXECEXECUTE 语句用于实现 SQL Server 在第一次解析时不允许的操作。实际上,SQL Server 会解析您的指令并检查是否有任何错误。因为您的表tblHistory + @hisID 不存在,即[tblHistory + @hidID],所以它不允许您使用。因此,使用EXECEXECUTE 命令将解析与“运行时”不同。 表格确实存在。否则“插入 [tbl_Historyef33894e-3fda-4833-b1e6-efa5cb9ce8ee] SELECT * FROM 插入;”不会工作。 @Tagamoga:我已经更新了我的答案。查看编辑部分 我爱你!但请在您的语句中添加“[]”,因为 MSSQL 不喜欢表名 bg 中的“-”:“EXEC ('INSERT INTO [tbl_History' + @userID + '] SELECT * FROM dbo. tbl_tmpHistoryForID');"【参考方案2】:

您无法使用动态 SQL 查询访问魔术表。在执行动态查询之前,将记录放入临时表中。下面是触发器的代码。

CREATE TRIGGER [dbo].[Trigger_tbl_History_Insert]
ON [dbo].[tbl_History]
AFTER INSERT
AS

BEGIN
    DECLARE @ID int;
    DECLARE @Qry varchar(max)
    SELECT @ID = inserted.ID FROM inserted;
    select * into #tmp from inserted
    SET @Qry=CONCAT('INSERT INTO tbl_History' , @ID ,'  SELECT * FROM #tmp')
    EXEC (@Qry)
END

【讨论】:

以上是关于MSSQL 中的 INSERT 触发器:按变量的目标表的主要内容,如果未能解决你的问题,请参考以下文章

mssql如何将一个数据库中的表同步到另一个数据库中 做成事务

使用 MSSQL 中的触发器跟踪和存储新旧值

如果值符合条件,则在 INSERT 之后更改列值?

mssql 的 存储过程 变量赋值问题

MSSQL自增序列删除数据后如何保持完整

MSsql数据库中的表级通知[关闭]