【问题标题】:Firebird update or insert with generated keyFirebird 使用生成的密钥更新或插入
【发布时间】:2018-12-05 17:12:53
【问题描述】:

带 FireDAC 的 Delphi 10.2 下的 Firebird 2.5:我有一个表,其中包含事件处理程序对象的定义数据,以及从表中加载和存储的那些对象的 TObjectList - 这个表永远不会变得很大,可能是最大值30-40 行,通常只有少数。表的每一行都有一个插入后触发器生成的 PK。我需要能够将对象更新回匹配的表行,并插入任何新条目在插入后取回生成的 PK 值以保持对象的 ID 匹配。

Firebird 支持的 UPDATE OR INSERT 子句似乎不适合 PK 由插入后触发器生成的情况,但也许我遗漏了一些东西。

那么有没有一种直接的方法来做这种类型的构造?并且考虑到表的小尺寸,是否更有效(如果不完全符合 kosher)只删除表并插入所有新记录?

【问题讨论】:

  • 你知道FireDAC event alerts吗?
  • 我也有同样的问题。我能够解决它的唯一方法是使用存储过程,该过程在生成密钥后执行插入并返回生成的密钥。
  • Martyn - 不,我不是。感谢您的链接 - 我想我知道如何利用这一点。即将测试它。
  • 如果只有您的应用程序使用数据库,另一种方法是设置一个生成器(如果您还没有)来生成您的 pk 并在表的 OnNewRecord 事件中自己调用它。
  • PK generated by an after-insert trigger 你是怎么做到的?插入后触发器不能像before-insert触发器一样更改列新值

标签: delphi firebird firedac


【解决方案1】:

UPDATE OR INSERT 语句支持RETURNING 子句,它允许您返回生成的 id。

但主要问题是您说“PK 是由插入后触发器生成的”。这是不可能的,或者 - 至少 - 如果这是您现在正在做的事情,那么您没有以正确的方式进行操作,您可能正在使用一种解决方法,例如在桌面上使用 update 语句。

生成 ID 的正确方法是在“插入前”触发器中,其中值在 NEW 上下文中设置(例如 NEW.id = <generated value>)。 “插入后”触发器无法修改 NEW 上下文,因此无法以正确的方式更新列值。在“插入前”触发器中更新NEW 上下文中的值也是允许使用RETURNING 子句返回的原因。

另请参阅 Firebird 语言参考中的 "OLD and NEW Context Variables"

在所有AFTER 触发代码中,NEW 变量是只读的

您可能还想阅读CREATE TRIGGER 文档,其中还包含有关如何生成 id 的示例。另一个例子,见How to create an autoincrement column?

【讨论】:

  • 呃!谢谢,马克 - 当然,PK 是在插入前触发器中生成的,而不是在插入后。我的脑袋放屁。我在想,因为 UPDATE OR INSERT 的返回值在应用任何插入后触发器之前被拉出,所以我不会得到它,但因为它在之前的事件中它会在那里。这应该有效。再次感谢! :)
猜你喜欢
  • 2018-12-05
  • 1970-01-01
  • 1970-01-01
  • 2012-11-17
  • 2016-04-08
  • 2013-09-05
  • 2016-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多