我有一个程序可以同步两个数据库中的记录。它依赖于插入时的主键违规来了解该记录已经存在,然后对该记录应用更新。这样,我就可以避免执行显式 SQL 查询来检查给定记录是否存在。
但是对于一个特定的表,我有主键和唯一索引(对于与主键不同的列)。当我尝试在其中插入重复记录时,首先发生唯一索引违规,因此不会发生主键违规,因此程序算法失败。
有没有办法确保主键违规总是首先发生?或者有没有明确的规则先检查?
下面是该表的DDL:
CREATE TABLE BONS
(
BON_ID INTEGER NOT NULL,
BON_OPENTIME TIMESTAMP NOT NULL,
BON_CLOSETIME TIMESTAMP NOT NULL,
BON_SALESMANID INTEGER NOT NULL,
BON_POSID INTEGER NOT NULL,
BON_TABLENO SMALLINT,
BON_NUM INTEGER NOT NULL,
...
);
/******************************************************************************/
/**** Primary key ****/
/******************************************************************************/
ALTER TABLE BONS ADD CONSTRAINT PK_BON_ID PRIMARY KEY (BON_ID);
/******************************************************************************/
/**** Indices ****/
/******************************************************************************/
CREATE UNIQUE INDEX IDX_UNQ_BON_POSID_NO ON BONS (BON_POSID, BON_NUM);
通过一些实验,似乎创建顺序决定了首先触发主键或唯一键(或更具体地说,其
RDB$INDICES.RDB$INDEX_ID
的值),这表明唯一索引是在主键之前创建的键,或者至少收到一个较低的 RDB$INDEX_ID
,如果主键之前表上存在另一个索引,并且在添加唯一索引之前删除该索引,也可能会发生这种情况。
仅删除并重新创建唯一索引是不够的。每个表的索引都有一个 id,如果删除一个或多个,后续创建的新索引将重用这些 id。您将需要删除唯一索引和主键,然后按所需的顺序重新创建它们。
但是,更多测试表明这并不能保证备份和恢复的确定性。备份时,索引按其物理存储顺序存储在
RDB$INDICES
元数据表中,恢复时,它们按该顺序恢复,表的第一个索引将获得 RDB$INDEX_ID = 1
,第二个索引将获得 2
,并且依此类推,这意味着他们的评估顺序可以改变。
在一个事务中删除两个索引,然后在同一事务中重新创建它们将使其物理存储顺序可能与其逻辑存储顺序相同,但这并不能保证。