如何在PostgreSQL中声明并使用临时表作为游标源?
在规范化了大部分2NF和一些3NF表之后,我现在需要下面这样的查询来上下移动我的表结构,以获取我需要的信息。PostgreSQL 9.3如何在PostgreSQL中声明并使用临时表作为游标源?,postgresql,plpgsql,Postgresql,Plpgsql,在规范化了大部分2NF和一些3NF表之后,我现在需要下面这样的查询来上下移动我的表结构,以获取我需要的信息。PostgreSQL 9.3 CREATE TEMPORARY TABLE test AS With charts_on_date_of_service AS ( SELECT t.service_recid, t.tservice, t.chart_recid FROM ( select s.recid as service_recid, s.
CREATE TEMPORARY TABLE test AS
With charts_on_date_of_service AS (
SELECT t.service_recid, t.tservice, t.chart_recid
FROM ( select s.recid as service_recid, s.tservice, p.chart_recid
from doctorservices d
join services s on (s.recid = d.service_recid)
join patients p on (p.recid = s.patient_recid)
where s.tservice::date = _tservice::date
) as t
)
select s.recid as service_recid, s.tservice, c.chart_recid, c.tservice as time_of_service
from charts_on_date_of_service c
join patients p on (p.chart_recid = c.chart_recid)
join services s on (s.patient_recid = p.recid)
join doctorservices d on ( d.service_recid = s.recid)
where s.tservice::date <= _tservice::date
order by c.chart_recid, s.tservice;
由于涉及到这个查询,我不希望在plpgsql函数中重复它。也就是说,我想做一些类似的事情:
CREATE OR REPLACE FUNCTION test(_tservice timestamp)
RETURNS TABLE (service_recid bigint, chart_recid int, tservice timestamp, ct int) AS
$func$
DECLARE
CREATE TEMPORARY TABLE test AS .... <--THIS FAILS
cur CURSOR FOR
SELECT t.service_recid, t.tservice, t.chart_recid
FROM test t
BEGIN
... some processing commands on the temp table test and cursor cur....
END
我有几个相关的问题:
如何在plpgsql中声明临时表?
临时表可以用作游标的源吗?
创建一个临时表并在多个位置使用它会更好,还是在多个位置重新创建相同的查询会更好?
我似乎无法通过谷歌找到答案。
非常感谢您的任何帮助或想法 你必须使用不同的方法。在PL/pgSQL内部,任何CREATE语句都不能位于DECLARE部分。它和其他语句一样是语句,应该在函数体部分。若您可以在动态创建的表上进行迭代,则必须使用游标,并且必须在OPEN语句中指定查询,或者更好-用于循环: 这个例子是可行的,但是它非常昂贵,并且只有在必要时才应该使用这个模式。临时表很昂贵,如果您不需要它,就不要使用它。这有很好的理由:性能、复杂性,但通常不需要。来自T-SQL的一些模式不能在Postgres中使用,有些工作需要不同的思考。您可以使用数组、返回下一步、返回查询语句:
CREATE OR REPLACE FUNCTION test(a int)
RETURNS table (b int, c int, d int) AS $$
BEGIN
RETURN QUERY SELECT col, col+1, col+2
FROM generate_series(1,a)
RETURN;
END; $$ LANGUAGE plpgsql;
对于类似的普通函数,最好使用SQL语言:
CREATE OR REPLACE FUNCTION test(a int)
RETURNS table (b int, c int, d int) AS $$
SELECT col, col+1, col+2
FROM generate_series(1,a)
$$ LANGUAGE sql;
您可以在Postgres中使用数组:
CREATE OR REPLACE FUNCTION test(a int)
RETURNS TABLE (b int, c int, d int) AS $$
DECLARE cols int[];
BEGIN
cols := ARRAY(SELECT generate_series(1,a));
RETURN QUERY
SELECT col, col + 1, col + 2
FROM unnest(cols) g(col);
RETURN;
END; $$ LANGUAGE plpgsql;
回答得很好。因此,如果临时表非常昂贵,在我的例子中,重复查询是否更好;我需要的两个游标各一次?谢谢。@Wayne,这取决于您的查询有多贵。临时表的成本随着频率的增加而增加-1/s(db+/-0),100/s(db)非常昂贵。始终取决于上下文,但行为与T-SQL有很大不同,内部实现也不同。如果有必要,可以使用临时表,但最好使用数组变量。
CREATE OR REPLACE FUNCTION test(a int)
RETURNS TABLE (b int, c int, d int) AS $$
DECLARE cols int[];
BEGIN
cols := ARRAY(SELECT generate_series(1,a));
RETURN QUERY
SELECT col, col + 1, col + 2
FROM unnest(cols) g(col);
RETURN;
END; $$ LANGUAGE plpgsql;