SQL Server. Истории о данных: случай с фантомным дубликатом. Часть II
Содержание:
1. Часть I;
2.Часть II (Вы читаете данный раздел);
3. Часть III.
Время от времени Мэри должна вводить новые контрольные значения в одну и ту же таблицу во всех четырех копиях базы данных. Предположим, ей нужно было ввести новое название страны в таблицу Countries. Самое молодое государство в мире — Южный Судан. Давайте возьмем для примера эту страну.
На каждом сервере Мэри приходится выполнять следующий запрос:
Похоже, что в режиме SQLCMD эта проблема решается просто. Мэри написала сценарий, который приведен в коде выше.
Когда этот сценарий выполнялся внутри базы данных ReferenceData на сервере DevServer, появилось сообщение об ошибке (см. скриншот выше). Таблица была определена так, как показано в коде выше.


Результат проверки
Мэри была озадачена: она была убеждена, что эти данные еще не были представлены в таблице, но было ясно, что ограничительное условие на уникальность для столбца LonglSOCode не соблюдается. Быстрая проверка показала, что Мэри была права (результат показан на скриншоте выше):
Всякий раз, когда Мэри выполняла данный сценарий, на экране появлялось сообщение о том, что эти сведения уже содержатся в таблице. Пришло время разобраться с тем, что же, собственно, происходит. Когда я сталкиваюсь с нарушениями первичного ключа или с нарушениями уникальных ограничительных условий, то исхожу из того, что обычно существует л ишь две возможности:
• вводимые оператором данные уже представлены в таблице;
• оператор пытается ввести данные неоднократно; возможно, это происходит внутри одной и той же инструкции.
Мы знаем, что первый вариант объяснения в данном случае не подходит, так что мы имеем дело со вторым вариантом. Но как операции INSERT могут приводить к неоднократному введению одного и того же значения?
Все дело в том, каким именно образом среда SQL Server Management Studio (SSMS) осуществляет обработку пакетов. Сценарий T-SQL может включать в себя один или несколько пакетов. Оператор GO в сущности не является оператором T-SQL, это разделитель пакетов. Поэтому, когда вы выполняете такой, например, сценарий T-SQL:
Среда SSMS не направляет процессору базы данных весь текст сценария. Она выявляет все разделители GO и с их помощью разбивает сценарий на фрагменты. Может показаться, что весь сценарий выполняется «за один проход», но это не так. На сервер направляется и выполняется сначала команда SELECT @@ VERSION; затем направляется на сервер и выполняется команда SELECT @@SERVERNAME; и, наконец, на сервер направляется и выполняется команда SELECT GET DATE ();.
Пытались выполнить представленный выше сценарий T-SQL на локальной машине, но ваш компьютер завис и наотрез отказался включаться? В этом случае вам поможет только опытный мастер, чья основная специализация - ремонт ноутбуков (http://asu-surgut.ru/services/computer-repair). Такого специалиста вы сможете найти, к примеру, на asu-surgut.ru.
1. Часть I;
2.
3. Часть III.
Время от времени Мэри должна вводить новые контрольные значения в одну и ту же таблицу во всех четырех копиях базы данных. Предположим, ей нужно было ввести новое название страны в таблицу Countries. Самое молодое государство в мире — Южный Судан. Давайте возьмем для примера эту страну.
На каждом сервере Мэри приходится выполнять следующий запрос:
INSERT ReferenceData.dbo.Countries
(CountryName, ShortISOCode, LongISOCode, PhonePrefix)
VALUES (N'South Sudan', N'SS', N'SSD', N'211');Похоже, что в режиме SQLCMD эта проблема решается просто. Мэри написала сценарий, который приведен в коде выше.
Когда этот сценарий выполнялся внутри базы данных ReferenceData на сервере DevServer, появилось сообщение об ошибке (см. скриншот выше). Таблица была определена так, как показано в коде выше.


Результат проверки
Мэри была озадачена: она была убеждена, что эти данные еще не были представлены в таблице, но было ясно, что ограничительное условие на уникальность для столбца LonglSOCode не соблюдается. Быстрая проверка показала, что Мэри была права (результат показан на скриншоте выше):
SELECT *
FROM dbo.Countries
WHERE LongISOCode = 'SSD';Всякий раз, когда Мэри выполняла данный сценарий, на экране появлялось сообщение о том, что эти сведения уже содержатся в таблице. Пришло время разобраться с тем, что же, собственно, происходит. Когда я сталкиваюсь с нарушениями первичного ключа или с нарушениями уникальных ограничительных условий, то исхожу из того, что обычно существует л ишь две возможности:
• вводимые оператором данные уже представлены в таблице;
• оператор пытается ввести данные неоднократно; возможно, это происходит внутри одной и той же инструкции.
Мы знаем, что первый вариант объяснения в данном случае не подходит, так что мы имеем дело со вторым вариантом. Но как операции INSERT могут приводить к неоднократному введению одного и того же значения?
Все дело в том, каким именно образом среда SQL Server Management Studio (SSMS) осуществляет обработку пакетов. Сценарий T-SQL может включать в себя один или несколько пакетов. Оператор GO в сущности не является оператором T-SQL, это разделитель пакетов. Поэтому, когда вы выполняете такой, например, сценарий T-SQL:
SELECT @@VERSION;
GO
SELECT @@SERVERNAME;
GO
SELECT GETDATE();
GOСреда SSMS не направляет процессору базы данных весь текст сценария. Она выявляет все разделители GO и с их помощью разбивает сценарий на фрагменты. Может показаться, что весь сценарий выполняется «за один проход», но это не так. На сервер направляется и выполняется сначала команда SELECT @@ VERSION; затем направляется на сервер и выполняется команда SELECT @@SERVERNAME; и, наконец, на сервер направляется и выполняется команда SELECT GET DATE ();.
Пытались выполнить представленный выше сценарий T-SQL на локальной машине, но ваш компьютер завис и наотрез отказался включаться? В этом случае вам поможет только опытный мастер, чья основная специализация - ремонт ноутбуков (http://asu-surgut.ru/services/computer-repair). Такого специалиста вы сможете найти, к примеру, на asu-surgut.ru.