违反 PRIMARY KEY 约束 PK。无法在对象 (table1) 中插入重复键,重复键值为 (Col1, Col2, Col3, Col4)

Violation of PRIMARY KEY constraint PK. Cannot insert duplicate key in object (table1), The duplicate key value is (Col1, Col2, Col3, Col4)

我有一个产品条目页面,我们不断在我们的数据库中添加产品条目。

产品位置明智,有 2 个系列。例如,ABCTMP(系列(1-最大))和XYZ(系列(1-最大))。

Table 具有主键约束,它是 4 列的组合。在 4 个中,只有一个在明智地增加系列组合时给出了问题。

第一列是如上所述的位置明智的产品代码,它是数据类型 char(20),因为它存储像 ABCTMP01 这样的值,并通过经典的 asp 代码。我们通过在现有值上加一来增加最后一个 01 值。

现在,当最后一个值达到 99 并变为 100 时面临问题。它通过代码生成代码 100 但无法插入数据库并给出此错误,这是由于数据库中存在条目。

重复的密钥部分与我在 subject/header 中提到的相同。如果我从记录号 table 中删除记录。 100 检查,它通过上面的查询和上面的经典 asp 代码给了我 99 的正确记录,它生成下一个代码为 99+1 = 100。

但是当我再次尝试为 101 添加下一个系列记录时,即使通过 SQL mgt studio,它也会给我以下错误。

违反主键约束'PK'。无法在对象 'prdct_mst_tab' 中插入重复键。重复键值为 (PWATERTMP100, 006, Y, 01)。声明已终止。

已尝试通过删除约束并将数据类型 char(20) 的大小更改为 char(30),因为对 table 存在依赖性。但没有奏效。然后,尝试将数据类型从 char(30) 更改为 varchar(30),仍然无效。然后再次手动尝试

executing insert command

在SQL本身,但第101条记录发生同样的错误。

在生成下一个系列之前,有 select 语句来检查最新插入的记录,该记录稍后会增加。

为了生成下一条 101 条记录,select 语句必须显示最后插入的 100 条记录,但它仍然给出第 99 条记录,代码再次生成 100 条记录,错误仍然存​​在。我不明白为什么当我在 SQL mgt studio 中执行 SELECt 语句时它没有记录第 100 条记录。该 PWATERTMP100 列的数据类型是 char(20)。

下面是我的经典 asp 系列生成代码和 SQL 'SELECT top 1 *' 位置明智产品记录计数语句。

select top 1 * 
from prdct_mst_tab 
where pmt_prdct_cd like 'PWATER%' 
and pmt_umt_unit_cd='006' 
AND PMT_CMT_CMPNY_CD='01' 
order by pmt_prdct_cd desc

经典ASP代码:-

If recordset.eof Then 
    getcode="ABCTMP01" 
Else
    getcode = clng(Mid(recordset("Column1"),10,20))
        response.write("Hello" & getcode)
    getcode = getcode +1
        response.write("<br />Hello" & getcode)
    getcode = "ABCTMP" & getcode
        response.write("<br />Hello" & getcode)
End if

下面用于在数据库中添加生成的产品代码 table。

Sql如下

select * from Table1
recordset.open sql,con,3,2
recordset.addnew
recordset("Column1")=getcode
recordset.update 
recordset.close

Note : Values given above are sample one.

我希望即使记录从 99 变为 100 也能插入,这意味着代码将变为 ABCTMP99 - ABCTMP100 并从 [=28= 继续] 以 100 范围(3 位数字)开头,例如 100、101、102....

问题是顺序是这样的:

select top 1 * from prdct_mst_tab 
where pmt_prdct_cd like 'PWATER%' 
and pmt_umt_unit_cd='006' 
AND PMT_CMT_CMPNY_CD='01' 
order by pmt_prdct_cd desc

没有达到您的预期。

在管理工作室尝试运行:

select * from prdct_mst_tab 
where pmt_prdct_cd like 'PWATER%' 
and pmt_umt_unit_cd='006' 
AND PMT_CMT_CMPNY_CD='01' 
order by pmt_prdct_cd desc

您会看到 100 出现在 之前 99 因为它是按字母数字而不是数字顺序排列的。

事实上,您还会看到 10 出现在 9 之前 - 您是如何克服这个问题的?

你有一个基本的设计缺陷。我将 添加 通过提出一个解决方案来巩固设计缺陷并引入新的错误。但它会给你一个结果。

一个解决方法 是这样做的:

select 
MAX(
  CASE 
    WHEN ISNUMERIC(RIGHT(RTRIM(pmt_prdct_cd),3)) = 1 
    THEN RIGHT(RTRIM(pmt_prdct_cd),3)
    ELSE '0' + RIGHT(RTRIM(pmt_prdct_cd),2)
  END
) As LargestNumber
from prdct_mst_tab 
where pmt_prdct_cd like 'PWATER%' 
and pmt_umt_unit_cd='006' 
AND PMT_CMT_CMPNY_CD='01' 

这是做什么的?

检查最后三个字符是否为数字。如果是它就使用它。

如果它不是数字,它会抓取最后两个字符并在前面放一个零。

然后它从所有这些中选择最大的数字。

注意 - 这 return 是一个数字,它不是 return 完整的产品代码。因此,您需要删除试图提取号码的 ASP Mid 代码。

这可能会奏效,直到您找到一些您尚未提及的其他数据或案例。例如,如果尾随字符不是数字。或者当你需要一个四字符的数字时

别搞错了 - 你有一个基本的设计缺陷,这只会延长问题,增加复杂性,并在轨道上引入更多错误

一些基本观察:

  • char 是一个错误的数据类型

  • 它有并发问题 - 如果两个请求同时调用它(从网络应用程序轻松完成),它 return 是相同的数字,它们都尝试插入一个重复值

  • 您不应该像这样分配和存储递增的数字。只需在数据库中使用 IDENTITY

我想既然你使用的是经典 ASP,你就不能重新设计它。

您需要决定是要用会引入新错误的东西来修补它还是正确修复它。

每个产品代码 真的 需要像那样在其自己的域内递增吗?使用 ABC01 然后使用 DEF02 然后使用 XYZ03 有什么问题吗?