Ошибка #: 50003167 (исправление SQL)
Дополнительные сведения о master списке сборок, выпущенных после выпуска SQL, см. в следующей статье базы знаний Майкрософт:
957826 Здесь можно найти дополнительные сведения о сборках SQL Server 2008, выпущенных после SQL Server 2008 г., и сборках SQL Server 2005 г., выпущенных после SQL Server 2005 с пакетом обновления 2 (SP2)
Проблема
В Microsoft SQL Server 2008 ограничение внешнего ключа может не применяться, если выполняются следующие условия:
- Выдается заявление MERGE.
- Целевой столбец обновления имеет некластеризованный уникальный индекс.
Рассмотрим следующий сценарий. Инструкция обновляет уникальный столбец с именем Column1 таблицы с именем Table1. На таблицу 1 ссылается ограничение внешнего ключа из таблицы с именем Table2.
В результате строки в таблице Table1 изменяются, когда этого не должно быть. Кроме того, в таблице Таблица2 будут строки с висячими ссылками на таблицу 1.
Данная проблема возникает при выполнении следующих условий.
Указанный столбец "Столбец1" в таблице "Таблица1" не является частью ключа кластеризации таблицы 1.
Столбцу Column1 можно назначить только одно возможное значение. Например, может произойти один из следующих сценариев:
Источником слияния является одна строка данных. Например, источником слияния является одна из следующих операторов select:
-
select <ConstantValues> -
select <Parameters>
Примечание. Этот сценарий наиболее вероятен.
-
Источником слияния фактически является одна строка данных. Например, источником слияния является одна из следующих операторов select:
-
select <ColumnName> from <TableName> where <TableName>.<ColumnName> = 1Note <TableName>.<Оптимизатор запросов называет ColumnName> уникальным значением.
-
select top 1 <ColumnName> from <TableName>
-
Объединение источника и целевого объекта слияния имеет предикат, который гарантирует обновление одной строки.
Предложение update устанавливает для столбца Column1 постоянное значение независимо от источника слияния.
Параметр Каскад обновления не включен для ограничения внешнего ключа в таблице 2.
Примечание. Это исправление рекомендуется применить, если вы используете инструкцию MERGE для обновления столбцов с некластеризованными уникальными индексами, на которые ссылаются ограничения внешних ключей.
Решение
Исправление для этой проблемы впервые выпущено в накопительном пакете обновления 1. Для получения дополнительных сведений о том, как получить этот накопительный пакет обновления для SQL Server 2008, откройте статью со следующим номером в базе знаний Майкрософт:
956717 Накопительный пакет обновления 1 за SQL Server 2008 г.
Примечание. Поскольку сборки являются накопительными, каждый новый выпуск исправления содержит все исправления и исправления безопасности, которые были включены в предыдущий выпуск исправления SQL Server 2008. Рекомендуется рассмотреть возможность применения последнего выпуска исправления, содержащего это исправление. Для просмотра статьи в базе знаний Майкрософт щелкните следующий номер статьи:
956909 Сборки SQL Server 2008 г., выпущенные после выпуска SQL Server 2008 г.
Временное решение
Пакет исправлений устраняет проблему. Если оператор MERGE используется в сценарии, описанном в разделе "Симптомы", и исправление не применяется, выполните следующие действия, чтобы устранить эту проблему:
Перепишите инструкцию MERGE так, чтобы значения для источника слияния находились в таблице, временной таблице или табличной переменной, а не были встроены в запрос.
Использовать флаг трассировки 8790. Этот флаг трассировки заставляет оптимизатор использовать своего рода план, который называется расширенным планом обновления. Широкие планы обновления не содержат этой проблемы. Этот шаг несет в себе риски для производительности всех инструкций DML. Поэтому следует избегать использования этого шага, если нет возможности изменить приложение.
Следующий сценарий Transact-SQL показывает один из способов изменения сценария для устранения этой проблемы, если вы не можете применить это исправление.
Например, у вас есть сценарий, который выглядит примерно так:
use tempdb;
drop table sale, product;
create table product(pno int not null primary key, name char(30), pAlternateKey char(6) not null unique);
create table sale(sno int not null primary key, pAlternateKey char(6) not null references product(pAlternateKey));
insert product values(1, 'Office Chair', 'ochair');
insert sale values(1, 'ochair')
-- No violation of foreign key constraint is detected. However, one should be.
merge into product
using (select 'Office Chair2' as name, 1 as pno, 'oxx' as pAlternateKey) as src
on product.pno = src.pno
when matched then
update set product.pAlternateKey = src.pAlternateKey,
product.name = src.name
when not matched then
insert values(src.pno, src.name, src.pAlternateKey);
Измените сценарий так, чтобы он выглядел примерно так:
insert product values(1, 'Office Chair', 'ochair');
insert sale values(1, 'ochair')
-- A foreign key constraint violation is detected, and the update fails.
declare @source table
(name nchar(30), pno int, pAlternateKey nchar(30));
insert into @source values('Office Chair2',1,'oxx');
merge into product
using @source as src
on product.pno = src.pno
when matched then
update set product.pAlternateKey = src.pAlternateKey,
product.name = src.name
when not matched then
insert values(src.pno, src.name, src.pAlternateKey);
Состояние
Корпорация Майкрософт подтвердила, что это проблема продуктов Microsoft, перечисленных в разделе «Относится к».
Дополнительные сведения
Для получения дополнительных сведений о том, какие файлы изменены, и о предварительных требованиях для применения накопительного пакета обновления, содержащего исправление, описанное в этой статье базы знаний Майкрософт, щелкните номер статьи со следующим номером в базе знаний Майкрософт:
956717 Накопительный пакет обновления 1 за SQL Server 2008 г.
Ссылки
Дополнительные сведения о списке сборок, доступных после выпуска SQL Server 2008, см. в следующей статье базы знаний Майкрософт:
956909 Сборки SQL Server 2008 г., выпущенные после выпуска SQL Server 2008 г.
Дополнительные сведения о модели добавочного обслуживания для SQL Server см. в следующей статье базы знаний Майкрософт:
935897 Команда SQL Server предоставляет модель добавочного обслуживания для предоставления исправлений для обнаруженных проблем
Дополнительные сведения о схеме именования для обновлений SQL Server см. в следующей статье базы знаний Майкрософт:
822499 Новая схема именования пакетов обновления программного обеспечения Microsoft SQL Server
Дополнительные сведения о терминологии обновления программного обеспечения см. в следующей статье базы знаний Майкрософт:
824684 Стандартные термины, используемые при описании обновлений программного обеспечения Майкрософт
Некластеризованные индексы в SQL Server 2008
Дополнительные сведения о некластеризованных индексах в SQL Server 2008 см. на следующем веб-сайте Microsoft Developer Network (MSDN):