我有一个表,在整个系统中保存翻译,其他表引用它,例如:
Table "translations"
id | title
----------------------------
1 | First Translation
2 | Second Translation
第二个表,外键指向translations
:
Table "article"
id | translation_id | ...
1 | 1 | ...
我想获得一个未被任何其他表引用的行列表(在此示例中,id = 2的行)。
表的数量可能会改变,我希望有一个通用的解决方案,可以在psql中运行本机关系机制。
答案 0 :(得分:0)
我已经完成了你需要的功能。 Bellow是我为测试它而创建的示例数据。在我的数据示例中,返回值应为表ID 4
中的t1
。对于您的情况,t1
表将是translations
表。
您必须将其更改为您的表格。这不应该是困难的。
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;
使用它只需:
select * from listAllReferences();
它将返回:
listallreferences
4
参考您的语言表的未来表也将被涵盖,因为我从PostgreSQL的INFORMATION_SCHEMA
获取数据
此外,您可能必须在隐式游标AND tc.table_schema = 'yourSchemaName'