СПОЧАТКУ
Ви , ймовірно , не потрібні всі три колонки: old_id
, external_id
, new_id
. new_id
Колона, будучи IDENTITY
, матиме нове значення , сгенерированное для кожного рядка, навіть при вставці в external_id
. Але, між old_id
і external_id
ті , в значній мірі взаємовиключні: або вже є old_id
значення або цей стовпець, в поточній концепції, буде тільки NULL
при використанні external_id
або new_id
. Оскільки ви не будете додавати новий "зовнішній" ідентифікатор до вже існуючої рядки (тобто такої, яка має old_id
значення), і нові значення не надходитимуть old_id
, то може бути один стовпець, який використовується для обох цілей.
Отже, позбудьтесь external_id
стовпця та перейменуйте, old_id
щоб бути чимось подібним old_or_external_id
чи будь-яким. Це не повинно вимагати жодних реальних змін у чомусь, однак зменшує деякі ускладнення. Щонайбільше вам може знадобитися зателефонувати в стовпчик external_id
, навіть якщо він містить "старі" значення, якщо код програми вже записаний для вставки external_id
.
Це зменшує нову структуру як раз:
PkId AS AS COALESCE(old_or_external_id, new_id, -1) PERSISTED NOT NULL,
old_or_external_id INT NULL, -- values from existing record OR passed in from app
new_id INT IDENTITY(2000000, 1) NOT NULL
Тепер ви додали лише 8 байт у рядку замість 12 байт (якщо припустимо, що ви не використовуєте SPARSE
параметр або стиснення даних). І вам не потрібно було змінювати будь-який код, T-SQL або код програми.
ДРУГИЙ
Продовжуючи цей шлях спрощення, давайте розглянемо, що нам залишилося:
- У
old_or_external_id
стовпці або вже є значення, або буде додано нове значення в додатку, або залишиться як NULL
.
new_id
Завжди буде мати нове значення , сгенерированное, але це значення буде використано тільки якщо old_or_external_id
стовпець NULL
.
Ніколи не буває часу, коли вам знадобляться значення в обох old_or_external_id
і new_id
. Так, буде час, коли обидва стовпці мають значення через new_id
те, що вони є IDENTITY
, але ці new_id
значення ігноруються. Знову ж таки, ці два поля взаємовиключні. І що тепер?
Тепер ми можемо розібратися, навіщо нам це було потрібно external_id
в першу чергу. Враховуючи те, що можна вставити в IDENTITY
стовпчик за допомогою SET IDENTITY_INSERT {table_name} ON;
, ви можете піти, не вносячи жодних змін у схему, а лише змінити код свого додатка, щоб обернути INSERT
оператори та операції в SET IDENTITY_INSERT {table_name} ON;
та SET IDENTITY_INSERT {table_name} OFF;
заяви. Потім потрібно визначити, до якого початкового діапазону скинути IDENTITY
стовпець (для новогенерованих значень), оскільки він повинен бути набагато вище значень, які буде вставляти код додатка, оскільки вставлення більш високого значення призведе до наступного автоматично сформованого значення бути більше, ніж поточне значення MAX. Але ви завжди можете вставити значення, яке нижче значення IDENT_CURRENT .
Поєднання стовпців old_or_external_id
та і new_id
також не збільшує шансів потрапити в ситуацію перекриття значень між автоматично створеними значеннями та значеннями, створеними додатком, оскільки намір мати 2, а то й 3 стовпці - поєднувати їх у значення первинного ключа, і це завжди унікальні цінності.
У такому підході вам просто потрібно:
Залиште таблиці як такі:
PkId INT IDENTITY(1,1) PRIMARY KEY
Це додає 0 байтів у кожен рядок, а не 8 або навіть 12.
- Визначте початковий діапазон для значень, створених додатком. Вони будуть більшими за поточне значення MAX у кожній таблиці, але менше, ніж стане мінімальним значенням для автоматично сформованих значень.
- Визначте, з якого значення повинен починатись автоматично створений діапазон. Між поточною величиною MAX та великою кількістю кімнати має бути достатньо місця , адже верхня межа - трохи більше 2,14 мільярда. Потім можна встановити це нове мінімальне значення насіння через DBCC CHECKIDENT .
- Оберніть код програми ВСТАВЛЕННЯ в
SET IDENTITY_INSERT {table_name} ON;
і SET IDENTITY_INSERT {table_name} OFF;
заяви.
ДРУГО, частина В
Різновидом на підході, зазначеним безпосередньо вище, було б, щоб у коді додатка вставлялися значення, починаючи з -1 і знижуючись звідти. Це залишає IDENTITY
значення як єдині, що піднімаються . Перевага тут полягає в тому, що ви не тільки не ускладнюєте схему, але і не потрібно турбуватися про набігання на ідентифікатори, що перекриваються (якщо значення, створені додатком, стикаються з новим автоматично створеним діапазоном). Це лише варіант, якщо ви вже не використовуєте негативні значення ідентифікатора (і людям здається досить рідкісним використання негативних значень на стовпцях, що автоматично створюються, тому це може бути можливим у більшості ситуацій).
У такому підході вам просто потрібно:
Залиште таблиці як такі:
PkId INT IDENTITY(1,1) PRIMARY KEY
Це додає 0 байтів у кожен рядок, а не 8 або навіть 12.
- Початковий діапазон для значень, створених додатком, буде
-1
.
- Оберніть код програми ВСТАВЛЕННЯ в
SET IDENTITY_INSERT {table_name} ON;
і SET IDENTITY_INSERT {table_name} OFF;
заяви.
Тут вам все одно потрібно зробити IDENTITY_INSERT
, але: ви не додаєте жодних нових стовпців, не потрібно «повторно» повторювати жодні IDENTITY
стовпці та не мати майбутнього ризику перекриття.
ДРУГО, частина 3
Останньою варіантом такого підходу було б можливо замінити IDENTITY
стовпці і замість цього використовувати послідовності . Причина застосовувати такий підхід полягає в тому, щоб мати можливість додатка коду вставляти значення, які: позитивні, вище автоматично сформованого діапазону (не нижче), і не потрібно SET IDENTITY_INSERT ON / OFF
.
У такому підході вам просто потрібно:
- Створіть послідовності, використовуючи CREATE SEQUENCE
Скопіюйте IDENTITY
стовпець у новий стовпець, який не має IDENTITY
властивості, але має DEFAULT
обмеження, використовуючи функцію NEXT VALUE FOR :
PkId INT PRIMARY KEY CONSTRAINT [DF_TableName_NextID] DEFAULT (NEXT VALUE FOR...)
Це додає 0 байтів у кожен рядок, а не 8 або навіть 12.
- Початковий діапазон значень, створених додатком, буде набагато вище того, що, на вашу думку, наблизиться автоматично створених значень.
- Оберніть код програми ВСТАВЛЕННЯ в
SET IDENTITY_INSERT {table_name} ON;
і SET IDENTITY_INSERT {table_name} OFF;
заяви.
ВІДПОВІДЬ , через вимогу, що код з будь-якою SCOPE_IDENTITY()
або @@IDENTITY
все-таки функціонує належним чином, перехід на послідовності наразі не є варіантом, оскільки, здається, немає еквівалента цих функцій для послідовностей :-(. Сумно!