2009-03-21 11 views
81

Tengo dos tablas, a saber, employees_ce y employees_sn bajo los empleados de la base de datos.¿Clave externa que se refiere a claves principales en varias tablas?

Ambos tienen sus respectivas columnas de clave principal únicas.

Tengo otra tabla llamada deducciones, cuya columna de clave externa quiero hacer referencia a las claves principales de employees_ce y employees_sn. es posible?

por ejemplo

employees_ce 
-------------- 
empid name 
khce1 prince 

employees_sn 
---------------- 
empid name 
khsn1 princess 

así es esto posible?

deductions 
-------------- 
id  name 
khce1 gold 
khsn1 silver 

Respuesta

2

Técnicamente posible. Es probable que se refiera a los empleados en las deducciones y en los employees_sn. Pero ¿por qué no fusionas employees_sn y employees_ce? No veo ninguna razón por la que tengas dos mesas. No hay una relación entre muchos. Y (no en este ejemplo) muchas columnas.

Si hace dos referencias para una columna, un empleado debe tener tener una entrada en ambas tablas.

1

Sí, es posible. Deberá definir 2 FK para la 3ra mesa. Cada FK apunta al campo o campos obligatorios de una tabla (es decir, 1 FK por tabla externa).

21

Probablemente pueda agregar dos restricciones de clave externa (sinceramente: nunca lo intenté), pero luego insistiría en que la fila padre existe en ambas tablas.

En su lugar, es probable que desee crear un supertipo para sus dos subtipos de empleados, y luego señalar la clave externa en su lugar. (Suponiendo que tenga una buena razón para dividir los dos tipos de empleados, por supuesto).

    employee  
employees_ce  ————————  employees_sn 
————————————  type   ———————————— 
empid —————————> empid <——————— empid 
name    /|\   name 
        | 
        | 
     deductions | 
     —————————— | 
     empid ————————+ 
     name 

type en la tabla empleado habría ce o sn.

+0

He intentado añadir varias claves externas, las que trabajaban, pero, al tiempo que añade un registro, derby java me dice que ambas claves foráneas que se han violado! –

+0

Acabo de probarlo en PostgreSQL, y funciona allí. ¿Tuviste el registro principal en ambas tablas? – derobert

+0

padre de registros que quiere decir, el empid? –

87

Suponiendo que he comprendido su escenario correctamente, esto es lo que yo llamaría la derecha manera de hacer esto:

inicio de una descripción de alto nivel de su base de datos! Tiene empleados, y los empleados pueden ser empleados "ce" y empleados "sn" (cualquiera que sean). En términos orientados a objetos, hay un "empleado" de clase, con dos subclases llamadas "empleado ce" y "empleado sn".

Entonces Traducir esta descripción de alto nivel de tres tablas: employees, employees_ce y employees_sn:

  • employees(id, name)
  • employees_ce(id, ce-specific stuff)
  • employees_sn(id, sn-specific stuff)

Dado que todos los empleados son empleados (duh !), cada empleado tendrá una fila en el employees mesa. Los empleados "ce" también tienen una fila en la tabla employees_ce, y los empleados "sn" también tienen una fila en la tabla employees_sn. employees_ce.id es una clave externa a employees.id, al igual que employees_sn.id es.

Para referirse a un empleado de cualquier tipo (ce o sn), consulte la tabla employees. Es decir, ¡la clave externa con la que tuvo problemas debería referirse a esa tabla!

+12

¿Cómo se puede hacer que ce y sn sean mutuamente exclusivos? Dado que un empleado no puede ser al mismo tiempo ce y sn, sería una buena práctica reflejar eso en la base de datos. Estoy teniendo este problema ahora mismo. – Rolf

+0

Creo que las claves de columna múltiple podrían ayudar con el problema en mi comentario anterior ... buscando eso ahora mismo. – Rolf

+12

Puede obligar al empleado a estar en una sola de las tablas (y la correcta) al almacenar un tipo en la tabla base, así como en las tablas derivadas. Cree la identificación de la clave principal, una clave única (id, type), la clave foránea de las tablas secundarias esté activada (id, type) y coloque una restricción CHECK en cada tabla secundaria para que solo tenga el tipo correcto. O bien, si su base de datos tiene restricciones de verificación global (y sin una gran penalización de velocidad), puede, por supuesto, hacer una prueba NO EXISTE. – derobert

0

Suponiendo que usted debe tener dos tablas para los dos tipos de empleados, por alguna razón, me extiendo sobre la respuesta de vmarquez:

esquema:

employees_ce (id, name) 
employees_sn (id, name) 
deductions (id, parentId, parentType, name) 

Los datos de deducciones:

deductions table 
id  parentId  parentType  name 
1  1    ce    gold 
2  1    sn    silver 
3  2    sn    wood 
... 

Esto le permitiría tener deducciones apuntando a cualquier otra tabla en su esquema. Este tipo de relación no está respaldada por restricciones de nivel de base de datos, IIRC, por lo que deberá asegurarse de que su aplicación gestione correctamente la restricción (lo que lo hace más engorroso si tiene varias aplicaciones/servicios diferentes que llegan a la misma base de datos).

15

En realidad yo hago esto yo mismo. Tengo una tabla llamada 'Comentarios' que contiene comentarios para registros en otras 3 tablas. Ninguna de las soluciones realmente maneja todo lo que usted probablemente quiera. En su caso, usted podría hacer esto:

Solución 1:

  1. añadir un campo tinyint a employees_ce y employees_sn que tiene un valor por defecto que es diferente en cada mesa (Este campo representa un " table identifier ', así que los llamaremos tid_ce & tid_sn)

  2. Cree un índice único en cada tabla usando el PK de la tabla y el campo de identificación de la tabla.

  3. añadir un campo tinyint a su mesa 'deducciones' para almacenar la segunda mitad de la clave externa (el ID de la tabla)

  4. Crear 2 claves externas de la tabla 'deducciones' (No puede cumplir la integridad referencial, ya sea porque una de las claves será válido u otro ... pero nunca ambos:

    ALTER TABLE [dbo].[Deductions] WITH NOCHECK ADD CONSTRAINT [FK_Deductions_employees_ce] FOREIGN KEY([id], [fk_tid]) 
    REFERENCES [dbo].[employees_ce] ([empid], [tid]) 
    NOT FOR REPLICATION 
    GO 
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_ce] 
    GO 
    ALTER TABLE [dbo].[Deductions] WITH NOCHECK ADD CONSTRAINT [FK_Deductions_employees_sn] FOREIGN KEY([id], [fk_tid]) 
    REFERENCES [dbo].[employees_sn] ([empid], [tid]) 
    NOT FOR REPLICATION 
    GO 
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_sn] 
    GO 
    
    employees_ce 
    -------------- 
    empid name  tid 
    khce1 prince 1 
    
    employees_sn 
    ---------------- 
    empid name  tid 
    khsn1 princess 2 
    
    deductions 
    ---------------------- 
    id  tid  name 
    khce1 1   gold 
    khsn1 2   silver   
    ** id + tid creates a unique index ** 
    

solución 2: Esta solución permite la integridad referencial para ser ma intained: 1. Cree un segundo campo de clave externa de la tabla 'deducciones', permiten valores nulos en ambas claves externas, y crear las claves externas normales:

employees_ce 
    -------------- 
    empid name 
    khce1 prince 

    employees_sn 
    ---------------- 
    empid name  
    khsn1 princess 

    deductions 
    ---------------------- 
    idce idsn  name 
    khce1 *NULL* gold 
    *NULL* khsn1  silver   

de Integridad sólo se comprueba si la columna no es nulo, por lo puedes mantener la integridad referencial.

6

Sé que este es un tema estancado durante mucho tiempo, pero en caso de que alguien busque aquí, es como trato con claves externas de múltiples tablas. Con esta técnica no tiene operaciones en cascada aplicadas por el DBA, así que asegúrese de ocuparse de DELETE y demás en su código.

Table 1 Fruit 
pk_fruitid, name 
1, apple 
2, pear 

Table 2 Meat 
Pk_meatid, name 
1, beef 
2, chicken 

Table 3 Entity's 
PK_entityid, anme 
1, fruit 
2, meat 
3, desert 

Table 4 Basket (Table using fk_s) 
PK_basketid, fk_entityid, pseudo_entityrow 
1, 2, 2 (Chicken - entity denotes meat table, pseudokey denotes row in indictaed table) 
2, 1, 1 (Apple) 
3, 1, 2 (pear) 
4, 3, 1 (cheesecake) 

SO Ejemplo de Op se vería así

deductions 
-------------- 
type id  name 
1  khce1 gold 
2  khsn1 silver 

types 
--------------------- 
1 employees_ce 
2 employees_sn 
Cuestiones relacionadas