Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PL/pgSQL函数的输入表_Sql_Postgresql_Plpgsql - Fatal编程技术网

PL/pgSQL函数的输入表

PL/pgSQL函数的输入表,sql,postgresql,plpgsql,Sql,Postgresql,Plpgsql,我想使用一个plpgsql函数,其中有一个表和几个列作为输入参数。这个想法是把桌子分成几块,然后对每一部分都做些事情 我尝试了以下功能: CREATE OR REPLACE FUNCTION my_func(Integer) RETURNS SETOF my_part AS $$ DECLARE out my_part; BEGIN FOR i IN 0..$1 LOOP FOR out IN SELECT * FROM my_func2(SELECT * FROM ta

我想使用一个plpgsql函数,其中有一个表和几个列作为输入参数。这个想法是把桌子分成几块,然后对每一部分都做些事情

我尝试了以下功能:

CREATE OR REPLACE FUNCTION my_func(Integer)
  RETURNS SETOF my_part
AS $$
DECLARE
out my_part;
BEGIN
  FOR i IN 0..$1 LOOP
    FOR out IN
    SELECT * FROM my_func2(SELECT * FROM table1 WHERE id = i)
    LOOP
       RETURN NEXT out;
   END LOOP;
  END LOOP;
  RETURN;
END;
$$
LANGUAGE plpgsql;
CREATE or REPLACE FUNCTION my_func2(_row table1) 
  RETURNS SETOF table1 AS
'SELECT ($1).*' LANGUAGE sql;
CREATE OR REPLACE FUNCTION my_func(int)
  RETURNS SETOF table1 AS
$func$
DECLARE
   rec table1;
BEGIN
  FOR i IN 0..$1 LOOP
     FOR rec IN
        SELECT * FROM table1 WHERE table1_id = i
     LOOP
        RETURN QUERY
        SELECT * FROM my_func2(rec);
     END LOOP;
  END LOOP;
END
$func$  LANGUAGE plpgsql;
my_func2()
是一个函数,它对每个较小的部分执行一些操作

CREATE or REPLACE FUNCTION my_func2(table1) 
  RETURNS SETOF my_part2 AS
$$ 
BEGIN
RETURN QUERY
SELECT * FROM table1;
END
$$
LANGUAGE plpgsql;
如果我跑步:

SELECT * FROM my_func(99);
我想我应该收到为每个id处理的前99个id。 但它说下面这行有一个错误:

SELECT * FROM my_func2(select * from table1 where id = i)
错误是:

子查询只允许返回一列


为什么会发生这种情况?有没有一种简单的方法来解决这个问题?

正如错误日志告诉您的那样。。子查询中只能返回一列,因此必须将其更改为

SELECT my_func2(SELECT Specific_column_you_need FROM hasval WHERE wid = i)

一种可能的解决方案是,将funct2所需表的主键传递给funct2,然后按照错误日志中的说明,在函数中选择*以获得整个表。。子查询中只能返回一列,因此必须将其更改为

SELECT my_func2(SELECT Specific_column_you_need FROM hasval WHERE wid = i)

一种可能的解决方案是,将funct2需要的表的主键传递给funct2,然后通过在函数中选择*来获得整个表。在你尝试高级魔法之前先学习基础知识

  • Postgres没有“表变量”。一次只能将一列或一行传递给函数。使用临时表或(如@Daniel注释)传递整个表。语法在多个地方无效,因此不清楚您是否真的在尝试这种语法。
    即使是这样:最好一次处理一行,或者重新考虑您的方法,使用基于集合的操作(纯SQL)而不是传递游标

  • 您的问题中未定义数据类型
    my\u part
    my\u part2
    。可能是问题的缺点或测试用例中的问题

  • 您似乎期望
    my_func2()
    函数体中的表名
    table1
    引用相同(类型!)名称的函数参数,但这至少在两个方面是根本错误的:

  • 只能传递值。表名是标识符,而不是值。您需要动态构建查询字符串,并在plpgsql函数中使用
    execute
    执行它。再说一遍,这也可能不是你想要的

  • 创建或替换函数my_func2(表1)
    中的
    表1
    类型名称,而不是参数名称。这意味着您的函数需要一个类型为
    table1
    的值。显然,您有一个同名的表,所以它应该是关联的行类型

  • my_func2()
    的返回类型必须与实际返回的内容匹配。由于要从表1返回
    SELECT*
    ,请使该
    返回表1的集合

  • 它可以只是一个简单的SQL函数

所有这些加在一起:

CREATE or REPLACE FUNCTION my_func2(_row table1) 
  RETURNS SETOF table1 AS
'SELECT ($1).*' LANGUAGE sql;
请注意括号,它们对于分解行类型是必不可少的

此处需要括号来表示
compositecol
是列名而不是表名

但还有更多

  • 不要使用
    out
    作为变量名,它是
    CREATE FUNCTION
    语句的关键字

  • 主查询
    my_func()
    的语法更像psudo代码。太多加不起来

概念证明 演示表:

CREATE TABLE table1(table1_id serial PRIMARY KEY, txt text);
INSERT INTO table1(txt) VALUES ('a'),('b'),('c'),('d'),('e'),('f'),('g');
辅助功能:

CREATE OR REPLACE FUNCTION my_func(Integer)
  RETURNS SETOF my_part
AS $$
DECLARE
out my_part;
BEGIN
  FOR i IN 0..$1 LOOP
    FOR out IN
    SELECT * FROM my_func2(SELECT * FROM table1 WHERE id = i)
    LOOP
       RETURN NEXT out;
   END LOOP;
  END LOOP;
  RETURN;
END;
$$
LANGUAGE plpgsql;
CREATE or REPLACE FUNCTION my_func2(_row table1) 
  RETURNS SETOF table1 AS
'SELECT ($1).*' LANGUAGE sql;
CREATE OR REPLACE FUNCTION my_func(int)
  RETURNS SETOF table1 AS
$func$
DECLARE
   rec table1;
BEGIN
  FOR i IN 0..$1 LOOP
     FOR rec IN
        SELECT * FROM table1 WHERE table1_id = i
     LOOP
        RETURN QUERY
        SELECT * FROM my_func2(rec);
     END LOOP;
  END LOOP;
END
$func$  LANGUAGE plpgsql;
主要功能:

CREATE OR REPLACE FUNCTION my_func(Integer)
  RETURNS SETOF my_part
AS $$
DECLARE
out my_part;
BEGIN
  FOR i IN 0..$1 LOOP
    FOR out IN
    SELECT * FROM my_func2(SELECT * FROM table1 WHERE id = i)
    LOOP
       RETURN NEXT out;
   END LOOP;
  END LOOP;
  RETURN;
END;
$$
LANGUAGE plpgsql;
CREATE or REPLACE FUNCTION my_func2(_row table1) 
  RETURNS SETOF table1 AS
'SELECT ($1).*' LANGUAGE sql;
CREATE OR REPLACE FUNCTION my_func(int)
  RETURNS SETOF table1 AS
$func$
DECLARE
   rec table1;
BEGIN
  FOR i IN 0..$1 LOOP
     FOR rec IN
        SELECT * FROM table1 WHERE table1_id = i
     LOOP
        RETURN QUERY
        SELECT * FROM my_func2(rec);
     END LOOP;
  END LOOP;
END
$func$  LANGUAGE plpgsql;
电话:


但这实际上只是一个概念的证明。还没有什么有用的。

这里有很多误解。在你尝试高级魔法之前先学习基础知识

  • Postgres没有“表变量”。一次只能将一列或一行传递给函数。使用临时表或(如@Daniel注释)传递整个表。语法在多个地方无效,因此不清楚您是否真的在尝试这种语法。
    即使是这样:最好一次处理一行,或者重新考虑您的方法,使用基于集合的操作(纯SQL)而不是传递游标

  • 您的问题中未定义数据类型
    my\u part
    my\u part2
    。可能是问题的缺点或测试用例中的问题

  • 您似乎期望
    my_func2()
    函数体中的表名
    table1
    引用相同(类型!)名称的函数参数,但这至少在两个方面是根本错误的:

  • 只能传递值。表名是标识符,而不是值。您需要动态构建查询字符串,并在plpgsql函数中使用
    execute
    执行它。再说一遍,这也可能不是你想要的

  • 创建或替换函数my_func2(表1)
    中的
    表1
    类型名称,而不是参数名称。这意味着您的函数需要一个类型为
    table1
    的值。显然,您有一个同名的表,所以它应该是关联的行类型

  • my_func2()
    的返回类型必须与实际返回的内容匹配。由于要从表1返回
    SELECT*
    ,请使该
    返回表1的集合

  • 它可以只是一个简单的SQL函数

所有这些加在一起:

CREATE or REPLACE FUNCTION my_func2(_row table1) 
  RETURNS SETOF table1 AS
'SELECT ($1).*' LANGUAGE sql;
请注意括号,它们对于分解行类型是必不可少的

此处需要括号来表示
compositecol
是列名而不是表名

但还有更多

  • 不要使用
    out
    作为变量名,它是
    CREATE FUNCTION
    语句的关键字