Будет ли умножение запросов на вставку к одной и той же таблице с прямым запросом и хранимой процедурой причиной коллизии? - PullRequest
3 голосов
/ 23 мая 2011

Несколько пользователей могут вызывать хранимую процедуру (SP) , которая внесет некоторые изменения в mytable в SQL Server.Этот SP должен вставить несколько строк в mytable , который имеет ссылку на себя через столбец parentid .

TABLE mytable(
   id int identity(1,1) primary key,
   name varchar(20) not null,
   parentId int not null foreign key references mytable(id)
)  

, чтобы вставить строку в такую ​​таблицу, соответственно другимпосты, у меня есть 2 способа:

  1. Разрешить null для parentid столбец ALTER TABLE mytable alter column parentid int null;, вставить строку, обновить parentid и затем отключить NULL для parentid
  2. Разрешить IDENTITY на set identity_insert maytable on, вставить фиктивный ряд с id = -1 и parentid = -1 вставьте правильную строку со ссылкой на -1 , обновите parentid до SCOPE_IDENTITY () и в конце установите IDENTITY в выключенное состояние

Дело:

Предположим, я выбрал 2nd . SP удалось set identity_insert mytable on НО еще не закончил выполнение остальных SP .В настоящее время существуют другие запросы INSERT (НЕ через SP) к таблице mytable , такие как INSERT INTO mytable(name,parentid) VALUES('theateist', -1).Нет id указано, потому что они предположили, что IDENTITY выключен, и поэтому id является автоинкрементным.

Вопрос:

Приведет ли это к ошибкам при вставке, потому что IDENTITY в этот период времени включен и больше не является автоинкрементным, и, следовательно, для него потребуется спецификация id ?Если да, то будет лучше использовать 1-й , не так ли?

Спасибо

1 Ответ

2 голосов
/ 23 мая 2011

identity_insert - это настройка для каждого соединения - вы не будете влиять на другие соединения / операторы, работающие с этой таблицей.

Я бы определенно не предлагал идти первым путем, если его можно было бы избежать,так как это может повлиять на других пользователей таблицы - например, какое-то другое соединение может выполнить неправильную вставку (parentid=null), пока определение столбца это позволяет, и тогда ваш сохраненный процесс будет прерван.Кроме того, установка столбца not null заставляет выполнить полное сканирование таблицы, поэтому это не будет работать должным образом по мере роста таблицы.

Если вы придерживались метода 2, у вас все еще есть проблема счто произойдет, если два соединения запустят этот сохраненный процесс одновременно - они оба захотят вставить строку -1 в разное время и также удалить ее.У вас будут конфликты.

Полагаю, проблема в том, что вы вставляете «корни» дерева (ов), поскольку у них нет родителей, и вы пытаетесь их получить.Самостоятельная ссылка.Вместо этого я бы, вероятно, навсегда оставил у корней нулевую парентиду.Если есть некоторые другие ключевые столбцы, их можно использовать в отфильтрованном индексе или индексированном представлении, чтобы гарантировать наличие только одного корня для каждого ключа.


Представьте, что мы создаем некоторую формуродословные и игнорирование большинства реалий таких зверей (например, большинство семей, требующих, чтобы у детей было два родителя):

CREATE TABLE People (
    PersonID int IDENTITY(1,1) not null,
    Surname varchar(30) not null,
    Forename varchar(30) not null,
    ParentID int null,
    constraint PK_People PRIMARY KEY (PersonID),
    constraint FK_People_Parents FOREIGN KEY (ParentID) references People (PersonID)
)

CREATE UNIQUE INDEX IX_SoleFamilyRoot ON People (Surname) WHERE (ParentID is null)

Это гарантирует, что в каждой семье (как определено по фамилии) точноодин человек имеет ноль ParentID.Надеемся, что вы можете изменить этот пример, чтобы он подходил для вашей модели.

В SQL Server 2005 и более ранних версиях вместо этого необходимо использовать индексированное представление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...