我有以下查询,如果相应的表为空,则forelast参数应为false
,否则为true
SELECT 'SELECT SETVAL(' ||
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1), ' ||
CASE WHEN (SELECT COUNT(*) FROM quote_ident(tablename))=0 THEN FALSE
ELSE TRUE
END ||
') FROM ' ||
quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
FROM pg_class AS S,
pg_depend AS D,
pg_class AS T,
pg_attribute AS C,
pg_tables AS PGT
WHERE S.relkind = 'S'
AND S.oid = D.objid
AND D.refobjid = T.oid
AND D.refobjid = C.attrelid
AND D.refobjsubid = C.attnum
AND T.relname = PGT.tablename
ORDER BY S.relname;
但是,它总是求值为true。
确实,子查询SELECT COUNT(*) FROM quote_ident(tablename)
的结果始终为1:
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1), ' ||
(SELECT COUNT(*) FROM quote_ident(tablename))||
') FROM ' ||
quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
FROM pg_class AS S,
pg_depend AS D,
pg_class AS T,
pg_attribute AS C,
pg_tables AS PGT
WHERE S.relkind = 'S'
AND S.oid = D.objid
AND D.refobjid = T.oid
AND D.refobjid = C.attrelid
AND D.refobjsubid = C.attnum
AND T.relname = PGT.tablename
ORDER BY S.relname;
但是我不知道为什么。
作为一个最小的工作示例,请尝试:
create table empty(id serial, name varchar);
create table notempty(id serial, name varchar);
insert into notempty(name) values('foobar');
现在,当您从上方执行查询时,它将对两个表分别为true进行评估1:
SELECT SETVAL('public.empty_id_seq', COALESCE(MAX(id), -->1<--), 1) FROM public.empty;
SELECT SETVAL('public.notempty_id_seq', COALESCE(MAX(id), 1), 1) FROM public.notempty;
答案 0 :(得分:1)
最简单的方法是在生成的查询中包含CASE
表达式:
SELECT 'SELECT SETVAL(' ||
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1), ' ||
'CASE WHEN (SELECT COUNT(*) FROM ' || quote_ident(PGT.schemaname) || '.' || quote_ident(tablename) || ')=0 THEN FALSE
ELSE TRUE
END' ||
') FROM ' ||
quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
FROM pg_class AS S,
pg_depend AS D,
pg_class AS T,
pg_attribute AS C,
pg_tables AS PGT
WHERE S.relkind = 'S'
AND S.oid = D.objid
AND D.refobjid = T.oid
AND D.refobjid = C.attrelid
AND D.refobjsubid = C.attnum
AND T.relname = PGT.tablename
ORDER BY S.relname;
如果您坚持只使用文字true
/ false
,则需要另一层动态SQL。但是由于表的内容可能会在您生成查询和执行查询之间发生变化,因此无论如何,在查询中包含表达式(即在查询运行时获取结果)都是更安全的选择。
我认为您可以实际上简化此过程,并在函数调用中直接使用count(*) > 0
表达式。无需再次子查询同一张表,也不需要CASE
表达式,因为该表达式可以简单地包装一个布尔表达式,因为Postgres可以直接使用布尔表达式。
SELECT 'SELECT SETVAL(' ||
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1), COUNT(*) > 0) FROM ' ||
quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
FROM pg_class AS S,
pg_depend AS D,
pg_class AS T,
pg_attribute AS C,
pg_tables AS PGT
WHERE S.relkind = 'S'
AND S.oid = D.objid
AND D.refobjid = T.oid
AND D.refobjid = C.attrelid
AND D.refobjsubid = C.attnum
AND T.relname = PGT.tablename
ORDER BY S.relname;