作为PL / PGSQL的新手,我正在尝试做一些适用于(至少一个)其他PL / SQL环境的东西,而且我还没有能够在PL / PGSQL中分离出这样做的方法。
我正在创建一个函数,并将一个变量传递给函数。使用此变量,我构建(或留空)一个变量,然后将其包含在最终的SQL语句中,然后执行该语句。
我已经尝试在代码中使用CASE和IF添加注释来表示尝试。 我查阅了文档,其中列出了CASE和IF的CAS版本以及CASE和IF的PL / PGSQL版本,但我无法确定它们之间的差异和正确使用,当然,是否我试图使用它的方式是允许的,或者如何正确地实现它。
--DROP FUNCTION public._1_ExampleQuery(varchar);
CREATE OR REPLACE FUNCTION public._1_ExampleQuery(namefield varchar(50) DEFAULT 'name')
RETURNS TABLE(id double precision , name character varying(100), frc smallint)
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
-- ------ GOAL -------------------------------------------------------------
--
-- If 'namefield' is blank, set namedwhere as empty, if namefield is
-- present build sql structure to omit blanks
-- ------ Attempt using CASE -----------------------------------------------
--
-- CASE namefield
-- WHEN '' THEN
-- namedwhere varchar(50) := '';
-- ELSE
-- namedwhere varchar(50) := ' and ' || namefield || ' <> '''' ';
-- END CASE;
-- ------ Attempt using If ------------------------------------------------
--
-- IF namefield = '' THEN
-- namedwhere varchar(50) := '';
-- ELSE
namedwhere varchar(50) := ' and ' || namefield || ' <> '''' ';
-- END IF;
-- ---------------------------------------------------------------------------
sqlQuery varchar(500) := 'SELECT id,name,frc FROM road_nw WHERE frc = 1 ' || namedwhere;
BEGIN
-- RAISE NOTICE 'SQL Query Statement: %',sqlQuery;
RETURN QUERY EXECUTE sqlQuery;
END;
当我取消注释CASE部分时,我收到此错误:
ERROR: syntax error at or near "CASE"
LINE 10: CASE namefield
^
SQL state: 42601
Character: 480
当我取消注释IF部分时,我得到了类似的错误:
ERROR: syntax error at or near "IF"
LINE 17: IF namefield = '' THEN
^
SQL state: 42601
Character: 752
我使用的PostgreSQL版本是: 在x86_64-unknown-linux-gnu上的PostgreSQL 9.3.19,由gcc编译(Ubuntu 4.8.4-2ubuntu1~14.04.3)4.8.4,64位
总而言之,可以在函数的声明部分使用CASE和IF,如果是这样的话怎么样?如果他们不能,那么实现具有SQL语句的条件部分的目标的正确方法是什么。
答案 0 :(得分:0)
第一个问题,你不能在DECLARE部分使用case-endcase或if-then-else-endif。
第二个问题是SQL注入。
另请注意,varchar与文本相同,只是(略微)慢。
我添加了RETURNS NULL ON NULL INPUT
,因为null会导致错误。
并添加了quote_identifier来阻止SQL注入
CREATE OR REPLACE FUNCTION public._1_ExampleQuery(namefield varchar(50) DEFAULT 'name')
RETURNS TABLE(id double precision , name character varying(100), frc smallint)
LANGUAGE 'plpgsql'
RETURNS NULL ON NULL INPUT
AS $BODY$
DECLARE
-- ------ GOAL -------------------------------------------------------------
--
-- If 'namefield' is blank, set namedwhere as empty, if namefield is
-- present build sql structure to omit blanks
sqlQuery text;
namedwhere text;
BEGIN
IF namefield = '' THEN
namedwhere := '';
ELSE
namedwhere := ' and ' || quote_identifier(namefield) || ' <> '''' ';
END IF;
sqlQuery := 'SELECT id,name,frc FROM road_nw WHERE frc = 1 ' || namedwhere;
-- RAISE NOTICE 'SQL Query Statement: %',sqlQuery;
RETURN QUERY EXECUTE sqlQuery;
END;
$BODY$;
如果你想将null namefield视为空,则反转if,并删除RETURNS NULL ON NULL INPUT
另一种方法是使用CASE ... END表达式而不是变量。 (这里我将null视为空白)
RETURN QUERY EXECUTE ( 'SELECT id,name,frc FROM road_nw WHERE frc = 1 '
|| CASE WHEN namefield <> ''
THEN ' and ' || quote_identifier(namefield) || ' <> '''' '
ELSE ''
END );