Postgresql 错误:表单中的函数表达式不能引用同一查询级别的其他关系:如何解决此问题

Postgresql 错误:表单中的函数表达式不能引用同一查询级别的其他关系:如何解决此问题,postgresql,postgresql-9.2,lateral,Postgresql,Postgresql 9.2,Lateral,当然,这个问题纯粹是假设性的,我没有愚蠢到试图在DBMS中计算素数表。但问题依然存在:有没有一种干净的方法可以绕过没有侧向力的情况 正如您所看到的,我尝试使用一个视图不起作用,这个视图周围的函数也不起作用,这个函数njet中的一个临时表,以及旋转函数的属性 下一步可能是一些触发器黑客,但我真的,真的很讨厌触发器,基本上是因为它们对DBMS模式的严格性是不可见的您可以在目标列表中使用SRF函数,但应该有一些奇怪的情况。侧边最好 DROP SCHEMA tmp CASCADE; CREATE SCH

当然,这个问题纯粹是假设性的,我没有愚蠢到试图在DBMS中计算素数表。但问题依然存在:有没有一种干净的方法可以绕过没有侧向力的情况

正如您所看到的,我尝试使用一个视图不起作用,这个视图周围的函数也不起作用,这个函数njet中的一个临时表,以及旋转函数的属性


下一步可能是一些触发器黑客,但我真的,真的很讨厌触发器,基本上是因为它们对DBMS模式的严格性是不可见的

您可以在目标列表中使用SRF函数,但应该有一些奇怪的情况。侧边最好

DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE primes
        ( pos SERIAL NOT NULL PRIMARY KEY
        , val INTEGER NOT NULL
        , CONSTRAINT primes_alt UNIQUE (val)
        );

CREATE FUNCTION is_prime(_val INTEGER)
RETURNS BOOLEAN
AS $func$
DECLARE ret BOOLEAN ;
BEGIN

SELECT False INTO ret
WHERE EXISTS (SELECT *
        FROM primes ex
        WHERE ex.val = $1
        OR ( (ex.val * ex.val) <= $1 AND ($1 % ex.val) = 0 )
        );
RETURN COALESCE(ret, True);
END;
$func$ LANGUAGE plpgsql STABLE;

CREATE VIEW vw_prime_step AS (
        -- Note when the table is empty we return {2,3,1} as a bootstrap
        SELECT
           COALESCE(MAX(val) +2,2) AS start
         , COALESCE((MAX(val) * MAX(val))-1, 3) AS stop
         , COALESCE(min(val), 1) AS step
        FROM primes
        );
SELECT * FROM vw_prime_step;

        -- The same as a function.
        -- Works, but is not usable in a query that alters the primes table.
        -- ; even not with the TEMP TABLE construct
CREATE FUNCTION fnc_prime_step ( OUT start INTEGER, OUT stop INTEGER, OUT step INTEGER)
RETURNS RECORD
AS $func$
BEGIN
/***
CREATE TEMP TABLE tmp_limits
        ON COMMIT DROP
        AS SELECT ps.start,ps.stop,ps.step FROM vw_prime_step ps
        ;
-- RETURN QUERY 
SELECT tl.start,tl.stop,tl.step INTO $1,$2,$3
FROM tmp_limits tl
LIMIT 1
        ; 
***/
SELECT tl.start,tl.stop,tl.step INTO $1,$2,$3
FROM vw_prime_step tl
LIMIT 1;
END;
$func$
-- Try lying ...
-- IMMUTABLE LANGUAGE plpgsql;
-- Try lying ...
Stable LANGUAGE plpgsql;

        -- This works
SELECT * FROM fnc_prime_step();
INSERT INTO primes (val)
SELECT gs FROM fnc_prime_step() sss
 , generate_series( 2, 3, 1 ) gs
WHERE is_prime(gs) = True
        ;
        -- This works
SELECT * FROM fnc_prime_step();
INSERT INTO primes (val)
SELECT gs FROM fnc_prime_step() sss
 , generate_series( 5, 24, 2 ) gs
WHERE is_prime(gs) = True
        ;

        -- This does not work
        -- ERROR:  function expression in FROM cannot refer to other relations of same query level:1
SELECT * FROM fnc_prime_step();
INSERT INTO primes (val)
SELECT gs FROM fnc_prime_step() sss
 , generate_series( sss.start, sss.stop, sss.step ) gs
WHERE is_prime(gs) = True
        ;

SELECT * FROM primes;
SELECT * FROM fnc_prime_step();

对于以后发现这一点的人,PostgreSQL 9.3将支持横向。 postgres=# select i, generate_series(1,i) X from generate_series(1,3) g(i); i | x ---+--- 1 | 1 2 | 1 2 | 2 3 | 1 3 | 2 3 | 3 (6 rows)