Ahm*_*mad 1 sql postgresql exists plpgsql postgresql-8.4
我在PostgreSQL中有一个存储过程
CREATE OR REPLACE FUNCTION show_senti_lang_setting(IN _senti_id bigint)
RETURNS TABLE(lang_code character, native_name character varying, is_active boolean) AS
$BODY$
BEGIN
RETURN QUERY
SELECT
l.lang_code,
l.native_name,
(CASE WHEN s.senti_id is NULL THEN FALSE
ELSE TRUE
END) is_active
FROM
language l
LEFT JOIN senti_lang s
ON s.lang_code=l.lang_code
AND s.senti_id=_senti_id;
END;
$BODY$
LANGUAGE plpgsql VOLATILE STRICT;
Run Code Online (Sandbox Code Playgroud)
错误是:
ERROR: syntax error at or near "$1"
LINE 1: ...HEN s.senti_id is NULL THEN FALSE ELSE TRUE END) $1 FROM l...
^
QUERY: SELECT l.lang_code, l.native_name, (CASE WHEN s.senti_id is NULL THEN FALSE ELSE TRUE END) $1 FROM language l LEFT JOIN senti_lang s ON s.lang_code=l.lang_code AND s.senti_id= $2
CONTEXT: SQL statement in PL/PgSQL function "show_senti_lang_setting" near line 13
********** Error **********
ERROR: syntax error at or near "$1"
SQL state: 42601
Context: SQL statement in PL/PgSQL function "show_senti_lang_setting" near line 13
Run Code Online (Sandbox Code Playgroud)
似乎错误是由CASEplpgsql引起的.相同的函数在SQL中运行良好:
CREATE OR REPLACE FUNCTION show_senti_lang_setting(bigint)
RETURNS TABLE(lang_code character, native_name character varying, is_active boolean) AS
$BODY$
SELECT
l.lang_code,
l.native_name,
CASE WHEN s.senti_id is NULL THEN FALSE
ELSE TRUE
END is_active
FROM
language l
LEFT JOIN senti_lang s
ON s.lang_code=l.lang_code
AND s.senti_id=$1;
$BODY$
LANGUAGE sql VOLATILE STRICT;
Run Code Online (Sandbox Code Playgroud)
版本8.4的OUT参数与返回的行(is_active)中的列别名相同.这已经被修改了,它适用于PostgreSQL 9.1或更高版本(甚至可能是9.0).这就是你的语法错误的原因.
列别名只是这个星座中的噪音.它们被丢弃以支持声明的OUT参数.他们唯一的目的可能是文档,所以只需将其作为评论并避免冲突开始:
CASE WHEN s.senti_id is NULL THEN FALSE ELSE TRUE END -- AS is_active
Run Code Online (Sandbox Code Playgroud)
也:
AS带有列别名的关键字(虽然通常可以跳过表别名).CASE声明周围没有括号.你拥有它的方式,总是返回表中的所有行language- 以及senti_lang找到匹配项的一个或多个实例.同时定义函数STRICT,因此在为NULL提供NULL值时根本没有行_senti_id.很难想象一个明智的用例.
如果找到多个匹配项,我不希望您想要为每种语言返回多行senti_lang.所以你可以简化为:
CREATE OR REPLACE FUNCTION show_senti_lang_setting(IN _senti_id bigint)
RETURNS TABLE(lang_code character, native_name varchar, is_active boolean) AS
$func$
BEGIN
RETURN QUERY
SELECT l.lang_code
,l.native_name
,EXISTS (SELECT 1 FROM senti_lang s
WHERE s.lang_code = l.lang_code
AND s.senti_id = _senti_id) -- AS is_active
FROM language l;
END
$func$ LANGUAGE plpgsql VOLATILE STRICT;
Run Code Online (Sandbox Code Playgroud)
我会提出一个问题是否需要STRICT.
Select 1在下面的评论中回答后续问题.我引用手册EXISTS:
由于结果仅取决于是否返回任何行,而不取决于这些行的内容,因此子查询的输出列表通常不重要.常见的编码约定是以EXISTS(SELECT 1 WHERE ...)的形式编写所有EXISTS测试.
基本上你可以编写任何语法上有效的表达式.无论如何它都被丢弃了.
我们一直在讨论这个相关问题的可读性.
| 归档时间: |
|
| 查看次数: |
3164 次 |
| 最近记录: |