#sql #sql-server
#sql #sql-сервер
Вопрос:
Это очень упрощено, но у меня есть массив элементов веб-службы, которые выглядят примерно так:
[12345, 34131, 13431]
и я собираюсь перебирать массив и вставлять их одну за другой в базу данных, и я хочу, чтобы эта таблица выглядела следующим образом. Эти значения будут привязаны к уникальному идентификатору, показывающему, что они были
1 12345
1 34131
1 13431
и затем, если бы появился другой массив, он вставил бы все свои числа с уникальным идентификатором 2 …. в основном это делается для отслеживания групп.
Потенциально это будет выполняться несколькими процессами одновременно, так каков был бы наилучший способ сгенерировать уникальный идентификатор, а также гарантировать, что два процесса не могли использовать один и тот же?
Комментарии:
1. Поскольку одновременно могут собираться несколько строк, нельзя просто взять последний использованный идентификатор и добавить его. Не лучший, но вы могли бы это сделать, это вставить список значений в основную таблицу (в виде 1 строки), взять идентификатор из этой таблицы для этой группировки и использовать этот идентификатор автоматического увеличения из этой таблицы для вставки в другую таблицу.
2. Вы изучали использование ПОСЛЕДОВАТЕЛЬНОСТИ? Или вам нужен идентификатор, использующий тип uniqueidentifier?
3. Если он функционирует только как идентификатор группы, вы могли бы использовать фактический guid / uniqueidentifier вместо целочисленного значения.
Ответ №1:
Вы должны исправить свою модель данных. Скажем, отсутствует объект batches
.
create table batches (
batch_id int identity(1, 1) primary key,
created_at datetime default getdate()
);
У вас может быть и другая информация.
И в вашей таблице должна быть ссылка на внешний ключ, batch_id
на batches
.
Тогда ваш код должен выполнять следующее:
- Вставьте новую строку в
batches
. Начался новый пакет. - Извлеките только что созданный идентификатор.
- Используйте этот идентификатор для строк, которые вы хотите вставить.
Хотя вы могли бы сделать это с помощью последовательности, отдельная таблица имеет для меня больше смысла. Вы связываете кучу строк вместе во что-то. Это что-то должно быть представлено в модели данных.
Комментарии:
1. … и исходная таблица должна определять внешний ключ, указывающий на
batches
. Трижды приветствую нормализацию! 😀
Ответ №2:
Вы можете объявить это: DECLARE @UniqueID УНИКАЛЬНЫЙ ИДЕНТИФИКАТОР = NEWID();
и используйте это как свой уникальный идентификатор при вставке вашего пакета
Ответ №3:
Поскольку это не первичный ключ, столбец идентификатора отсутствует. Честно говоря, я бы, вероятно, просто отслеживал это, используя отдельную таблицу последовательности идентификаторов. Создайте процедуру, которая получает следующий доступный идентификатор, а затем увеличивает его. Если вы открываете транзакцию в начале процедуры, это должно помешать второму потоку получить номер, пока первый поток не завершит обновление.
Что-то вроде:
CREATE PROCEDURE getNextID
@NextNumber INT OUTPUT
,@id_type VARCHAR(20)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @NextValue TABLE (NextNumber int);
BEGIN TRANSACTION;
UPDATE id_sequence
SET last_used_number = ISNULL(@NextNumber, 0) 1
OUTPUT inserted.last_used_number INTO @NextValue(NextNumber)
WHERE id_type = @id_type
SELECT @NextNumber = NextNumber FROM @NextValue
COMMIT TRANSACTION;
END