获取外键多列的Postgresql查询

获取外键多列的Postgresql查询,postgresql,Postgresql,我有这个模式: 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"),

我有这个模式:

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")
);
我想从表“comment”到“cat”获取外键列表,因此我使用:

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' 

;
几乎得到了我想要的:

  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

但是有第1行和第4行,我想在结果中消除它们,因为它不反映列的依赖关系。如何在Postgresql中实现这一点?

我认为您不能仅使用
信息\u模式来实现这一点,但您可以直接查询表:

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
结果

  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

我认为您不能仅使用
信息\u模式
,但可以直接查询表:

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
结果

  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

我认为您应该选择引用中使用的列名列表作为一个整体:

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) 
但是,不确定列名的顺序是否正确,这取决于它们在信息模式中列出的方式

更可靠的解决方案是查询 函数
get\u col\u names()
定义如下:


我认为您应该选择引用中使用的列名列表作为一个整体:

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) 
但是,不确定列名的顺序是否正确,这取决于它们在信息模式中列出的方式

更可靠的解决方案是查询 函数
get\u col\u names()
定义如下:


referential\u约束。唯一的\u约束*
key\u列的用法。序号位置
列可用于将外部列与其引用列正确连接。看看这个答案

以下是我的精简版本:

SELECT
  rc.constraint_schema,
  rc.constraint_name,
  kcu.table_name,
  kcu.column_name,
  rcu.table_name AS referenced_table,
  rcu.column_name AS referenced_column
FROM information_schema.referential_constraints rc
LEFT JOIN information_schema.key_column_usage kcu
  ON rc.constraint_catalog = kcu.constraint_catalog
  AND rc.constraint_schema = kcu.constraint_schema
  AND rc.constraint_name = kcu.constraint_name
LEFT JOIN information_schema.key_column_usage rcu -- referenced columns
  ON rc.unique_constraint_catalog = rcu.constraint_catalog
  AND rc.unique_constraint_schema = rcu.constraint_schema
  AND rc.unique_constraint_name = rcu.constraint_name
  AND rcu.ordinal_position = kcu.position_in_unique_constraint;

编辑修复了
ordinal_位置
连接条件

引用的约束。唯一的约束*
键列的用法。可以使用ordinal_位置
列将外部列正确连接到其引用的列。看看这个答案

以下是我的精简版本:

SELECT
  rc.constraint_schema,
  rc.constraint_name,
  kcu.table_name,
  kcu.column_name,
  rcu.table_name AS referenced_table,
  rcu.column_name AS referenced_column
FROM information_schema.referential_constraints rc
LEFT JOIN information_schema.key_column_usage kcu
  ON rc.constraint_catalog = kcu.constraint_catalog
  AND rc.constraint_schema = kcu.constraint_schema
  AND rc.constraint_name = kcu.constraint_name
LEFT JOIN information_schema.key_column_usage rcu -- referenced columns
  ON rc.unique_constraint_catalog = rcu.constraint_catalog
  AND rc.unique_constraint_schema = rcu.constraint_schema
  AND rc.unique_constraint_name = rcu.constraint_name
  AND rcu.ordinal_position = kcu.position_in_unique_constraint;
编辑修复了
顺序位置
连接条件