PostgreSQL使用select into时有无STRICT关键字的区别

Posted gooczb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PostgreSQL使用select into时有无STRICT关键字的区别相关的知识,希望对你有一定的参考价值。

PostgreSQL使用select into target时有无STRICT关键字的区别

 摘自官方文档http://www.postgres.cn/docs/11/plpgsql-statements.html

 

43.5.3. 执行一个有单一行结果的查询

一个产生单一行(可能有多个列)的 SQL 命令的结果可以被赋值给一个记录变量、行类型变量或标量变量列表。这通过书写基础 SQL 命令并增加一个INTO子句来达成。例如:

SELECT select_expressions INTO [STRICT] target FROM ...;
INSERT ... RETURNING expressions INTO [STRICT] target;
UPDATE ... RETURNING expressions INTO [STRICT] target;
DELETE ... RETURNING expressions INTO [STRICT] target;

其中target可以是一个记录变量、一个行变量或一个有逗号分隔的简单变量和记录/行域列表。PL/pgSQL变量将被替换到该查询的剩余部分中,并且计划会被缓存,正如之前描述的对不返回行的命令所做的。这对SELECT、带有RETURNINGINSERT/UPDATE/DELETE以及返回行集结果的工具命令(例如EXPLAIN)。除了INTO子句,SQL 命令和它在PL/pgSQL之外的写法一样。

提示

注意带INTOSELECT的这种解释和PostgreSQL常规的SELECT INTO命令有很大的不同,后者的INTO目标是一个新创建的表。如果你想要在一个PL/pgSQL函数中从一个SELECT的结果创建一个表,请使用语法CREATE TABLE ... AS SELECT

如果一行或一个变量列表被用作目标,该查询的结果列必须完全匹配该结果的结构,包括数量和数据类型,否则会发生一个运行时错误。当一个记录变量是目标时,它会自动地把自身配置成查询结果列组成的行类型。

INTO子句几乎可以出现在 SQL 命令中的任何位置。通常它被写成刚好在SELECT命令中的select_expressions列表之前或之后,或者在其他命令类型的命令最后。我们推荐你遵循这种惯例,以防PL/pgSQL的解析器在未来的版本中变得更严格。

如果STRICT没有在INTO子句中被指定,那么target将被设置为该查询返回的第一个行,或者在该查询不返回行时设置为空(注意除非使用了ORDER BY,否则第一行”的界定并不清楚)。第一行之后的任何结果行都会被抛弃。你可以检查特殊的FOUND变量(见第 43.5.5 节)来确定是否返回了一行:

SELECT * INTO myrec FROM emp WHERE empname = myname;
IF NOT FOUND THEN
    RAISE EXCEPTION ‘employee % not found‘, myname;
END IF;

如果指定了STRICT选项,该查询必须刚好返回一行或者将会报告一个运行时错误,该错误可能是NO_DATA_FOUND(没有行)或TOO_MANY_ROWS(多于一行)。如果你希望捕捉该错误,可以使用一个异常块,例如:

BEGIN
    SELECT * INTO STRICT myrec FROM emp WHERE empname = myname;
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            RAISE EXCEPTION ‘employee % not found‘, myname;
        WHEN TOO_MANY_ROWS THEN
            RAISE EXCEPTION ‘employee % not unique‘, myname;
END;

成功执行一个带STRICT的命令总是会将FOUND置为真。

对于带有RETURNINGINSERT/UPDATE/DELETE,即使没有指定STRICTPL/pgSQL也会针对多于一个返回行的情况报告一个错误。这是因为没有类似于ORDER BY的选项可以用来决定应该返回哪个被影响的行。

如果为该函数启用了If print_strict_params,那么当因为 STRICT的要求没有被满足而抛出一个错误时,该错误消息 的DETAIL将包括传递给该查询的参数信息。可以通过设置 plpgsql.print_strict_params为所有函数更改 print_strict_params设置,但是只有修改后被编译的函数 才会生效。也可以使用一个编译器选项来为一个函数启用它,例如:

CREATE FUNCTION get_userid(username text) RETURNS int
AS $$
#print_strict_params on
DECLARE
userid int;
BEGIN
    SELECT users.userid INTO STRICT userid
        FROM users WHERE users.username = get_userid.username;
    RETURN userid;
END
$$ LANGUAGE plpgsql;

失败时,这个函数会产生一个这样的错误消息

ERROR:  query returned no rows
DETAIL:  parameters: $1 = ‘nosuchuser‘
CONTEXT:  PL/pgSQL function get_userid(text) line 6 at SQL statement

 

注意

STRICT选项匹配 Oracle PL/SQL 的SELECT INTO和相关语句的行为。

对于要处理来自于一个 SQL 查询的结果行的情况,请见第 43.6.6 节

以上是关于PostgreSQL使用select into时有无STRICT关键字的区别的主要内容,如果未能解决你的问题,请参考以下文章

select into 时有无strict关键字的区别

select into 时有无strict关键字的区别

select into 时有无strict关键字的区别

postgresql/lightdb中对应ctas的select into

PostgreSQL SELECT INTO和INSERT INTO SELECT 两种表复制语句

Postgresql存储过程select into temp table。