Создать PK для таблицы #temp не удалось, когда script выполняется параллельно
У меня есть следующий код в хранимой процедуре.
....
select ... into #temp from ....
alter table #temp add constraint PK_mytemp13 primary key (....)
....
И я получаю следующее сообщение об ошибке время от времени, если хранимая процедура выполняется параллельно.
В базе данных уже есть объект с именем "PK_perf322dsf". Не удалось создать ограничение. См. Предыдущие ошибки.
Я думаю, этого можно избежать с помощью следующих подходов. Есть ли еще более элегантное решение?
-
Сначала создайте временную таблицу с первичным ключом. Затем вставьте строки.
create table #temp (... primary key (....))
-
Динамически динамически создавайте PK с идентификатором сеанса.
declare @s varchar(500) = 'alter table #temp add constraint PK_temp' + @@spid + ' primary key (....)
Ответы
Ответ 1
- вы пытаетесь вставить в ту же временную таблицу из разных соединений (что невозможно, вместо глобальных временных таблиц),
- или вы пытаетесь вставить в разные таблицы.
if 2nd - вы просто можете сделать следующее: ALTER TABLE #temp ADD PRIMARY KEY (...)
if 1st - вам нужно создать таблицу (регулярную или глобальную временную) с ключом до использования в параллельных операциях
Ответ 2
Это может произойти только в том случае, если одно и то же соединение клиента (равное одному SPID или соединению в SQL Server) повторно используется для двух разных вызовов. Два параллельных вызова должны иметь разные экземпляры соединений и отдельные идентификаторы SPID
SPID полностью изолированы друг от друга локальными (одиночные таблицы #temp)
Изменить:
Игнорировать выше
Я никогда не называл ограничения для временных таблиц. Я использую индексы по мере необходимости или просто добавляю PRIMARY KEY после столбца. Имена констант уникальны для баз данных в sys.objects
A PK - это, в основном, неидеальный кластеризованный индекс. Поэтому используйте CREATE UNIQUE CLUSTERED INDEX
вместо этого, поскольку имена индексов уникальны для каждой таблицы в sys.indexes.
Это не удается при запуске в двух окнах запросов SSMS
CREATE TABLE #gbn (foo int NOT NULL);
ALTER TABLE #gbn ADD CONSTRAINT PK_gbn PRIMARY KEY (foo);
Msg 2714, уровень 16, состояние 5, строка 2
В базе уже есть объект с именем "PK_gbn".
Msg 1750, уровень 16, состояние 0, строка 2
Не удалось создать ограничение. См. Предыдущие ошибки.
Любопытно, что ошибка и имя ограничения совпадают в отличие от вашей ошибки
Это работает
CREATE TABLE #gbn (foo int NOT NULL);
CREATE UNIQUE CLUSTERED INDEX PK_gbn ON #gbn (foo);
Ответ 3
Я пытался запомнить, как это сделать, но вы можете создать безымянный первичный ключ в таблице temp и избежать этой ошибки. Это отличается от размещения PK на уровне столбцов, поскольку он поддерживает более одного столбца. Вот пример:
CREATE TABLE #test
(
AccountNumber INT NOT NULL,
TransactionNumber INT NOT NULL,
PRIMARY KEY CLUSTERED (tranid, sys_process_dt)
);
Это позволяет достичь конечной цели плюс предотвращает дублирование имен. Querying покажет, что SQL Server поместит GUID в имя PK для вас в sys.sysobjects:
SELECT *
FROM tempdb.sys.sysobjects
WHERE name LIKE '%#test%'
имя | xtype
--------------------------------
#test ___..._ 000000000407 | U
PK __ # test_____B88A05A770B3A6A6 | ПК
Вы можете получить свой торт и съесть его тоже.