Postgresql 使用新的创建过程方法选择用法

Postgresql 使用新的创建过程方法选择用法,postgresql,plpgsql,Postgresql,Plpgsql,我试图在PostgreSQL 11中使用新的CREATE过程方法存储一个简单的SELECT查询。我的想法是将查询存储在DB中,因为我的API服务器中可以有一个非常简单的代码,如果我可以在强制类型安全的sql函数中使用if/else,也许我不需要开发查询生成器。我有一个简单的例子: 首先,我尝试了这个plpgsql函数: CREATE OR REPLACE PROCEDURE test_proc() AS $$ BEGIN SELECT * FROM my_db

我试图在PostgreSQL 11中使用新的
CREATE过程
方法存储一个简单的
SELECT
查询。我的想法是将查询存储在DB中,因为我的API服务器中可以有一个非常简单的代码,如果我可以在强制类型安全的sql函数中使用if/else,也许我不需要开发查询生成器。我有一个简单的例子:

首先,我尝试了这个plpgsql函数:

CREATE OR REPLACE PROCEDURE test_proc() AS $$
    BEGIN
        SELECT * FROM my_db
        LIMIT 1;
    END;
$$ LANGUAGE plpgsql;

CALL test_proc();
但是会引发此错误:

错误:查询没有结果数据的目标
提示:如果要放弃选择的结果,请改用“执行”。
上下文:SQL语句SQL状态:42601处的PL/pgSQL函数test_proc()第3行

如果我试图使用
返回查询

CREATE OR REPLACE PROCEDURE test_proc() AS $$
    BEGIN
        RETURN QUERY;
        SELECT * FROM my_db
        LIMIT 1;
    END;
$$ LANGUAGE plpgsql;
我得到了这个错误:

错误:无法在非函数集中使用返回查询
第17行:返回查询^
SQL状态:42804
字符:310

当我尝试使用
将void作为$$
返回或
将table(…)作为$$$
返回时,也会出现错误。似乎
返回
创建过程中不受支持?那么,是否可以使用新的存储过程方法返回表?如果不是,可能是JSON?

PostgreSQL(Oracle、DB2)中的过程与MS-SQL中的过程不同。它有不同的目标,您不能使用它。通常,你能做的最好的事情就是忘记你从MSSQL知道的一切。程序部分真的不同

只有函数才能返回一些数据,因此需要使用函数。函数可以返回标量值、复合值、数组值或表。您需要返回表的函数

CREATE OR REPLACE FUNCTION fx()
RETURNS SETOF mytab AS $$
BEGIN
  RETURN QUERY SELECT * FROM mytab;
END
$$ LANGUAGE plpgsql;

SELECT * FROM fx();
记录在案:

您可以使用SQL函数,这可能会有更好(或更差)的性能(取决于上下文)。这些函数有时称为参数化视图

CREATE OR REPLACE FUNCTION fx()
RETURNS SETOF mytab AS $$
  SELECT * FROM mytab;
$$ LANGUAGE sql;
注意:此技术是反模式的 如果您想要非常慢的应用程序,或者如果您的数据模型或查询是原始的,请使用它。在其他情况下,不要这样做


不要害怕SQL——它是为手动使用而设计的很棒的语言。最好将所有数据访问放在一个模块(模型)上,不要在代码中的任何地方访问数据库,但在代码中隐藏SQL也不好。

postgreSql 11。我们必须创建一个存储过程

有一个解决方案:

首先,过程是在PostgreSQL 11中介绍的,如果您使用的是低于11的版本,则不能使用过程。您可以使用函数来代替过程

创建函数的语法

    CREATE or replace function function_name(_parameter varchar) 
    returns table(col1 varchar, col2 varchar, col3 varchar) 
          language 'plpgsql' 
          as $BODY$ 
          BEGIN
                  return query select a.col1, a.col2, b.col3 from table a
                  join table2 as b on a.col1 = b.col1;
        END;
        $BODY$;
可以调用与表相同的函数

select * From function_name('sample data');
创建过程的语法

CREATE OR REPLACE PROCEDURE procedure_name(_parameter varcar,INOUT result refcursor)
LANGUAGE 'plpgsql'
AS $BODY$         
BEGIN
open result for SELECT ,  * from sampletable where a = _parameter; 
END;
$BODY$;
您可以在事务中使用call关键字执行过程

BEGIN;
CALL public.procedure_name( 'sample data',  'test');
fetch all in "test";
COMMIT;

如果您需要
返回
某些内容,请使用
函数
,而不是
过程
,因此可能建议插入
创建过程
(因为事务支持),如果要返回表,我需要使用函数进行查询?对我来说没关系。你忘了提到SQL函数。这些不是优化器的障碍,并且是实现“带参数的视图”的好方法@a_horse_,a_no_name-只有当内联可用时,它才起作用,而且并不总是可能的。现在,根据我的经验,我在思考(这是我的观点),所以查询包装只是反模式的(尽管有一些例外),最好不要使用它。我的回答不准确(我知道),但它是安全的。令人难过的是:-(欢迎链接到解决方案,但请确保您的答案在没有它的情况下是有用的:这样您的其他用户就会知道它是什么以及它为什么在那里,然后引用您链接到的页面的最相关部分,以防目标页面不可用..解决方案由我自己确保。它由我自己工作并测试。“函数不支持动态查询”-错误“您不能在函数中使用DML,如插入/更新/删除查询”-错误“函数的返回类型应与函数中表的结构匹配”-错误。您可以定义您喜欢的任何输出结构。因此,句子应为“应与函数中查询的结构匹配”“@a_horse_,没有名字,您是否尝试过Postgresql函数中的动态查询和DML查询。如果您尝试与我们共享。当我尝试共享时,我失败了。然后您做了一些错误的事情,因为这肯定有效。