web-dev-qa-db-fra.com

Comment trouver toutes les tables qui ont des clés étrangères qui font référence à une table.colonne particulière et qui ont des valeurs pour ces clés étrangères?

J'ai une table dont la clé primaire est référencée dans plusieurs autres tables en tant que clé étrangère. Par exemple:

  CREATE TABLE `X` (
    `X_id` int NOT NULL auto_increment,
    `name` varchar(255) NOT NULL,
    PRIMARY KEY  (`X_id`)
  )
  CREATE TABLE `Y` (
    `Y_id` int(11) NOT NULL auto_increment,
    `name` varchar(255) NOT NULL,
    `X_id` int DEFAULT NULL,
    PRIMARY KEY  (`Y_id`),
    CONSTRAINT `Y_X` FOREIGN KEY (`X_id`) REFERENCES `X` (`X_id`)
  )
  CREATE TABLE `Z` (
    `Z_id` int(11) NOT NULL auto_increment,
    `name` varchar(255) NOT NULL,
    `X_id` int DEFAULT NULL,
    PRIMARY KEY  (`Z_id`),
    CONSTRAINT `Z_X` FOREIGN KEY (`X_id`) REFERENCES `X` (`X_id`)
  )

À présent, je ne sais pas combien de tables dans la base de données contiennent des clés étrangères dans X, comme les tables Y et Z. Existe-t-il une requête SQL que je peux utiliser pour renvoyer:

  1. Une liste de tables qui ont des clés étrangères dans X
  2. ET laquelle de ces tables a réellement des valeurs dans la clé étrangère
254
nebs

Voici:

USE information_schema;
SELECT *
FROM
  KEY_COLUMN_USAGE
WHERE
  REFERENCED_TABLE_NAME = 'X'
  AND REFERENCED_COLUMN_NAME = 'X_id';

Si vous avez plusieurs bases de données avec des noms de tables/colonnes similaires, vous pouvez également souhaiter limiter votre requête à une base de données particulière:

SELECT *
FROM
  KEY_COLUMN_USAGE
WHERE
  REFERENCED_TABLE_NAME = 'X'
  AND REFERENCED_COLUMN_NAME = 'X_id'
  AND TABLE_SCHEMA = 'your_database_name';
369
Alex N.

Manuel de référence MySQL 5.5: "Contraintes InnoDB et FOREIGN KEY"

SELECT
  ke.REFERENCED_TABLE_SCHEMA parentSchema,
  ke.referenced_table_name parentTable,
  ke.REFERENCED_COLUMN_NAME parentColumnName,
  ke.TABLE_SCHEMA ChildSchema,
  ke.table_name childTable,
  ke.COLUMN_NAME ChildColumnName
FROM
  information_schema.KEY_COLUMN_USAGE ke
WHERE
  ke.referenced_table_name IS NOT NULL
  AND ke.REFERENCED_COLUMN_NAME = 'ci_id' ## Find Foreign Keys linked to this Primary Key
ORDER BY
  ke.referenced_table_name;
57
Ovidiu

Cette solution affichera non seulement toutes les relations mais également le nom de la contrainte, qui est requis dans certains cas (par exemple, une contrainte de suppression):

SELECT
    CONCAT(table_name, '.', column_name) AS 'foreign key',
    CONCAT(referenced_table_name, '.', referenced_column_name) AS 'references',
    constraint_name AS 'constraint name'
FROM
    information_schema.key_column_usage
WHERE
    referenced_table_name IS NOT NULL;

Si vous souhaitez vérifier les tables d'une base de données spécifique, ajoutez les éléments suivants:

AND table_schema = 'database_name';
20
Panayotis

Vous pouvez trouver toutes les informations relatives au schéma dans la table judicieusement nommée information_schema.

Vous voudrez peut-être vérifier la table REFERENTIAL_CONSTRAINTS et KEY_COLUMN_USAGE. Le premier vous indique quelles tables sont référencées par d’autres; ces derniers vous diront comment leurs domaines sont liés.

14
Seb

Répertorier toutes les clés étrangères dans une base de données, y compris sa description

    SELECT  
    i1.CONSTRAINT_NAME, i1.TABLE_NAME,i1.COLUMN_NAME,
    i1.REFERENCED_TABLE_SCHEMA,i1.REFERENCED_TABLE_NAME, i1.REFERENCED_COLUMN_NAME,
    i2.UPDATE_RULE, i2.DELETE_RULE 
    FROM   
    information_schema.KEY_COLUMN_USAGE AS i1  
    INNER JOIN 
    information_schema.REFERENTIAL_CONSTRAINTS AS i2 
    ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME 
    WHERE i1.REFERENCED_TABLE_NAME IS NOT NULL  
    AND  i1.TABLE_SCHEMA  ='db_name';

restreindre à une colonne spécifique dans une table

AND i1.table_name = 'target_tb_name' AND i1.column_name = 'target_col_name'
4
bortunac

J'ai écrit un peu bash onliner que vous pouvez écrire dans un script pour obtenir une sortie conviviale:

mysql_references_to:

mysql -uUSER -pPASS -A DB_NAME -se "USE information_schema; SELECT * FROM KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME = '$1' AND REFERENCED_COLUMN_NAME = 'id'\G" | sed 's/^[ \t]*//;s/[ \t]*$//' |egrep "\<TABLE_NAME|\<COLUMN_NAME" |sed 's/TABLE_NAME: /./g' |sed 's/COLUMN_NAME: //g' | paste -sd "," -| tr '.' '\n' |sed 's/,$//' |sed 's/,/./'

Donc l'exécution: mysql_references_to transaccion (où transaccion est un nom de table aléatoire) donne une sortie comme celle-ci:

carrito_transaccion.transaccion_id
comanda_detalle.transaccion_id
comanda_detalle_devolucion.transaccion_positiva_id
comanda_detalle_devolucion.transaccion_negativa_id
comanda_transaccion.transaccion_id
cuenta_operacion.transaccion_id
...
3
jhvaras