简体   繁体   English

在PostgreSQL中获取其他表中没有任何引用的行列表

[英]Get list of rows without any references in other tables in postgresql

I have a table that holds translations in an entire system and other tables reference to it, for example something like this: 我有一个表,可保存整个系统中的翻译,其他表也引用该表,例如:

Table "translations"
id | title
----------------------------
 1 | First Translation
 2 | Second Translation

And second table with foreign key pointing to translations : 第二张表带有指向translations外键:

Table "article"
id | translation_id | ...
 1 | 1              | ...

I would like to get a list of rows that are not referenced by any other table (in this example row with id=2). 我想获取没有任何其他表引用的行的列表(在此示例中,id = 2的行)。

Number of tables might change and I would like to have a general solution that will operate on native relations mechanism in psql. 表的数量可能会更改,我想有一个通用的解决方案,该解决方案可以在psql中的本机关系机制上运行。

I've made the function you need. 我已经完成了您需要的功能。 Bellow is the sample data I created to test it. 贝娄是我创建的用于测试的示例数据。 In my data sample the return should be the ID 4 from the table t1 . 在我的数据样本中,返回值应该是表t1ID 4 To your case the t1 table would be the translations table. 根据您的情况, t1表将是translations表。

You have to change it to your tables. 您必须将其更改为表格。 It shouldn't be difficult. 应该不难。

create table t1 (
    id integer primary key not null,
    lang varchar(10)
);

create table t2 (
    id integer primary key not null,
    id_t1 integer,
     constraint fk_t2 foreign key (id_t1) references t1(id)
);

create table t3 (
    id integer primary key not null,
    id_t1 integer,
    constraint fk_t3 foreign key (id_t1) references t1(id)
);

insert into t1 values (1, 'pt'), (2, 'us'), (3,'cn'), (4,'uk');
insert into t2 values (1, 1), (2,2);
insert into t3 values (1, 1), (2,3);

CREATE OR REPLACE FUNCTION listAllReferences()
  RETURNS setof integer AS
$$
declare
   fullSQL text;
   rs RECORD;
begin
   fullSQL := '';
   for rs in 
        SELECT 'select t1.id from t1 inner join ' || tc.table_name || ' ON ('||tc.table_name||'.'||kcu.column_name||' = t1.id)' as sel
          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 ccu.table_name='t1' loop
      if fullSQL != '' then
         fullSQL := fullSQL || ' union ';
      end if;
      fullSQL := fullSQL || rs.sel;
   end loop;
   return query
      execute 'select t1.id 
                 from t1 left join ('||fullSQL||') alltb on (t1.id = alltb.id)
                where alltb.id is null';
   return;

end;
$$
  LANGUAGE plpgsql;

And to use it just do: 要使用它,只需执行以下操作:

select * from listAllReferences();

It will return: 它将返回:

listallreferences
       4

Future tables with reference to your language table will also get covered because I'm getting the data from the INFORMATION_SCHEMA of PostgreSQL 将来涉及您的语言表的表也将涵盖在内,因为我是从PostgreSQL的INFORMATION_SCHEMA获取数据的

Also you may have to add another filter () to the query on the implicit cursor which is AND tc.table_schema = 'yourSchemaName' 另外,您可能还需要向隐式游标上的查询中添加另一个过滤器(),且为AND tc.table_schema = 'yourSchemaName'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM