2010-07-05 17 views
16

Esta pregunta es más o menos similar a this one, pero para SQL Server 2005:clave externa que hace referencia una clave principal 2 columnas en SQL Server

tengo 2 tablas en mi base de datos:

--'#' denotes the primary key 
[Libraries] 
#ID #Application Name 
1  MyApp  Title 1 
2  MyApp  Title 2 


[Content] 
#ID Application LibraryID Content 
10 MyApp  1   xxx 
11 MyApp  1   yyy 

(la la base de datos es, obviamente, mucho más compleja y tener esta doble clave tiene sentido)

Cada biblioteca se identifica por su ID único y nombre de aplicación. Estoy tratando de asegurarme de que cada contenido haga referencia de forma adecuada a una biblioteca existente.

Al crear la restricción (usando el Asistente) como

Primary key table   Foreign key table 
[Libraries]     [Content] 
ID     --->  LibraryID 
Application   --->  Application 

tengo el siguiente error:

The columns in table 'Libraries' do not match an existing primary key or UNIQUE constraint

¿Tiene alguna idea de lo que está pasando? y si es posible usar SQL Server? (No puedo modificar la tabla [Library] en absoluto)

¡Muchas gracias por su ayuda!

Respuesta

33

Por supuesto, es posible crear una relación de clave foránea con una clave primaria compuesta (más de una columna). Que no nos presenta la cuenta de que está utilizando para tratar de crear esa relación - que debe ser algo así como:

ALTER TABLE dbo.Content 
    ADD CONSTRAINT FK_Content_Libraries 
    FOREIGN KEY(LibraryID, Application) 
    REFERENCES dbo.Libraries(ID, Application) 

¿Es eso lo que estás usando ?? Si (ID, Application) es de hecho la clave principal en dbo.Libraries, esta afirmación definitivamente debería funcionar.

Luk: solo para verificar: ¿puede ejecutar esta declaración en su base de datos e informar cuál es el resultado?

SELECT 
    tc.TABLE_NAME, 
    tc.CONSTRAINT_NAME, 
    ccu.COLUMN_NAME 
FROM 
    INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc 
INNER JOIN 
    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu 
     ON ccu.TABLE_NAME = tc.TABLE_NAME AND ccu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME 
WHERE 
    tc.TABLE_NAME IN ('Libraries', 'Content') 
+0

Estaba usando la IU directamente en ese punto, pero el uso de la sintaxis genera el siguiente error: "No hay claves principales o candidatas en la tabla referenciada 'dbo.Libraries' que coincidan con la lista de columnas de referencia en la clave externa. .. – Luk

+0

Bueno, en ese caso, el par (Id, Aplicación) ** no ** es la clave primaria en la tabla de Bibliotecas. Solo se puede hacer referencia a la clave principal en una tabla padre - o una columna (o conjunto de columnas) que forman parte de un índice único. Consulte la tabla 'Bibliotecas' –

+0

Esa fue mi primera idea también, pero el script SQL especifica ' CREATE TABLE [Libraries] ('...' CONSTRAINT [PK_sf_Libraries] CLAVE PRIMARIA CLUSTERED ([Aplicación] ASC, [ID] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) EN [PRIMARY] '... (lo siento por dum ping todo el SQL aquí) – Luk

1

La tabla Content propensos a tener múltiples duplicados Application valores que no se pueden asignar a Libraries. ¿Es posible soltar la columna Application del Libraries Índice de clave principal y agregarla como Índice clave único?

+0

Sí, quizás duplicados para 'Application', pero nunca se requiere que sea único. El par de '(LibraryID, Application)' incluso puede tener múltiples valores, ¡ese no es el PK en la tabla 'Content', es el PK en la tabla' Libraries'! –

+0

OK, entonces, ¿qué sucede cuando tiene (LibraryID, Aplicación) de Contenido que no corresponde a (ID, Aplicación) en Bibliotecas? A partir de ahora, no hay ninguna restricción para hacer cumplir eso. Si OP no quiere cambiar la estructura actual, le sugiero que trate de crear un índice de clave única en (LibraryID, aplicación) y ver si se puede crear con éxito. Solo entonces, intenta crear la relación nuevamente. –

+0

Desafortunadamente, no puedo tocar 'Bibliotecas' en absoluto. Incluso se supone que las dos tablas tienen una relación de 1-1 porque no puedo agregar nuevas columnas a 'Libraries'. Tiene razón, se requiere un índice exclusivo allí (pero eso no solucionó el problema) – Luk

0

Tuve el mismo problema y creo que tengo la solución.

Si su campo Application en la tabla Library tiene una clave externa que hace referencia a un campo de otra tabla (denominada Application Apostaría), entonces su campo Application en la tabla Library tiene que tener una clave externa a la tabla Application también.

Después de eso puede hacer su clave foránea compuesta.

Disculpe mi pobre inglés, y lo siento si me equivoco.

7

Tenga en cuenta que los campos deben estar en el mismo orden. Si la clave principal a la que hace referencia se especifica como (Aplicación, ID), entonces su clave externa debe hacer referencia (Aplicación, ID) y NO (ID, Aplicación) ya que se consideran dos claves diferentes.

+0

sospecho que este es el problema también esp.ya que enumeró "Aplicación" primero en su Clave primaria def ("CLAVE PRIMARIA CLUSTER ([Aplicación] ASC, [ID] ASC)") en su "5 de julio a las 15:07" Comentario a la respuesta aceptada ("marc_s's en "Jul 5 '10 a 10:26") pero "ID" primero en sus dos ejemplos en su OP. No me sorprende nadie más (incluyendo los 500 (meñique a los labios) MIL más Rep'ed "marc_s") señaló eso en los 4 años 8 meses antes que usted. – Tom

0

La clave es "el orden de la columna debe ser el mismo"

Ejemplo:

create Table A (
    A_ID char(3) primary key, 
    A_name char(10) primary key, 
    A_desc desc char(50) 
) 

create Table B (
    B_ID char(3) primary key, 
    B_A_ID char(3), 
    B_A_Name char(10), 
    constraint [Fk_B_01] foreign key (B_A_ID,B_A_Name) references A(A_ID,A_Name) 
) 

el orden de las columnas en la tabla A debería ser ->A_ID entonces A_Name; la definición de la clave externa también debe seguir el mismo orden.

Cuestiones relacionadas