2017-09-04 7 views
0

Ich habe dieses Schema zu erhalten:Postgresql Abfrage Fremdschlüssel mehrspaltigen

create table "cat" (
    "name" varchar(64), 
    "owner" varchar(64), 
    primary key ("name", "owner") 
); 

create table "comment" (
    "name" varchar(45), 
    "owner" varchar(45), 
    "id" uuid, 
    "comment" text, 
    primary key ("id"), 
    foreign key ("name", "owner") references "cat"("name", "owner") 
); 

Ich möchte, um eine Liste von Fremdschlüsseln aus der Tabelle „Kommentar“ zu „cat“, so verwende ich:

SELECT 
    tc.constraint_name, tc.table_name, kcu.column_name, 
    ccu.table_name AS foreign_table_name, 
    ccu.column_name AS foreign_column_name 
FROM 
    information_schema.table_constraints AS tc 
    JOIN information_schema.key_column_usage AS kcu 
     ON tc.constraint_name = kcu.constraint_name 
    JOIN information_schema.constraint_column_usage AS ccu 
     ON ccu.constraint_name = tc.constraint_name 
WHERE constraint_type = 'FOREIGN KEY' 

; 

und bekam fast, was ich will:

constraint_name | table_name | column_name | foreign_table_name | foreign_column_name 
-------------------+------------+-------------+--------------------+--------------------- 
comment_name_fkey | comment | owner  | cat    | name 
comment_name_fkey | comment | name  | cat    | name 
comment_name_fkey | comment | owner  | cat    | owner 
comment_name_fkey | comment | name  | cat    | owner 

Aber es gibt Zeile 1 und Zeile 4, die ich mag würde im Ergebnis beseitigen, weil es nicht mi tut Richten Sie die Abhängigkeiten der Spalte aus. Wie kann ich es in Postgresql machen?

Antwort

1

Ich glaube, Sie nicht tun können, dass nur mit information_schema, aber man kann es direkt Tabellen tun Abfrage:

SELECT conname AS constraint_name, conrelid::regclass AS table_name, ta.attname AS column_name, 
     confrelid::regclass AS foreign_table_name, fa.attname AS foreign_column_name 
    FROM (
    SELECT conname, conrelid, confrelid, 
      unnest(conkey) AS conkey, unnest(confkey) AS confkey 
    FROM pg_constraint 
    WHERE conname = 'comment_name_fkey' 
     --and contype = 'f' 
) sub 
    JOIN pg_attribute AS ta ON ta.attrelid = conrelid AND ta.attnum = conkey 
    JOIN pg_attribute AS fa ON fa.attrelid = confrelid AND fa.attnum = confkey 

Ergebnis

constraint_name | table_name | column_name | foreign_table_name | foreign_column_name 
-------------------+------------+-------------+--------------------+--------------------- 
comment_name_fkey | comment | name  | cat    | name 
comment_name_fkey | comment | owner  | cat    | owner 
1

Ich denke, Ihnen eine Liste der Spaltennamen wählen sollten in einer Referenz als Ganzes verwendet:

SELECT 
    tc.constraint_name, 
    tc.table_name, 
    string_agg(distinct kcu.column_name, ', ') AS column_names, 
    ccu.table_name AS foreign_table_name, 
    string_agg(distinct ccu.column_name, ', ') AS foreign_column_names 
FROM 
    information_schema.table_constraints AS tc 
    JOIN information_schema.key_column_usage AS kcu 
     ON tc.constraint_name = kcu.constraint_name 
    JOIN information_schema.constraint_column_usage AS ccu 
     ON ccu.constraint_name = tc.constraint_name 
WHERE constraint_type = 'FOREIGN KEY' 
    AND tc.table_name = 'comment' 
GROUP BY 1, 2, 4; 

    constraint_name | table_name | column_names | foreign_table_name | foreign_column_names 
-------------------+------------+--------------+--------------------+---------------------- 
comment_name_fkey | comment | name, owner | cat    | name, owner 
(1 row) 

Allerdings ist es nicht sicher, dass die Spaltennamen wird in der richtigen Reihenfolge sein, es hängt davon ab, wie sie in information_schema aufgeführt sind.

Die zuverlässigere Lösung ist, die system catalog pg_constraint. Die Funktion get_col_names() zur Abfrage wird hier definiert: List all foreign keys PostgresSQL.

select 
    conname as constraint_name, 
    conrelid::regclass as table_name, 
    get_col_names(conrelid, conkey) as column_names, 
    confrelid::regclass as foreign_table_name, 
    get_col_names(confrelid, confkey) as foreing_column_names 
from pg_constraint 
where contype ='f' 
and conrelid = 'comment'::regclass; 

    constraint_name | table_name | column_names | foreign_table_name | foreing_column_names 
-------------------+------------+--------------+--------------------+---------------------- 
comment_name_fkey | comment | name, owner | cat    | name, owner 
(1 row)