sql >> Base de Datos >  >> RDS >> Mysql

Cómo usar claves foráneas con PHP

Desambiguación de restricciones/columnas de clave externa

Suponiendo que se está refiriendo a las restricciones de clave externa , la respuesta corta sería simplemente no los usas .

Y aquí viene el largo:

Estamos acostumbrados a referirnos a columnas como claves externas a otras mesas. Especialmente durante el proceso de normalización, frases como "user_purchase.i_id es una clave foránea para los items mesa" sería muy común. Si bien esa es una forma perfectamente válida de describir la relación, puede volverse un poco confuso cuando lleguemos a la fase de implementación.

Suponga que ha creado sus tablas sin la FOREIGN KEY cláusulas:

CREATE TABLE user(
  id INT(11) NOT NULL AUTO_INCREMENT,
  username VARCHAR(50) NOT NULL,
  password VARCHAR(20) NOT NULL,
  PRIMARY KEY (id)
);

CREATE TABLE items(
  i_id INT(11) NOT NULL AUTO_INCREMENT,
  name TINYTEXT NOT NULL,
  price DECIMAL(8,2) NOT NULL,
  PRIMARY KEY (i_id)
);

CREATE TABLE user_purchase(
  i_id INT(11) NOT NULL,
  name TINYTEXT NOT NULL,
  id INT(11) NOT NULL,
);

Observe que, en cuanto a la relación, las columnas de la clave foránea están todavía implementados . Hay una columna que hace referencia al user tabla (id ) y otro que hace referencia a los items tabla (i_id ) -- pongamos el name columna a un lado por un momento. Considere los siguientes datos:

  user              user_purchase    items
| id  username |    | id  i_id |    | i_id  name            price |
| 23  john     |    | 55   10  |    |  10   chocolate bar    3.42 |
| 55  mary     |    | 70   10  |    |  33   mobile phone    82.11 |
| 70  fred     |    | 70   33  |    |  54   toothpaste       8.67 |
                    | 55   10  |    |  26   toy car          6.00 |
                    | 70   26  |

La relación está ahí. Se implementa mediante el user_purchase tabla, que contiene información sobre quién compró qué . Si tuviéramos que consultar la base de datos para un informe relevante, haríamos:

select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)

Y así es como usamos la relación y las columnas de clave externa involucrado.

Ahora, ¿qué pasa si hacemos:

insert into user_purchase (id,i_id) values (23,99)

Aparentemente, esta es una entrada inválida. Aunque hay un usuario con id=23 , no hay ningún elemento con i_id=99 . El RDBMS permitiría que eso sucediera, porque no sabe nada mejor . Aún.

Ahí es donde la clave externa restricciones ven a jugar. Especificando FOREIGN KEY (i_id) REFERENCES items(i_id) en el user_purchase definición de la tabla, esencialmente le damos al RDBMS una regla a seguir:entradas con i_id valores que no están contenidos en items.i_id columna no son aceptables . En otras palabras, mientras una clave externa columna implementa la referencia , una clave foránea restricción hace cumplir la integridad referencial .

Tenga en cuenta, sin embargo, que el select anterior no cambiaría, solo porque definió una restricción FK. Por lo tanto, usted no use restricciones FK, RDBMS sí, para proteger sus datos.

Redundancias

Pregúntate:¿Por qué querrías eso? Si las dos claves foráneas tienen el mismo propósito, la redundancia eventualmente lo meterá en problemas. Considere los siguientes datos:

 user_purchase                   items
| id  i_id  name           |    | i_id  name            price |
| 55   10   chocolate bar  |    |  10   chocolate bar    3.42 |
| 70   10   chocolate bar  |    |  33   mobile phone    82.11 |
| 70   33   mobile phone   |    |  54   toothpaste       8.67 |
| 55   10   toothpaste     |    |  26   toy car          6.00 |
| 70   26   toy car        |

Qué está mal con esta imagen? ¿El usuario 55 comprar dos barras de chocolate, o una barra de chocolate y una pasta de dientes? Este tipo de ambigüedad puede generar un gran esfuerzo para mantener los datos sincronizados, lo que sería innecesario si solo mantuviéramos una de las claves externas. De hecho, ¿por qué no soltar el name columna por completo, ya que está implícito en la relación.

Por supuesto, podríamos resolver esto implementando una clave foránea compuesta, configurando PRIMARY KEY(i_id,name) para los items tabla (o definiendo un UNIQUE(i_id,name) adicional index, en realidad no importa) y luego establecer una FOREIGN KEY(i_id,name) REFERENCES items(i_id,name) . De esta forma, solo (i_id,name) parejas que existen en los items la tabla sería válida para user_purchases . Aparte del hecho de que todavía tendrías uno clave foránea , este enfoque es totalmente innecesario, siempre que el i_id columna ya es suficiente para identificar un elemento (no puedo decir lo mismo para el name columna...).

Sin embargo, no existe una regla contra el uso de múltiples claves externas en una tabla. De hecho, hay circunstancias que exigen tal enfoque. Considere una person(id,name) tabla y un parent(person,father,mother) uno, con los siguientes datos:

 person             parent
| id  name    |    | person  father  mother |
| 14  John    |    |   21      14      59   |
| 43  Jane    |    |   14      76      43   |
| 21  Mike    |
| 76  Frank   |
| 59  Mary    |

Obviamente, las tres columnas del parent table son claves foráneas para person . No para la misma relación , sin embargo, pero para tres diferentes :Dado que los padres de una persona también son personas, las dos columnas correspondientes deben hacer referencia a la misma tabla person hace. Tenga en cuenta, sin embargo, que los tres campos no solo pueden pero también tener que referir a otra person s en el mismo parent fila, ya que nadie es su propio padre y el padre de nadie es su madre también.