执行UPDATE语句

时间:2016-12-13 16:14:24

标签: sql database db2 toad

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

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

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

  

插入或更新的值是无效的,因为索引空间的索引限制了表中的列所以没有两行可以包含现有行的列中的重复值X

我看到的完整错误是:

  

我看到的完整错误是:

     

DB2数据库错误:错误[23505] [IBM] [DB2 / LINUXX8664] SQL0803N由DELETE语句引起的INSERT语句,UPDATE语句或外键更新中的一个或多个值无效,因为主键是唯一的由“2”约束表或“WSCOMUSR.SEOURLKEYWORD”标识的约束或唯一索引具有索引键的重复值。 SQLSTATE = 23505       1 0

我不确定“2'标识的索引”是什么意思,但它可能很重要。

SEOURLKEYWORD表的列属性如下:

enter image description here

根据我对此信息的理解,唯一被强制唯一的列是主键列SEOURLKEYWORD_ID。这使得它听起来像我正在尝试运行的更新语句正在尝试插入具有表中已存在的SEOURLKEYWORD_ID的行。

如果我在我想要更新的行上运行select *语句,这就是我得到的:

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

enter image description here

我不明白执行UPDATE语句是如何导致错误的。这个语句甚至只能查看4行,而我根本不会手动更新主键。在删除现有行之前,它似乎重新插入了具有更新列值的重复行。

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

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

2 个答案:

答案 0 :(得分:1)

评论太长了。

错误很清楚。表中有唯一的索引/约束。假设您有两行:

STOREENT_ID    URLKEYWORD
    10701        A/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

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

答案 1 :(得分:1)

为了补充@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