【问题标题】:Get identity after Instead of insert trigger在代替插入触发器之后获取身份
【发布时间】:2017-01-12 17:19:37
【问题描述】:

我正在使用 Hibernate 和 MSSQL 服务器编写与现有数据库集成的软件。我需要插入表上有一个instead of insert 触发器,它搞砸了@@Identity,这意味着在Hibernate 的save 上我无法获得插入行的ID。我无法控制触发器(无法修改)。我看到this的问题,但它涉及程序,我的触发器没有,所以我认为我的问题足够不同。我无法发布整个触发器,但希望我可以发布足够多的内容来表达观点:

CREATE TRIGGER TrigName ON TableName
INSTEAD OF INSERT
AS
SET XACT_ABORT ON
BEGIN TRANSACTION
-- several DECLARE, SET statements
-- a couple of inserts into other tables for business logic
-- plain T-SQL statements without procedures or functions
...

-- this is the actual insert that i need to perform
-- to be honest, I don't quite understand how INSERTED table 
-- was filled with all necessary columns by this point, but for now
-- I accept it as is (I am no SQL pro...)
INSERT INTO ClientTable (<columns>)
SELECT <same columns> from INSERTED

-- a couple of UPDATE queries to unrelated tables
...

COMMIT TRANSACTION;

我想知道是否有可靠的方法来获取要插入的行的 ID?我想到并尝试制作的一个解决方案是在同一个表上安装on insert 触发器,将新插入的行写入我添加到数据库的新表中。我会将该表用作队列。在 Hibernate 中提交事务后,我可以进入该表并使用我刚刚插入的信息运行select(我仍然可以从相同的方法范围访问它),我可以获得 id 并最终删除该行。这是一个庞大的解决方案,但到目前为止我能想到的最好的解决方案。

非常感谢一些帮助。我不能修改现有的触发器和过程,但如果它绝对不影响现有逻辑(比如那个新表和on insert 触发器),我可以向数据库添加一些东西。

总结一下:我需要找到一种方法来获取我刚刚通过 Hibernate 的 save 调用插入的行的 ID。由于那个instead of insert 触发器,休眠总是返回identity=0。我需要找到一种方法来获取该 ID,因为我需要在一个事务期间在其他几个表中进行插入。

【问题讨论】:

  • 我并不完全清楚您要做什么,但要在插入中获取标识列的值,您应该使用 OUTPUT 子句。它可以一次返回所有插入的值(请记住,每个操作触发一次,而不是每行一次)。您可以使用输出值与新创建的标识值一起插入到另一个表中。
  • 嗨@SeanLange 我将更新qn,但我需要找到一种方法来获取我刚刚通过Hibernate 的save 调用插入的行的ID。由于instead of insert 触发器,hibernate 总是返回 0。我需要找到一种方法来获取该 ID,因为我需要在一个事务期间在其他几个表中执行插入操作。
  • @SeanLange 我会将 OUTPUT 子句放在哪里?我无法修改 instead of insert 触发器。
  • 插入是在程序中完成的吗?我有感觉不是。您可以修改执行实际插入的代码吗?这就是您要使用输出捕获标识值的地方。
  • @SeanLange 插入是在我上面帖子中的触发器中完成的。我无法发布整个触发器,但据我所知,触发器中没有任何程序。

标签: java sql-server hibernate triggers


【解决方案1】:

我想我为我的问题找到了一个答案。回复@SeanLange 的评论:我实际上无法编辑插入代码 - 它由另一个应用程序完成,并且查询更改将花费太长时间(或不会发生 - 这是一个遗留应用程序)。我所做的是在同一张表上插入另一个触发器on insert。由于我知道现有instead of insert 触发器中的操作顺序,我可以看到最后一个insert 操作将在我想要的表中,这意味着我的on insert 触发器将在此之后立即触发。在该触发器的范围内,我可以访问inserted 表,我从中提取了 id。

CREATE TRIGGER Client_OnInsert ON myClientTable
FOR INSERT
AS
BEGIN
  DECLARE @ID int;
  SET @ID = (select ClientID from inserted);
  INSERT INTO ModClient (modClientId)
  OUTPUT @ID
  VALUES (@ID);
END
GO

然后在 Hibernate 中(因为我不能再使用 save()),我使用 NativeQuery 来执行此插入。我设置参数并运行 NativeQuery 的 list() 方法,该方法返回一个 List,其中第一个也是唯一的参数是我想要的 id。

这是一种笨重的方式,我知道。如果有什么非常糟糕的事情会引起人们的注意 - 请告诉我。我真的很感激对此的一些反馈。但是,我想将此答案发布为迄今为止有效的潜在答案,但这并不意味着它非常好。为了让这个解决方案发挥作用,我必须创建另一个小表 ModClient,为此我必须将其用作临时 id 存储。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-04
    • 2020-11-04
    • 2023-03-08
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多