如何检索和PostgreSQL外键的信息

问题描述 投票:1回答:1

我想正是MySQL的复制上返回FKS从INFORMATION_SCHEMA表中提取它们的信息的方式。

我对MySQL的这些表:

create table test.subjects (
  ID_SUBJECT bigint NOT NULL AUTO_INCREMENT,
  FULL_NAME varchar(200) NOT NULL,
  PRIMARY KEY (ID_SUBJECT)
);

create table test.request_state (   
  ID_REQUEST_STATE char(3) NOT NULL,  
  DESCRIPTION varchar(80) NOT NULL,
  PRIMARY KEY (ID_REQUEST_STATE)
);

create table test.subject_profiles (    
  ID_SUBJECT_PROFILES bigint NOT NULL AUTO_INCREMENT,
  ID_SUBJECT bigint NOT NULL,
  ID_PROFILE bigint,    
  PRIMARY KEY (ID_SUBJECT_PROFILES)
);

CREATE UNIQUE INDEX subject_profiles_uq1
ON test.subject_profiles (ID_SUBJECT, ID_PROFILE);

ALTER TABLE test.subject_profiles add  
  CONSTRAINT subject_profiles_fk1
    foreign key (ID_SUBJECT) 
    REFERENCES test.subjects (ID_SUBJECT) on delete cascade;

create table test.demand (  
  ID_DEMAND bigint NOT NULL AUTO_INCREMENT,
  ID_SUBJECT bigint NOT NULL,
  DEMAND_STATE char(3) not null,
  ID_PROFILE bigint,                          
  PRIMARY KEY (ID_DEMAND)
);

ALTER TABLE test.demand add
  CONSTRAINT demand_fk1
    foreign key (ID_SUBJECT) 
    REFERENCES test.subjects (ID_SUBJECT) on delete cascade;

ALTER TABLE test.demand add
  CONSTRAINT demand_fk2 foreign key (DEMAND_STATE) REFERENCES test.request_state (ID_REQUEST_STATE);                                                       
alter table test.demand
 add CONSTRAINT demand_fk3
    foreign key (ID_SUBJECT, ID_PROFILE) 
    REFERENCES test.subject_profiles (ID_SUBJECT, ID_PROFILE);

而他们的PostgreSQL的副本:

create table test.subjects (
  ID_SUBJECT bigint NOT NULL,
  FULL_NAME varchar(200) NOT NULL,
  PRIMARY KEY (ID_SUBJECT)
);

create table test.request_state (   
  ID_REQUEST_STATE char(3) NOT NULL,  
  DESCRIPTION varchar(80) NOT NULL,
  PRIMARY KEY (ID_REQUEST_STATE)
);

create table test.subject_profiles (    
  ID_SUBJECT_PROFILES bigint NOT NULL,
  ID_SUBJECT bigint NOT NULL,
  ID_PROFILE bigint,    
  PRIMARY KEY (ID_SUBJECT_PROFILES)
);

CREATE UNIQUE INDEX subject_profiles_uq1
ON test.subject_profiles (ID_SUBJECT, ID_PROFILE);

ALTER TABLE test.subject_profiles add  
  CONSTRAINT subject_profiles_fk1
    foreign key (ID_SUBJECT) 
    REFERENCES test.subjects (ID_SUBJECT) on delete cascade;

create table test.demand (  
  ID_DEMAND bigint NOT NULL,
  ID_SUBJECT bigint NOT NULL,
  DEMAND_STATE char(3) not null,
  ID_PROFILE  bigint,
   PRIMARY KEY (ID_DEMAND)
);

ALTER TABLE test.demand add
  CONSTRAINT demand_fk1
    foreign key (ID_SUBJECT) 
    REFERENCES test.subjects (ID_SUBJECT) on delete cascade;

ALTER TABLE test.demand add
  CONSTRAINT demand_fk2
    foreign key (DEMAND_STATE) REFERENCES test.request_state (ID_REQUEST_STATE);                                                       
alter table test.demand
 add CONSTRAINT demand_fk3
    foreign key (ID_SUBJECT, ID_PROFILE) 
    REFERENCES test.subject_profiles (ID_SUBJECT, ID_PROFILE);

现在,MySQL的这个查询:

SELECT 
  CONCAT(table_name) AS table_name, CONCAT(column_name) AS column_name,
  CONCAT(referenced_table_name) AS referenced_table_name,
  CONCAT(referenced_column_name) AS referenced_column_name
FROM 
  INFORMATION_SCHEMA.key_column_usage 
WHERE 
  referenced_table_schema = 'subjects_data'
  and referenced_table_name IS NOT NULL 
  and table_name = 'demand'
ORDER BY table_name, column_name

返回:

table_name  column_name  referenced_table_name referenced_column_name                              
---------------------------------------------------------------------
demand      DEMAND_STATE request_state         ID_REQUEST_STATE                                    
demand      ID_PROFILE   subject_profiles      ID_PROFILE                                          
demand      ID_SUBJECT   subjects              ID_SUBJECT                                          
demand      ID_SUBJECT   subject_profiles      ID_SUBJECT

虽然这是我最好的Postgres的“翻版”:

SELECT  
  tc.table_name,
  kcu.column_name,
  ccu.table_name as references_table,
  ccu.column_name as references_field
FROM 
  information_schema.table_constraints tc
  LEFT JOIN information_schema.key_column_usage kcu
  ON tc.constraint_catalog = kcu.constraint_catalog
  AND tc.constraint_schema = kcu.constraint_schema
  AND tc.constraint_name = kcu.constraint_name
  LEFT JOIN information_schema.referential_constraints rc
  ON tc.constraint_catalog = rc.constraint_catalog
  AND tc.constraint_schema = rc.constraint_schema
  AND tc.constraint_name = rc.constraint_name
  LEFT JOIN information_schema.constraint_column_usage ccu
  ON rc.unique_constraint_catalog = ccu.constraint_catalog
  AND rc.unique_constraint_schema = ccu.constraint_schema
  AND rc.unique_constraint_name = ccu.constraint_name
WHERE 
  tc.constraint_catalog = 'subjects_db'
  and tc.constraint_schema = 'test' 
  and tc.table_name = 'demand'
  and tc.constraint_type = 'FOREIGN KEY'

返回:

table_name  column_name  referenced_table_name referenced_column_name
---------------------------------------------------------------------
demand      id_subject   subjects              id_subject            
demand      demand_state request_state         id_request_state      
demand      id_subject   <null>                <null>                
demand      id_profile   <null>                <null>                

所以,最后,以何种方式,我应该重写我的Postgres的查询,以检索引用的表和列的所有信息?

我相信这是我丢失的东西,因为有PostgreSQL的结果集的一些空值。

TIA!

mysql postgresql code-generation jooq information-schema
1个回答
1
投票

您正在使用一个唯一索引,而不是用于subject_profiles_uq1唯一约束。相当多的RDBMS支持这样的指标,通常不是在字典中的意见普通的方式上市。举例来说,当你在你的PostgreSQL数据库运行此查询:

SELECT constraint_name, unique_constraint_name
FROM information_schema.referential_constraints;

你应该得到的东西是这样的:

|       constraint_name | unique_constraint_name |
|-----------------------|------------------------|
| deferred_17_aba21_ref |    deferred_check_pkey |
|  subject_profiles_fk1 |          subjects_pkey |
|            demand_fk1 |          subjects_pkey |
|            demand_fk2 |     request_state_pkey |
|            demand_fk3 |                 (null) |

理想情况下,你不应该使用唯一索引,但唯一约束。即限定subject_profiles_uq1这样:

ALTER TABLE test.subject_profiles
  ADD CONSTRAINT subject_profiles_uq1
    UNIQUE (id_subject, id_profile);

在这情况下,你的查询将正常工作。 SQL Fiddle here,生产:

| table_name |  column_name | references_table | references_field |
|------------|--------------|------------------|------------------|
|     demand |   id_subject |         subjects |       id_subject |
|     demand | demand_state |    request_state | id_request_state |
|     demand |   id_subject | subject_profiles |       id_profile |
|     demand |   id_subject | subject_profiles |       id_subject |
|     demand |   id_profile | subject_profiles |       id_profile |
|     demand |   id_profile | subject_profiles |       id_subject |

如果你绝对需要使用一个唯一索引,那么你要查询pg_catalog代替:

SELECT fc.relname, fa.attname, uc.relname, ua.attname
FROM pg_catalog.pg_constraint f
JOIN pg_namespace fn ON f.connamespace = fn.oid
JOIN pg_catalog.pg_class fc ON f.conrelid = fc.oid
JOIN pg_attribute fa ON fa.attrelid = fc.oid AND fa.attnum = ANY(f.conkey)
JOIN pg_catalog.pg_class uc ON f.confrelid = uc.oid
JOIN pg_attribute ua ON ua.attrelid = uc.oid AND ua.attnum = ANY(f.confkey)
WHERE f.contype = 'f'
AND fc.table_name = 'demand'
AND fn.nspname = 'test'

About jOOQ

您标记你的问题,所以我假设你正在寻找进入调试的jOOQ 3.11,目前不拿起唯一索引,因为唯一约束这一限制:https://github.com/jOOQ/jOOQ/issues/8286

© www.soinside.com 2019 - 2024. All rights reserved.