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

huus2vyu  于 2022-11-07  发布在  DB2
关注(0)|答案(2)|浏览(1105)

当我执行以下DB2语句时,我收到SQLSTATE=23505错误:

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

在快速搜索之后,SQL状态23505错误定义如下:
插入或更新的值无效,因为索引空间中的索引限制了表的列,因此在现有行为X的列中,没有两行可以包含重复值
我看到的完整错误是:
我看到的完整错误是:
DB2数据库错误:错误[23505] [IBM][DB2/LINUXX 8664] SQL 0803 N INSERT语句、UPDATE语句或DELETE语句导致的外键更新中的一个或多个值无效,因为由“2”标识的主键、唯一约束或唯一索引限制表“WSCOMUSR.SEOURLKEYWORD”的索引键具有重复的值。SQLSTATE=23505 1 0
我不确定“由”2“标识的指数”是什么意思,但它可能很重要。
SEOURLKEYWORD表的列的属性如下:

根据我对这些信息的理解,唯一被强制为唯一的列是SEOURLKEYWORD_ID,即主键列。这听起来像是我试图运行的更新语句试图插入一个具有表中已存在的SEOURLKEYWORD_ID的行。
如果我在我试图更新的行上运行select * 语句,得到的结果如下:

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

我不明白执行UPDATE语句为什么会在这里产生错误。这个语句应该只查看4行,而且我根本没有手动更新主键。看起来像是在删除现有行之前,用更新的列值重新插入了一个重复的行。
当我尝试更新这四行的URLKEYWORD列时,为什么会出现此错误?如何解决此问题?
重要提示:在编写此问题时,我已将问题范围缩小到上表中四行的最后一行,SEOURLKEYWORD_ID = 3074457345616973668。我可以很好地更新其他三行,但第四行导致了错误,我不知道为什么。如果我运行一个选择 * 从SEOURLKEYWORD其中SEOURLKEYWORD_ID = 3074457345616973668;,我只看到了1排。

6g8kf2rb

6g8kf2rb1#

错误很明显。您在表中有一个唯一索引/约束。假设您有如下两行:
| 存储标识|URL关键字|
| - -|- -|
| 小行星10701|甲/B|
| 小行星10701| A至B|
当第一个版本被'A-B'替换时,结果将违反(STOREENT_ID, URLKEYWORD)(URLKEYWORD)上的唯一约束(请注意,其他列也可能包括在唯一约束/索引中)。
你可以通过不更新它们来避免这些情况。我不知道唯一约束在哪些列上,但让我们假设只在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

只有在替换两个值后,它们才会发生冲突。

ca1c2owp

ca1c2owp2#

为了补充@GordonLinoff给出的答案,下面的查询可用于查找表的唯一约束,包括它们的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

相关问题