Генерация уникального идентификатора для совместного использования с несколькими таблицами SQL 2008 - PullRequest
3 голосов
/ 17 ноября 2008

У меня есть пара таблиц на сервере SQL 2008, для которых мне нужно сгенерировать уникальные идентификаторы. Я посмотрел на столбец «личность», но идентификаторы действительно должны быть уникальными и распределяться между всеми таблицами.

Так что, если я скажу (5) пять таблиц разновидности "инфраструктуры активов", и я хочу работать с уникальным идентификатором между ними как объединенной группой, мне нужен какой-то генератор, который просматривает все (5) пять таблицы и выдает следующий идентификатор, который не дублируется ни в одной из этих (5) пяти сказок.

Я знаю, что это можно сделать с помощью какой-то хранимой процедуры, но я не уверен, как это сделать. Есть идеи?

Ответы [ 7 ]

5 голосов
/ 06 мая 2009

Самое простое решение состоит в том, чтобы установить ваши начальные значения и приращения для каждой таблицы, чтобы они никогда не перекрывались. Таблица 1: Семя 1, Приращение 5 Таблица 2: Семя 2, Приращение 5 Таблица 3: Семя 3, Приращение 5 Таблица 4: Семя 4, Приращение 5 Таблица 5: Семя 5, Приращение 5

Мод 5 столбца идентификаторов скажет вам, в какой таблице находится запись. Вы будете использовать свое пространство идентификаторов в пять раз быстрее, поэтому убедитесь, что тип данных достаточно большой.

4 голосов
/ 17 ноября 2008

Немного читая дизайн, звучит так, как будто вам действительно нужна отдельная таблица с именем Asset и столбцом идентификаторов, а затем либо:

а) 5 дополнительных таблиц для подтипов активов, каждая из которых имеет внешний ключ к первичному ключу в активе; или

b) 5 представлений об Активе, каждый из которых выбирает подмножество строк и затем отображается (для пользователей), как 5 исходных таблиц, которые у вас сейчас есть.

Если столбцы в таблицах одинаковы, то (б) - лучший выбор; если они все разные, (а) - лучший выбор. Это классическое вращение БД в отношении супертип / подтип.

В качестве альтернативы, вы можете сделать то, о чем говорите, и воссоздать функцию IDENTITY самостоятельно с помощью хранимого процесса, который включает доступ INSERT ко всем 5 таблицам. Обратите внимание, что вам нужно будет поместить транзакцию вокруг него, если вы хотите гарантировать уникальность, и если это популярная таблица, это может сделать ее узким местом в производительности. Если это не проблема, такой процесс может принять форму:

CREATE PROCEDURE InsertAsset_Table1 (
  BEGIN TRANSACTION
  -- SELECT MIN INTEGER NOT ALREADY USED IN ANY OF THE FIVE TABLES
  -- INSERT INTO Table1 WITH THAT ID
  COMMIT TRANSACTION -- or roll back on error, etc.
)

Опять же, SQL сильно оптимизирован, чтобы помочь вам, если вы выберете шаблоны, о которых я упоминал выше, и НЕ оптимизирован для такого рода вещей (создание транзакции сопряжено с дополнительными затратами, и вы будете совместно использовать блокировки для всех 5 таблиц, этот процесс продолжается). Сравните это с использованием метода PK / FK, описанного выше, где SQL Server точно знает, как это сделать без блокировок, или метода представления, когда вы вставляете только в 1 таблицу.

4 голосов
/ 17 ноября 2008

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

Идентификаторы GUID будут работать, но они неприятны и непоследовательны, если это важно.

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

Вы понимаете, что есть логические проблемы с дизайном, верно?

4 голосов
/ 17 ноября 2008

Почему бы не использовать GUID?

0 голосов
/ 27 ноября 2011

Это распространенная проблема, например, при использовании таблицы людей (называемой ЛИЧНОМ, пожалуйста) и каждый человек классифицируется, например, врачи, пациенты, сотрудники, медсестры и т. Д.

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

Например, у Пациента может быть много медсестер и врачей, которые работают над ним, поэтому таблица «многие ко многим», которая связывает Пациента с другими людьми в таблице ЛИЦО, облегчает это. В этой таблице должно быть некоторое описание отношений между этими людьми, которое возвращает нас к категориям людей.

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

Хороший способ сделать это, как предложено, состоит в том, чтобы иметь таблицу, предназначенную для автоматического увеличения первичного ключа. Сначала выполните вставку в эту таблицу, чтобы получить OID, а затем используйте ее для нового ЛИЦА.

Мне нравится идти дальше. Когда дела идут ужасно (какой-то новый разработчик получает в свои руки базу данных или, что еще хуже, действительно старый разработчик, тогда очень полезно добавить больше смысла в OID.

Обычно это делается программно, а не с ядром базы данных, но если вы используете BIG INT для всех идентификаторов первичного ключа, тогда у вас будет много места для префикса числа с визуально идентифицируемой последовательностью. Например, все идентификаторы врачей могут начинаться со 100, все пациенты - со 110, все медсестры - со 120.

К этому я добавлю, скажем, юлианскую дату или дату + время Unix, и, наконец, добавлю идентификатор автоматического увеличения.

Это приведет к таким числам, как:

110,2455892,00000001
120,2455892,00000002
100,2455892,00000003

, поскольку юлианская дата через 100 лет составляет всего 2492087, вы можете видеть, что 7 цифр будут адекватно хранить это значение.

BIGINT - это 64-разрядное (8-байтовое) целое число со знаком со значением от -9,22 × 10 ^ 18 до 9,22 × 10 ^ 18 (от -2 ^ 63 до 2 ^ 63 -1). Обратите внимание, что показатель степени равен 18. Это 18 цифр, с которыми вам нужно работать.

Используя этот дизайн, вы ограничены 100 миллионами OID, 999 категориями людей и датами до ... намного больше срока годности вашей базы данных, но я подозреваю, что этого достаточно для большинства решений.

Операции, требуемые для создания подобного OID, - это умножение и деление, которые исключают все искажения при обработке текста.

Недостатком является то, что для вставки требуется больше, чем простая инструкция TSQL, но преимущество заключается в том, что когда вы отслеживаете ошибочные данные или даже умны в своих запросах, ваш OID визуально говорит вам много больше, чем случайное число или хуже , бельмо на глазу, как GUID.

0 голосов
/ 24 января 2011

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

create table T1(ID int primary key identity(1,2), rownum varchar(64))

create table T2(ID int primary key identity(2,2), rownum varchar(64))

insert into T1(rownum) values('row 1')
insert into T1(rownum) values('row 2')
insert into T1(rownum) values('row 3')

insert into T2(rownum) values('row 1')
insert into T2(rownum) values('row 2')
insert into T2(rownum) values('row 3')

select * from T1

select * from T2

drop table T1
drop table T2
0 голосов
/ 09 января 2009

Я нашел это при поиске в Google. Я впервые сталкиваюсь с подобной проблемой. У меня была идея создать специальную таблицу идентификаторов, чтобы генерировать идентификаторы, но я не был уверен, считалось ли это нормальным дизайном. Так что я просто хотел сказать СПАСИБО за подтверждение .. похоже, это адекватное решение, хотя и не идеальное.

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