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
、带有RETURNING
的INSERT
/UPDATE
/DELETE
以及返回行集结果的工具命令(例如EXPLAIN
)。除了INTO
子句,SQL 命令和它在PL/pgSQL之外的写法一样。
提示
注意带INTO
的SELECT
的这种解释和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
置为真。
对于带有RETURNING
的INSERT
/UPDATE
/DELETE
,即使没有指定STRICT
,PL/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关键字的区别的主要内容,如果未能解决你的问题,请参考以下文章
postgresql/lightdb中对应ctas的select into