使用 PL/pgSQL 将查询结果存储在变量中

Posted

技术标签:

【中文标题】使用 PL/pgSQL 将查询结果存储在变量中【英文标题】:Store query result in a variable using in PL/pgSQL 【发布时间】:2012-09-01 22:23:38 【问题描述】:

如何将查询结果分配给 PL/pgSQL(PostgreSQL 的过程语言)中的变量?

我有一个函数:

CREATE OR REPLACE FUNCTION test(x numeric)
RETURNS character varying AS
$BODY$
DECLARE
name   character varying(255);
begin
 name ='SELECT name FROM test_table where id='||x;

 if(name='test')then
  --do somthing
 else
  --do the else part
 end if;
end;
return -- return my process result here
$BODY$
LANGUAGE plpgsql VOLATILE

在上面的函数中我需要存储这个查询的结果:

'SELECT name FROM test_table where id='||x;

到变量name

如何处理?

【问题讨论】:

【参考方案1】:

我想你在找SELECT select_expressions INTO

select test_table.name into name from test_table where id = x;

这将从test_table 中提取name,其中id 是您的函数的参数,并将其保留在name 变量中。不要遗漏test_table.name 上的表名前缀,否则您会收到关于不明确引用的投诉。

【讨论】:

如果我需要多个变量怎么办。喜欢 select test_table.name, test_table.id, test_table.ssn? @DaoLam:从我喜欢的文档中:“产生单行(可能是多列)的 SQL 命令的结果可以分配给记录变量、行类型变量或列表标量变量。” @muistooshort 所以你说我可以做同样的事情,我可以使用 name.id, name.ssn 来检索?我用 IF EXISTS 尝试过,但没有用:IF EXISTS (select * into name from test_table...)) 文档中没有示例(或者我错过了),但正如@muistooshort 指出的那样,您可以通过单选选择多个变量:SELECT test_table.column1, test_table.column2 INTO variable1, variable2 FROM test_table WHERE id = x; Postgres 文档将此语法称为SELECT select_expressions INTO(不会创建表),而不是SELECT INTO(会创建表)。 More info【参考方案2】:

要分配单个变量,您还可以在 PL/pgSQL 代码块中使用plain assignment,并在右侧使用scalar subquery:

name := (SELECT t.name from test_table t where t.id = x);

实际上与SELECT INTO 类似@mu already provided 相同,但有细微差别:

SELECT INTO 在我对 Postgres 14 的测试中稍快。 (在不涉及 SELECT 的情况下,简单的常量分配仍然快 10 倍。) SELECT INTO 也设置了special variable FOUND,而普通赋值则没有。您可能需要其中之一。 SELECT INTO 也可以一次分配多个变量。看: SELECT INTO with more than one attribution

值得注意的是,这也有效:

name := t.name from test_table t where t.id = x;

没有前导 SELECTSELECT 语句。但我不会使用这种混合。正如@Pavel 评论的那样,最好使用前两种更清晰、记录在案的方法中的一种。

【讨论】:

这不是个好主意 - 这个功能没有文档记录,而且很丑 PL/pgSQL 允许混合使用 SQL 和 PL - 有时您可以创建非常奇怪的生物,但更好的是干净地混合 PL 和 SQL - 在孤立的语句中。 @PavelStehule:我同意,你的形式更可取。 其实我更喜欢你的语法,但问题是当你想处理错误时,你的语句不会在 select into 语句的反面将 FOUND 发送为 true,checkout (postgresql.org/docs/9.1/plpgsql-statements.html)【参考方案3】:

通常的模式是EXISTS(subselect):

BEGIN
  IF EXISTS(SELECT name
              FROM test_table t
             WHERE t.id = x
               AND t.name = 'test')
  THEN
     ---
  ELSE
     ---
  END IF;

此模式用于 PL/SQL、PL/pgSQL、SQL/PSM、...

【讨论】:

【参考方案4】:

创建学习表:

CREATE TABLE "public"."learning" (
    "api_id" int4 DEFAULT nextval('share_api_api_id_seq'::regclass) NOT NULL,
    "title" varchar(255) COLLATE "default"
);

插入数据学习表:

INSERT INTO "public"."learning" VALUES ('1', 'Google AI-01');
INSERT INTO "public"."learning" VALUES ('2', 'Google AI-02');
INSERT INTO "public"."learning" VALUES ('3', 'Google AI-01');

步骤:01

CREATE OR REPLACE FUNCTION get_all (pattern VARCHAR) RETURNS TABLE (
        learn_id INT,
        learn_title VARCHAR
) AS $$
BEGIN
    RETURN QUERY SELECT
        api_id,
        title
    FROM
        learning
    WHERE
        title = pattern ;
END ; $$ LANGUAGE 'plpgsql';

步骤:02

SELECT * FROM get_all('Google AI-01');

步骤:03

DROP FUNCTION get_all();

演示:

【讨论】:

【参考方案5】:

根据Executing a Query with a Single-Row Result,使用以下语法:

SELECT select_expressions INTO [STRICT] target FROM ...

其中target 可以是记录变量、行变量或简单变量和记录/行字段的逗号分隔列表。

SELECT INTO 不同,SELECT select_expressions INTO 不会创建表。

在你的例子中,你有一个简单的变量name,所以选择语句是:

SELECT test_table.name INTO name FROM test_table WHERE test_table.id = x;

【讨论】:

【参考方案6】:

您可以使用以下示例将查询结果存储在使用 PL/pgSQL 的变量中:

 select * into demo from maintenanceactivitytrack ; 
    raise notice'p_maintenanceid:%',demo;

【讨论】:

以上是关于使用 PL/pgSQL 将查询结果存储在变量中的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PL/pgSQL 中的动态选择查询中使用迭代器变量?

在 PL/PGSQL 动态 SQL 内部函数中引用局部变量

游标可以在 PL/pgSQL 中保存变量吗?

从 PL/PGSQL 引用会话变量 (\set var='value')

PostgreSQL PL/pgSQL:存储在表中的查询(营业时间)

PL/PGSQL - 无法将 SELECT 语句中的 array_agg 分配给变量