2010-12-15 42 views
40

Tengo dos tablas en dos bases de datos diferentes. En la tabla 1 (está en database1) hay una columna llamada column1 y es una clave principal. Ahora en la tabla 2 (está en databse2) hay una columna llamada coulmn2 y quiero agregarla como una clave externa.Agregar relación de clave externa entre dos bases de datos

He intentado añadir él y me dio el siguiente error:

Msg 1763, Level 16, State 0, Line 1
Cross-database foreign key references are not supported. Foreign key Database2.table2.

Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.

Cómo hacer yo hacer eso ya que las mesas están en diferentes bases de datos.

Respuesta

40

Debería gestionar la restricción referencial en las bases de datos utilizando un desencadenador.


Básicamente se crea una inserción, activador de actualización para verificar la existencia de la clave en la tabla de la clave principal. Si la clave no existe, invierta la inserción o actualización y luego maneje la excepción.

Ejemplo:

Create Trigger dbo.MyTableTrigger ON dbo.MyTable, After Insert, Update 
As 
Begin 

    If NOT Exists(select PK from OtherDB.dbo.TableName where PK in (Select FK from inserted) BEGIN 
     -- Handle the Referential Error Here 
    END 

END 

Editado: sólo para aclarar. Este no es el mejor enfoque para imponer la integridad referencial. Lo ideal es que desee ambas tablas en el mismo db, pero si eso no es posible. Entonces lo anterior es una posible solución para ti.

+0

Puede explicarme con un ejemplo – Sam

+0

De manera similar, también tengo que crear el Desencadenador de actualizaciones. – Sam

+0

@Sam Sí ... pero puede crear un disparador para Insertar y actualizar. Vea mi respuesta editada –

0

Como dice el mensaje de error, esto no es compatible con el servidor sql. La única manera de garantizar la integridad refrerencia es trabajar con desencadenadores.

+0

¿Puede explicarme con un ejemplo – Sam

3

La respuesta corta es que SQL Server (a partir de SQL 2008) no admite claves externas de bases de datos cruzadas, como indica el mensaje de error.

Si bien no puede tener integridad referencial declarativa (el FK), puede alcanzar el mismo objetivo utilizando activadores. Es un poco menos confiable, porque la lógica que usted escribe puede tener errores, pero de todos modos lo hará llegar allí.

Consulte la documentación de SQL @http://msdn.microsoft.com/en-us/library/aa258254%28v=sql.80%29.aspx Qué estado:

Triggers are often used for enforcing business rules and data integrity. SQL Server provides declarative referential integrity (DRI) through the table creation statements (ALTER TABLE and CREATE TABLE); however, DRI does not provide cross-database referential integrity. To enforce referential integrity (rules about the relationships between the primary and foreign keys of tables), use primary and foreign key constraints (the PRIMARY KEY and FOREIGN KEY keywords of ALTER TABLE and CREATE TABLE). If constraints exist on the trigger table, they are checked after the INSTEAD OF trigger execution and prior to the AFTER trigger execution. If the constraints are violated, the INSTEAD OF trigger actions are rolled back and the AFTER trigger is not executed (fired).

También hay una discusión OK encima en SQLTeam - http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=31135

22

Si necesita roca sólida integridad, tener las dos tablas en una base de datos, y usa una restricción FK. Si su tabla primaria está en otra base de datos, nada impide que alguien restaure esa base de datos primaria de una copia de seguridad anterior, y luego tiene huérfanos.

Esta es la razón por la que no se admite FK entre bases de datos.

20

En mi experiencia, la mejor manera de manejar esto cuando la principal fuente autorizada de información para dos tablas que están relacionadas tiene que estar en dos bases de datos separadas es sincronizar una copia de la tabla desde la ubicación principal a la secundaria (utilizando T-SQL o SSIS con la comprobación de errores adecuada: no puede truncar y volver a llenar una tabla mientras tiene una referencia de clave externa, por lo que hay algunas maneras de descartar la actualización de la tabla).

A continuación, agregue una relación FK tradicional en la segunda ubicación a la tabla que es efectivamente una copia de solo lectura.

Puede utilizar un disparador o un trabajo programado en la ubicación principal para mantener la copia actualizada.

+0

Re. "Puede desencadenar o programar un trabajo en la ubicación principal para mantener la copia actualizada": ¿por qué no simplemente usar la replicación de SQL Server (específicamente el tipo Transacción vs. Merge desde la copia del Suscriptor (la copia que tiene las Tablas que necesitan Restricciones de clave externa) solo debe ser de solo lectura)? Ver: [enlace] (https://docs.microsoft.com/en-us/sql/relational-databases/replication/sql-server-replication) – Tom

+0

@Tom sí, ciertamente puede usar la replicación para guardar una copia del tabla actualizada en una base de datos remota. –

11

Puede usar la restricción de verificación con una función definida por el usuario para realizar la comprobación. Es más confiable que un disparador. Se puede desactivar y reactivar cuando sea necesario, al igual que las claves externas y volver a verificar después de una restauración de la base de datos2.

CREATE FUNCTION dbo.fn_db2_schema2_tb_A 
(@column1 INT) 
RETURNS BIT 
AS 
BEGIN 
    DECLARE @exists bit = 0 
    IF EXISTS (
     SELECT TOP 1 1 FROM DB2.SCHEMA2.tb_A 
     WHERE COLUMN_KEY_1 = @COLUMN1 
    ) BEGIN 
     SET @exists = 1 
     END; 
     RETURN @exists 
END 
GO 

ALTER TABLE db1.schema1.tb_S 
    ADD CONSTRAINT CHK_S_key_col1_in_db2_schema2_tb_A 
    CHECK(dbo.fn_db2_schema2_tb_A(key_col1) = 1) 
Cuestiones relacionadas