SQL/DB2执行UPDATE语句时出现SQLSTATE=23505错误

SQL/DB2 SQLSTATE=23505 error when executing an UPDATE statement

当我执行以下 DB2 语句时出现 SQLSTATE=23505 错误:

update SEOURLKEYWORD 
set URLKEYWORD = REPLACE(URLKEYWORD, '/', '-') 
where STOREENT_ID = 10701 
and URLKEYWORD like '%/%';

经过快速搜索,SQL状态23505错误定义如下:

AN INSERTED OR UPDATED VALUE IS INVALID BECAUSE THE INDEX IN INDEX SPACE CONSTRAINS COLUMNS OF THE TABLE SO NO TWO ROWS CAN CONTAIN DUPLICATE VALUES IN THOSE COLUMNS RID OF EXISTING ROW IS X

我看到的完整错误是:

The full error I am seeing is:

DB2 Database Error: ERROR [23505] [IBM][DB2/LINUXX8664] SQL0803N One or more values in the INSERT statement, UPDATE statement, or foreign key update caused by a DELETE statement are not valid because the primary key, unique constraint or unique index identified by "2" constrains table "WSCOMUSR.SEOURLKEYWORD" from having duplicate values for the index key. SQLSTATE=23505 1 0

我不确定 "index identified by '2'" 是什么意思,但它可能很重要。

SEOURLKEYWORD table 的列属性如下:

根据我对这些信息的理解,唯一强制唯一的列是 SEOURLKEYWORD_ID,主键列。这听起来像是我正在尝试 运行 的更新语句试图插入一个 SEOURLKEYWORD_ID 已经存在于 table 中的行。

如果我 运行 对要更新的行执行 select * 语句,这就是我得到的结果:

select * from SEOURLKEYWORD 
where storeent_id = 10701 
and lower(URLKEYWORD) like '%/%';

我不明白执行 UPDATE 语句是如何导致这里出现错误的。这条语句应该只查看 4 行,而且我根本没有手动更新主键。在删除现有行之前,它似乎正在重新插入具有更新列值的重复行。

为什么我在尝试更新这四行的 URLKEYWORD 列时会看到此错误?我该如何解决这个问题?

重要提示:在我写这个问题时,我已将问题缩小到上面 table 中四行中的最后一行,SEOURLKEYWORD_ID = 3074457345616973668。我可以更新其他三行很好,但是第 4 行导致了错误,我不知道为什么。如果我 运行 a select * from SEOURLKEYWORD where SEOURLKEYWORD_ID = 3074457345616973668;,我只看到第 1 行。

错误很明显。您在 table 中有一个独特的 index/constraint。假设您有这样的两行:

STOREENT_ID URLKEYWORD
10701 A/B
10701 A-B

当第一个版本被 'A-B' 替换时,结果将违反对 (STOREENT_ID, URLKEYWORD)(URLKEYWORD) 的唯一约束(请注意,其他列可能包含在唯一约束中constraint/index 还有)。

您可以通过不更新它们来避免这些情况。我不知道唯一约束在哪些列上,但我们只说 URLKEYWORD。那么:

update SEOURLKEYWORD 
    set URLKEYWORD = REPLACE(URLKEYWORD, '/', '-') 
where STOREENT_ID = 10701 and
      URLKEYWORD like '%/%' and
      not exists (select 1 from SEOURLKEYWORD s2 where replace(s2.urlkeyword, '/', '-') = REPLACE(SEOURLKEYWORD.URLKEYWORD, '/', '-') 
                 );

请注意,两列都需要 replace(),因为您可能有:

A-B/C
A/B-C

这些仅在替换两个值后发生冲突。

为了补充@GordonLinoff 给出的答案,这里有一个查询可用于查找 table 的唯一约束及其 ID 以及其中包含的列:

SELECT c.tabschema, c.tabname, i.iid AS index_id, i.indname, ck.colname
FROM syscat.tabconst c
INNER JOIN syscat.indexes i
 ON i.indname = c.constname -- unique index name matches constraint name
AND i.tabschema = c.tabschema AND i.tabname = c.tabname
INNER JOIN syscat.keycoluse ck
 ON ck.constname = c.constname 
AND ck.tabschema = c.tabschema  c.tabname = ck.tabname AND 
WHERE c.type = 'U' -- constraint type: unique
AND (c.tabschema, c.tabname) = ('YOURSCHEMA', 'YOURTABLE') -- replace schema/table
ORDER BY i.iid, ck.colseq