如何在不更新现有主键的情况下匹配非主键时插入或更新?

How to INSERT OR UPDATE while MATCHING a non Primary Key without updating existing Primary Key?

我目前正在使用 Firebird 并尝试利用 UPDATE OR INSERT 功能来解决我们软件中的特定新案例。基本上,我们需要从源中提取数据并将其放入现有的 table 中,然后定期更新该数据并添加任何新的引用。源不是数据库,所以使用 MERGE 到 link 两个 table 不是问题(除非我们单独制作一个 table 然后合并它,但这似乎没有必要).

问题在于我们不能使用现有table的主键进行匹配,因为我们需要根据从源中获得的ID进行匹配。我们可以使用 MATCHING 子句没有问题,但问题是现有 table 的主键每次都会更新为下一个键,因为它必须在查询中,因为插入机会。这是用于演示问题的查询(以及 c# 参数添加)。

UPDATE OR INSERT INTO existingtable (PrimaryKey, UniqueSourceID, Data) VALUES (?,?,?) MATCHING (UniqueSourceID);

this.AddInParameter("PrimaryKey", FbDbType.Integer, itemID);

this.AddInParameter("UniqueSourceID", FbDbType.Integer, source.id);

this.AddInParameter("Data", FbDbType.SmallInt, source.data);

问题显示每次触发 UPDATE 时,主键也将更改为下一个递增键我需要一种方法在更新时单独保留主键,但如果它正在插入我需要插入它。

不要手动生成主键,让触发器在必要时生成它:

CREATE SEQUENCE seq_existingtable;

SET TERM ^ ;

CREATE TRIGGER Gen_PK FOR existingtable
ACTIVE BEFORE INSERT
AS
BEGIN
  IF(NEW.PrimaryKey IS NULL)THEN NEW.PrimaryKey = NEXT VALUE FOR seq_existingtable;
END^

SET TERM ; ^

现在您可以从语句中省略 PK 字段:

UPDATE OR INSERT INTO existingtable (UniqueSourceID, Data) VALUES (?,?) MATCHING (UniqueSourceID);

并且当语句触发 insert 时,触发器将负责创建 PK。如果您需要知道生成的 PK,请使用 UPDATE OR INSERT 语句的 RETURNING 子句。