Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MS SQL Server > Восстановить IDENT_CURRENT(<table>)


Автор: Gwire 3.6.2016, 14:56
Здравствуйте.

Архитектура:
Имеется 2 сервера базы данных MS SQL Server 2012. 
По структуре обе базы данных, на этих серверах, почти идентичны. Отличаются только первичные ключи (id) записей.
  При создании таблиц были заданы разные IDENT_SEED 
  IDENTITY(101,100) для таблиц первой и
  IDENTITY(102,100) для таблиц второй
  Так все записи, если их свести в одно место, будут иметь уникальные id
Базы друг с другом на прямую не общаются.

Источник проблемы:
Иногда, клиентская программа дает запрос для базы 02: добавить запись, данные для которой вычитаны из базы 01. Id при этом должен быть добавлен без изменений.
Отключаю IDENTITY_INSERT. Добавляю запись. Включаю IDENTITY_INSERT.

Проблема:
SELECT IDENT_CURRENT(<table>) указывает id последней добавленной записи в таблицу. И этот id имеет суффикс базы 01, а не текущей (02). Оно и понятно... 
Но дальше происходит неприемлемое: При добавлении новой записи, для нее рассчитывается id на основе суффикса "01".

Вопрос:
* Как задать старый IDENT_CURRENT для таблицы? или
* Как не дать INSERT-у изменять IDENT_CURRENT (хотя тут скорее всего никак)

ПС: Сам я дошел только до метода, принудительно создать-удалить пустую запись с ключом  (старый-id + 100). Но мне этот метод не нравится.

Автор: Akina 3.6.2016, 15:26
Цитата(Gwire @  3.6.2016,  15:56 Найти цитируемый пост)
дальше происходит неприемлемое: При добавлении новой записи, для нее рассчитывается id на основе суффикса "01".

Ну вообще-то https://msdn.microsoft.com/ru-ru/library/ms188059(v=sql.110).aspx утверждает, что такое должно происходить только в случае, если значение ключевого поля добавленной записи больше текущего значения IDENTITY. 

Цитата(Gwire @  3.6.2016,  15:56 Найти цитируемый пост)
Как задать старый IDENT_CURRENT для таблицы?

Только через CREATE TABLE (в данном случае явно неприменимо) или ALTER TABLE.

Автор: Gwire 3.6.2016, 16:18
Цитата(Akina @  3.6.2016,  15:26 Найти цитируемый пост)
такое должно происходить только в случае, если значение ключевого поля добавленной записи больше текущего значения IDENTITY. 

Ну, ожидать, что все id будут меньше текущего значения IDENTITY... 
Скорее всего, по закону подлости (вернее по теории вероятности) такого счастья не будет.

Цитата(Akina @  3.6.2016,  15:26 Найти цитируемый пост)
или ALTER TABLE

Это через ALTER TABLE <table> ALTER COLUMN [id]?

Автор: Akina 3.6.2016, 16:41
Цитата(Gwire @  3.6.2016,  17:18 Найти цитируемый пост)
Это через ALTER TABLE <table> ALTER COLUMN [id]?

А что, есть другие варианты?

Но вообще ВСЁ тобой описываемое мне, например, активно не нравится. Особенно то, что клиенту даны права на DDL, чего бы и близко быть не должно. Так что поскольку случай копирования данных - достаточно "особый", думаю, не будет ничего удивительного, если для этого и код будет "особый". Тогда вставку в таблицу копии записи из второй таблицы лучше оформить хранимой процедурой - пусть именно её код и разрешением вставки в IDENTITY-поле занимается, и DDL выполняет.

Автор: Gwire 3.6.2016, 17:04
Так и сделано - через ХП.

Мне не ясно, что нужно после ALTER COLUMN писать. В доке только ADD и DROP

Автор: Akina 3.6.2016, 17:15
В том, что ИЗМЕНИТЬ его значение можно с помощью ALTER TABLE, я неправ. 

Покопался попристальнее... изменить его может только системная процедура
https://msdn.microsoft.com/en-us/library/ms176057(v=sql.110).aspx (<table_name>, reseed, <новое_значение>)

Автор: Gwire 3.6.2016, 17:17
ПО предварительным результатам решение найдено:
Код

DECLARE @OLD_SEED bigint = IDENT_CURRENT('<table_name>');

SET IDENTITY_INSERT <table_name> OFF
INSERT INTO <table_name> bla-bla-bla
SET IDENTITY_INSERT <table_name> ON

DBCC CHECKIDENT ('<table_name>', RESEED, @OLD_SEED);


Добавлено @ 17:21
Цитата(Akina @  3.6.2016,  17:15 Найти цитируемый пост)
Покопался попристальнее

Почти синхронно. Или даже не почти. smile

Для тех у кого возникнет такая же или похожая проблема - курить msdn по DBCC CHECKIDENT
https://msdn.microsoft.com/ru-ru/library/ms176057(v=sql.120).aspx

Автор: Akina 3.6.2016, 17:37
Осталось только обезопасить себя от вставки в другом сеансе...

Автор: Gwire 3.6.2016, 17:44
Цитата(Akina @  3.6.2016,  17:37 Найти цитируемый пост)
Осталось только обезопасить себя от вставки в другом сеансе... 

А изоляция таблицы не решит эту проблему?

Автор: Akina 3.6.2016, 18:34
Решит... но надо ли реально так строго? читать-то кому надо - пусть себе читают...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)