multirow子选择将在in
子句中where
运算符的右侧使用:
create table t (a integer);
insert into t (a) values (1), (9);
drop function if exists f();
create function f()
returns void as $$
begin
execute '
select a
from t
where a in $1
' using (select 1 union select 2);
end;$$
language plpgsql;
select f();
ERROR: more than one row returned by a subquery used as an expression
CONTEXT: SQL statement "SELECT (select 1 union select 2)"
PL/pgSQL function "f" line 3 at EXECUTE statement
如果能够实现上述功能,将如何实现?
答案 0 :(得分:2)
我的问题中没有任何内容可以通过以下方式解决:
SELECT a
FROM t
JOIN (VALUES (1), (2)) x(a) USING (a); -- any query returning multiple int
你能澄清你的例子中的必要性吗?
作为概念证明,这将更简单/更快:
CREATE OR REPLACE FUNCTION x.f1()
RETURNS SETOF integer AS
$BODY$
BEGIN
RETURN QUERY EXECUTE '
SELECT a
FROM t
WHERE a = ANY($1)'
USING ARRAY(VALUES (1), (2)); -- any query here
END;
$BODY$
LANGUAGE plpgsql;
您的观察结果正确。这是有道理的。尝试:
EXPLAIN ANALYZE SELECT * FROM tbl WHERE id IN (1,2,3);
查询计划将显示:
索引条件:(id = ANY('{1,2,3}':: integer []))
PostgreSQL在内部将id IN (..)
构造转换为id = ANY(..)
。这两个执行相同 - 除了可忽略的开销惩罚。
我的代码只能更快地构建语句 - 就像你诊断的那样。
答案 1 :(得分:0)
create function f()
returns setof integer as $$
begin
return query execute format('
select a
from t
where a in %s
', replace(replace(array(select 1 union select 2)::text, '{', '('), '}', ')'));
end$$
language plpgsql;