Нарушение ПЕРВИЧНОГО КЛЮЧЕВОГО КОНТРОЛЯ ПК. Невозможно вставить дубликат ключа в объект (таблица1), значение дубликата ключа (Col1, Col2, Col3, Col4) - PullRequest
0 голосов
/ 05 января 2019

У меня есть страница ввода продукта, и мы продолжаем добавлять записи о продуктах в нашу базу данных.

В зависимости от местоположения продукта существует 2 серии. например, ABCTMP (серия (1-max)) и XYZ (серия (1-max)).

Таблица имеет ограничение первичного ключа, которое представляет собой комбинацию из 4 столбцов. Из 4 только одна вызывает проблему, в то время как комбинация последовательных приращений является разумной.

В этом первом столбце указан код продукта с указанием местоположения, как указано выше, и он имеет тип данных char(20), поскольку в нем хранятся значения, такие как ABCTMP01 и через классический код asp. Мы увеличиваем это последнее 01 значение, добавляя единицу к существующему значению.

Прямо сейчас возникает проблема, когда последнее значение достигает 99 и превращается в 100. Он генерирует код 100 с помощью кода, но не может быть вставлен в базу данных и выдает эту ошибку, которая произошла из-за существующей записи в базе данных.

Повторяющаяся ключевая часть та же самая, о которой я упоминал выше в теме / заголовке. Если я удаляю запись из таблицы записей, то нет. 100, чтобы проверить, это дает мне правильную запись 99 через вышеупомянутый запрос и через вышеупомянутый классический код asp, это генерирует следующий код как 99 + 1 = 100.

Но когда я снова пытаюсь добавить следующую серию записей для 101, даже через SQL mgt studio, это выдает мне ошибку ниже.

Нарушение ограничения PRIMARY KEY 'PK'. Невозможно вставить дубликат ключа в объект 'prdct_mst_tab'. Значение дублированного ключа (PWATERTMP100, 006, Y, 01). Заявление было прекращено.

Попытался сбросить ограничение и изменить размер типа данных char(20) на char(30), так как существуют зависимости от таблицы. Но не сработало. Затем попытались изменить тип данных с char(30) на varchar(30), все еще не работает. Затем снова попробовал вручную

выполнение команды вставки

в самом SQL, но такая же ошибка произошла для 101-й записи.

Перед генерацией следующей серии есть оператор выбора для проверки последней вставленной записи, которая будет увеличена позже.

Для создания следующей записи из 101 оператор SELECT должен показывать последнюю вставленную запись из 100, но он по-прежнему дает 99-ю запись, и код снова генерируется как 100, и ошибка повторяется. Я не понимаю, почему он не берет сотую запись, когда я выполняю оператор SELECt в SQL mgt studio. Тип данных этого столбца 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

Ниже для добавления сгенерированного кода продукта в таблицу базы данных.

Sql как показано ниже

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

Примечание: приведенные выше значения являются примерами.

Я хочу, чтобы запись вставлялась даже тогда, когда она меняется с 99 на 100, означает, что код станет ABCTMP99 - ABCTMP100 и продолжится с series, начиная с диапазона 100 (3 цифры), например 100, 101, 102 ....

1 Ответ

0 голосов
/ 07 января 2019

Проблема в том, что порядок по этому:

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 - как вы когда-либо проходили это?

У вас есть фундаментальный недостаток дизайна. Я добавлю к этому , предложив решение, которое устранит недостатки дизайна и внесет новые ошибки. Но это даст вам результат.

Один обходной путь должен сделать что-то такое:

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 - плохой тип данных для этого

  • У него есть проблемы с параллелизмом - если два запроса вызывают его одновременно (это легко сделать из веб-приложения), он возвращает один и тот же номер, и они оба пытаются вставить дублирующее значение

  • Вы не должны присваивать и хранить увеличивающиеся числа, подобные этому. Просто используйте IDENTITY в базе данных.

Я полагаю, поскольку вы используете классический ASP, вы не можете изменить его.

Вам нужно решить, собираетесь ли вы исправлять это с помощью чего-то, что будет вводить новые ошибки или исправлять это правильно.

Должен ли каждый код продукта действительно быть увеличен в своем собственном домене? Есть ли проблема с ABC01, затем DEF02, а затем XYZ03?

...