2012-08-15 12 views
53

A continuación, la estructura de la tabla de ejemplo proporciona un ERROR: no existe una restricción única que coincida con las claves para la tabla referenciada, y al haberla observado no puedo entender por qué surge este error en esta situación.¿Qué está causando ERROR: no hay una restricción única que coincida con las claves dadas para la tabla a la que se hace referencia?

BEGIN; 

CREATE TABLE foo (
    name    VARCHAR(256) PRIMARY KEY 
); 

CREATE TABLE bar(
    pkey  SERIAL PRIMARY KEY, 
    foo_fk  VARCHAR(256) NOT NULL REFERENCES foo(name), 
    name  VARCHAR(256) NOT NULL, 
    UNIQUE (foo_fk,name) 
); 

CREATE TABLE baz( 
    pkey   SERIAL PRIMARY KEY, 
    bar_fk   VARCHAR(256) NOT NULL REFERENCES bar(name), 
    name   VARCHAR(256) 
); 

COMMIT; 

ejecutar el código anterior muestra el siguiente error, lo que no tiene sentido para mí, ¿alguien puede explicar por qué surge este error. Estoy utilizando Postgres 9.1

NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "foo_pkey" for table "foo" 
NOTICE: CREATE TABLE will create implicit sequence "bar_pkey_seq" for serial column "bar.pkey" 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "bar_pkey" for table "bar" 
NOTICE: CREATE TABLE/UNIQUE will create implicit index "bar_foo_fk_name_key" for table "bar" 
NOTICE: CREATE TABLE will create implicit sequence "baz_pkey_seq" for serial column "baz.pkey" 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "baz_pkey" for table "baz" 
ERROR: there is no unique constraint matching given keys for referenced table "bar" 


********** Error ********** 

ERROR: there is no unique constraint matching given keys for referenced table "bar" 
SQL state: 42830 

Respuesta

63

Se debe a que la columna name sobre la mesa bar no tiene la ÚNICA restricción.

Así que imagine que tiene 2 filas en la tabla bar que contiene el nombre 'ams' y se inserta una fila en baz con 'ams' en bar_fk, que fila en bar sería refiriéndose ya que hay dos filas coincidentes?

42

en PostgreSQL todas las claves externas deben hacer referencia a una única clave de la tabla primaria, por lo que en su mesa bar debe tener un índice de unique (name).

Ver también http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK y en concreto:

Finally, we should mention that a foreign key must reference columns that either are a primary key or form a unique constraint.

El subrayado es mío.

+7

¿por qué la PK declarada no se considera una restricción única? no es como si tuvieras un PK no único ... – amphibient

+0

Debe ser único en la tabla al que "apunta", porque si no lo está, el motor de la base de datos no tendrá forma de saber a qué fila te estás refiriendo realmente. –

4

cuando haces UNIQUE como una restricción a nivel de tabla como lo han hecho después de lo que su definición es un poco como una clave principal compuesta ver ddl constraints, aquí es un extracto

"This specifies that the *combination* of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique." 

esto significa que cualquiera de los campos podría posiblemente tener un valor no único siempre que la combinación sea única y esto no coincida con su restricción de clave externa.

es muy probable que desee que la restricción esté a nivel de columna. entonces, en lugar de definirlos como restricciones de nivel de tabla, 'añada' UNIQUE al final de la definición de columna como name VARCHAR(60) NOT NULL UNIQUE o especifique las restricciones de nivel de tabla individuales para cada campo.

+0

La restricción de nivel de columna en mi situación no funcionará Realmente debería definir una clave primaria compuesta, pero me alejé de ella porque asignarla a JPA es un poco doloroso :) – ams

1

Debe tener la columna de nombre como una restricción única. He aquí un 3 líneas de código para cambiar sus problemas

1.En primer lugar averiguar las restricciones de clave principal de escribir este código

\ d nombre_tabla

se le muestra como esta en la parte inferior "some_constraint" PRIMARY KEY, btree (columna)

2.Drop la restricción:

ALTER TABLE nombre_tabla DROP CONSTRAINT some_constraint

3.Agregue una nueva columna de clave principal con la existente:

ALTER TABLE table_name ADD CONSTRAINT some_constraint PRIMARY KEY (COLUMN_NAME1, COLUMN_NAME2);

Eso es todo.

Cuestiones relacionadas