REVISIÓN: Una instrucción MERGE puede imponer una restricción foreign key cuando la instrucción actualiza una columna de clave única que no forma parte de una clave de agrupación y no hay una sola fila como origen de actualización de SQL Server 2008

Nº de error: 50003167 (revisión SQL)
Para obtener más información acerca de la lista maestra de generaciones que se publicaron después del lanzamiento de SQL, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

957826 donde encontrará más información sobre la versión SQL Server 2008 generaciones que se publicaron después de SQL Server 2008 y compilaciones de SQL Server 2005 que se publicaron después de SQL Server 2005 Service Pack 2

Síntomas

En Microsoft SQL Server 2008, una restricción foreign key puede no aplicarse cuando se cumplen las condiciones siguientes:
  • Se emite una instrucción MERGE.
  • La columna de destino de la actualización tiene un índice único no agrupado.
Considere el siguiente escenario. La instrucción actualiza una columna única denominada Columna1 de una tabla denominada tabla1. Tabla1 hace referencia a una restricción foreign key de una tabla denominada tabla2.

El resultado es que las filas en Table1 se modifican cuando no debería haber sido. Además, tabla2 tendrán filas que tienen referencias pendientes a tabla1.

Este problema se produce en este escenario, cuando se cumplen las condiciones siguientes:
  • La columna referenciada de Columna1 en Table1 no forma parte de la clave de agrupación de la tabla1.
  • Un único valor posible puede asignarse a la columna de la columna 1 . Por ejemplo, produce una de las siguientes situaciones:
    • El origen de la combinación es una sola fila de datos. Por ejemplo, el origen de combinación es una de las siguientes instrucciones select:
      • select <ConstantValues>
      • select <Parameters>
      Nota: Este escenario es el escenario más probable.
    • El origen de combinación es realmente una sola fila de datos. Por ejemplo, el origen de combinación es una de las siguientes instrucciones select:
      • select <ColumnName> from <TableName> where <TableName>.<ColumnName> = 1
        Nota: < nombreTabla >. < nombreColumna > se conoce por el optimizador de consultas para ser un valor único.
      • select top 1 <ColumnName> from <TableName>
    • La combinación entre el origen de la combinación y el destino de combinación tiene un predicado que garantiza que se actualizará una sola fila.
    • La cláusula update establece la columna de la columna 1 con un valor constante, independientemente del origen de la combinación.
  • La opción Cascade en la actualización no está activada en la restricción foreign key en tabla2.
Nota: Se recomienda aplicar esta revisión si utiliza la instrucción MERGE para actualizar las columnas que tienen índices únicos no agrupados que hacen referencia las restricciones foreign key.

Solución

La corrección para este problema en primer lugar se publicó en la actualización acumulativa 1. Para obtener más información acerca de cómo obtener este paquete de actualización acumulativa para SQL Server 2008, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

Paquete 1 de actualización de 956717 acumulativa para SQL Server 2008

Nota: Como las compilaciones son acumulativas, cada versión de corrección nueva contiene todas las revisiones y revisión de todas las revisiones de seguridad que se incluyeron con la anterior de SQL Server 2008. Le recomendamos que considere aplicar la versión más reciente de revisión que contenga este hotfix. Para obtener más información, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

956909 the SQL Server 2008 generaciones que se publicaron después del lanzamiento de SQL Server 2008

Solución alternativa

El paquete de hotfix elimina el problema. Si utiliza la instrucción MERGE en la situación que se describe en la sección "Síntomas" y si elige no aplicar la revisión, siga estos pasos para eliminar este problema:
  1. Vuelva a escribir la instrucción MERGE para que los valores de origen de combinación estén en una tabla, tabla temporal o variable de tabla en lugar de en línea en la consulta.
  2. Utilice el indicador de traza 8790. Este indicador de traza obliga al optimizador a utilizar un tipo de plan que se llama un plan de actualización. Planes amplios de actualización no tienen el problema. Este paso conlleva riesgos de rendimiento de todas las instrucciones DML. Por lo tanto, debe evitar el uso de este paso a menos que sea imposible cambiar la aplicación.
La secuencia de comandos de Transact-SQL siguiente muestra una forma de cambiar la secuencia de comandos para resolver este problema si no puede aplicar este hotfix.

Por ejemplo, tiene una secuencia de comandos similar al siguiente:
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);

Cambiar la secuencia de comandos para que se asemeje a la siguiente:
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);

Estado

Microsoft ha confirmado que se trata de un problema de los productos de Microsoft que se enumeran en la sección "Aplicable a".

Más información

Para obtener más información acerca de qué archivos se cambian y para obtener información acerca de los requisitos previos para aplicar el paquete de actualización acumulativa que contiene la revisión que se describe en este artículo de Microsoft Knowledge Base, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
Paquete 1 de actualización de 956717 acumulativa para SQL Server 2008

Referencias

Para obtener más información acerca de la lista de compilaciones disponibles después del lanzamiento de SQL Server 2008, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

956909 the SQL Server 2008 generaciones que se publicaron después del lanzamiento de SQL Server 2008



Para obtener más información sobre el modelo de servicio Incremental de SQL Server, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

935897 un modelo de servicio Incremental está disponible en el equipo de SQL Server para entregar revisiones para problemas detectados



Para obtener más información acerca del esquema de nomenclatura para las actualizaciones de SQL Server, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

822499 Nuevo esquema de nomenclatura para los paquetes de actualización de software de Microsoft SQL Server


Para obtener más información acerca de la terminología de la actualización de software, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
824684 descripción de la terminología estándar que se utiliza para describir las actualizaciones de software de Microsoft

Referencias

Para obtener más información acerca de los índices no agrupados en SQL Server 2008, visite el siguiente sitio Web de Microsoft Developer Network (MSDN):
Propiedades

Id. de artículo: 956718 - Última revisión: 14 ene. 2017 - Revisión: 1

Comentarios