Sql 违反主键约束PK。无法在对象(表1)中插入重复键,重复键值为(Col1、Col2、Col3、Col4)

Sql 违反主键约束PK。无法在对象(表1)中插入重复键,重复键值为(Col1、Col2、Col3、Col4),sql,sql-server,asp-classic,oledb,Sql,Sql Server,Asp Classic,Oledb,我有一个产品条目页面,通过我们在数据库中不断添加产品条目 产品位置方面有2个系列。e、 例如,ABCTMP(系列(1-max))和XYZ(系列(1-max)) 表具有主键约束,它是4列的组合。在4个序列中,只有一个在增量序列组合方面出现问题 第一列是如上所述的位置相关产品代码,它的数据类型为char(20),因为它存储的值类似于ABCTMP01,并通过经典的asp代码存储。我们通过在现有值中加1来增加最后的01值 现在,当最后一个值达到99并变为100时,面临问题。它通过代码生成代码100,但无

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

产品位置方面有2个系列。e、 例如,
ABCTMP
(系列(1-max))和
XYZ
(系列(1-max))

表具有主键约束,它是4列的组合。在4个序列中,只有一个在增量序列组合方面出现问题

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

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

重复的关键部分与我在主题/标题中提到的相同。若我从100号记录表中删除记录进行检查,通过上面的查询和上面的经典asp代码,它会给我正确的99号记录,并生成下一个代码为99+1=100

但当我再次尝试添加101的下一个系列记录时,即使是通过SQLMGTStudio,也会出现以下错误

违反主键约束“PK”。无法在对象“prdct\U mst\U选项卡”中插入重复的密钥。重复的键值是(PWATERTMP100,006,Y,01)。声明已终止。

已尝试删除约束并将数据类型
char(20)
的大小更改为
char(30)
,因为存在对表的依赖关系。但不起作用。然后,尝试将数据类型从
char(30)
更改为
varchar(30)
,但仍然不起作用。然后再次手动尝试

执行insert命令

在SQL本身中,但第101条记录发生了相同的错误

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

要生成101的下一条记录,select语句必须显示100的最后一条插入记录,但它仍然给出第99条记录,代码再次生成为100,错误继续。我不明白为什么当我在SQLMGTStudio中执行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
注:以上给出的值为示例一


我希望记录在从
99
变为
100
时被插入,这意味着代码将变为
ABCTMP99
-
ABCTMP100
并从
系列
开始,从
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
没有达到你的期望

请尝试在management studio中运行此命令:

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
之前-您是如何度过这一关的

你有一个基本的设计缺陷。我将通过提出一个解决方案来补充这一点,该解决方案将设计缺陷固定到位,并引入新的bug。但它会给你一个结果

一种解决方法是这样做:

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' 
这有什么用

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

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

然后从所有这些中选出最大的一个

注意-这会返回一个数字,但不会返回完整的产品代码。因此,您需要删除尝试提取号码的ASP
Mid
代码

这可能会起作用,直到你找到一些你还没有提到的其他数据或案例。例如,如果有非数字的尾随字符。或者当您需要四个字符的数字时

请不要搞错-您有一个基本的设计缺陷,这只会延长问题的时间,增加复杂性,并引入更多的错误

一些基本意见:

  • char是此的错误数据类型

  • 它有并发性问题-如果两个请求同时调用它(很容易从web应用程序完成),它将返回相同的号码,并且它们都尝试插入重复的值

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

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

您需要决定是否要使用会引入新bug的东西来修补此问题,或者正确地修复它


每个产品代码真的需要像这样在自己的域中递增吗?使用ABC01、DEF02和XYZ03是否存在任何问题?

复制键值是否存在错误(Col1、Col2、Col3、Col4)?请编辑您的问题并发布真正的错误。可能100被截断为00。调试代码会有所帮助。在应用层生成唯一的密钥通常是个坏主意。真正的错误是这样的-违反主键约束“PK”。无法在对象“table1”中插入重复键。您的意思是说,由于数据类型为char(20),一旦值从99变为100,由于char数据类型大小,该值100将转换为00。。对吧?那只是猜测而已。通常,您会从数据库中得到一个截断错误。您将发现的唯一方法是调试程序并确认它实际试图写入数据库的内容。还可以尝试第三次发布错误。
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'