Автоинкремент SQL Server для составного ключа - PullRequest
4 голосов
/ 12 марта 2012

У меня есть таблица с составным ключом в SQL Server 2008 (это было сделано по разным причинам / дизайн БД, но основной является b / c, мы переходим к новой схеме и должны сохранить данные).

Итак, я создал новую таблицу со ссылкой на внешний ключ и работал над переносом данных. Извлечение / редактирование данных легко. Теперь я хотел бы иметь возможность вставлять новые записи (используя заданное значение FK) и иметь возможность автоматически увеличивать идентификаторы вновь вставленных записей и обрабатывать все это в рамках сохраненного процесса.

Пример

Таблица 1: (id, type make up the composite key)

id   data  type(FK)
1     A      1
2     B      1
1     C      2
2     D      2
3     B      1
4     C      1
3     A      2
4     G      2

Теперь, если у меня есть другая запись (данные F типа 2), я бы хотел иметь возможность передавать данные записи (data=F,type=2) и иметь сохраненную вставку процедуры (5, F, 2) .. в потокобезопасный / параллельный / масштабируемый способ (то есть без выполнения SELECT MAX(id)...). Любые идеи / мысли о том, как сделать это наилучшим образом от сообщества SQL Server?

Ответы [ 3 ]

4 голосов
/ 12 марта 2012

Самое простое решение и самое безопасное состоит в том, чтобы просто добавить столбец INT IDENTITY в таблицу и позволить SQL Server разобраться со сложностями обновления значения идентификатора.Это даст вам реальное, правильное и надежное значение идентичности - независимо от значения вашего столбца type.

В SQL Server 2012 вы можете использовать объект базы данных SEQUENCE для создания последовательности длякаждое значение type, в котором вы нуждаетесь, но, к сожалению, в версии 2008 года такого еще нет.

1 голос
/ 12 марта 2012

С какой стати вы хотите хранить эти данные, когда вы всегда можете получить их во время запроса и гарантировать, что они будут точными?

SELECT 
  [type], data, 
  id = ROW_NUMBER() OVER (PARTITION BY [type] ORDER BY data)
FROM dbo.table
ORDER BY [type], id;

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

DELETE dbo.table WHERE data = 'B';

UPDATE dbo.table SET data = 'Z' WHERE data = 'C';

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

1 голос
/ 12 марта 2012

Это один из способов сделать это, предполагая, что данные, которые вы хотите вставить, находятся в другой таблице (Таблица2):

INSERT INTO Table1(id, data, type)
SELECT  ISNULL(B.MaxId,0) + ROW_NUMBER() OVER(PARTITION BY A.type ORDER BY A.data) AS Id,
        A.data,
        A.type
FROM Table2 A
LEFT JOIN (SELECT type, MAX(id) MaxId 
            FROM Table1 
            GROUP BY type) B
ON A.type = B.type

Как сказал @marc_s в комментарии: Использование подхода MAX (Id) обычно небезопасно при нагрузке параллелизма

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