Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在PL/pgSQL中使用关键字清理用户输入_Sql_Database_Postgresql_Plpgsql_Dynamic Sql - Fatal编程技术网

在PL/pgSQL中使用关键字清理用户输入

在PL/pgSQL中使用关键字清理用户输入,sql,database,postgresql,plpgsql,dynamic-sql,Sql,Database,Postgresql,Plpgsql,Dynamic Sql,这就是我创建搜索词的方法: IF char_length(search_term) > 0 THEN order_by := 'ts_rank_cd(textsearchable_index_col, to_tsquery(''' || search_term || ':*''))+GREATEST(0,(-1*EXTRACT(epoch FROM age(last_edited)/86400))+60)/60 DESC'; search_term

这就是我创建搜索词的方法:

    IF char_length(search_term) > 0 THEN
        order_by := 'ts_rank_cd(textsearchable_index_col, to_tsquery(''' || search_term || ':*''))+GREATEST(0,(-1*EXTRACT(epoch FROM age(last_edited)/86400))+60)/60 DESC';
        search_term := 'to_tsquery(''' || search_term || ':*'') @@ textsearchable_index_col';
    ELSE
        search_term := 'true';
    END IF;
我在使用PLPGSQL函数时遇到一些问题:

    RETURN QUERY EXECUTE '
        SELECT
            *
        FROM
            articles
        WHERE
            $1 AND
            ' || publication_date_query || ' AND
            primary_category LIKE ''' || category_filter || ''' AND
            ' || tags_query || ' AND
            ' || districts_query || ' AND
            ' || capability_query || ' AND
            ' || push_notification_query || ' AND
            ' || distance_query || ' AND
            ' || revision_by || ' AND
            ' || publication_priority_query || ' AND
            ' || status_query || ' AND
            is_template = ' || only_templates || ' AND
            status <> ''DELETED''
        ORDER BY ' || order_by || ' LIMIT 500'
        USING search_term;
    END; $$;
返回查询执行'
挑选
*
从…起
文章
哪里
一元及
“| |出版|日期|查询| |”和
主|u类如“”||类|u过滤器| |“”,以及
“| |标记| | |”和
| |地区| | | |和
“| |能力| | |”和
“| |推送|通知|查询|”和
“| |距离| | |”和
| |修订| | |和
“| |发布|优先级|查询| |”和
“| |状态| | |”和
is|template='||仅|templates |和
状态“已删除”
按“| |按| |按|按|按|按|按|限500”订购
使用搜索词;
完(元);
返回错误:

和的参数必须是布尔类型,而不是字符64处的文本类型

与之相反:

        RETURN QUERY EXECUTE '
            SELECT
                *
            FROM
                articles
            WHERE
                ' || search_term || ' AND
                ' || publication_date_query || ' AND
                primary_category LIKE ''' || category_filter || ''' AND
                ' || tags_query || ' AND
                ' || districts_query || ' AND
                ' || capability_query || ' AND
                ' || push_notification_query || ' AND
                ' || distance_query || ' AND
                ' || revision_by || ' AND
                ' || publication_priority_query || ' AND
                ' || status_query || ' AND
                is_template = ' || only_templates || ' AND
                status <> ''DELETED''
            ORDER BY ' || order_by || ' LIMIT 500';
        END; $$;
返回查询执行'
挑选
*
从…起
文章
哪里
“| |搜索| |”和
“| |出版|日期|查询| |”和
主|u类如“”||类|u过滤器| |“”,以及
“| |标记| | |”和
| |地区| | | |和
“| |能力| | |”和
“| |推送|通知|查询|”和
“| |距离| | |”和
| |修订| | |和
“| |发布|优先级|查询| |”和
“| |状态| | |”和
is|template='||仅|templates |和
状态“已删除”
按| |按| |按| |按|按|按| | |限制500 |订购|;
完(元);
。。。这很有效。我错过什么了吗?

我的目标是清理我的用户输入。

如果您的一些输入参数可以为NULL或空,并且在这种情况下应该忽略,那么您最好根据用户输入动态构建整个语句,并完全省略相应的
WHERE
/
ORDER BY
子句

关键是在这个过程中正确、安全(优雅)地处理NULL和空字符串。对于初学者来说,
search\u term'
是比
char\u length(search\u term)>0更聪明的测试。见:

您需要对PL/pgSQL有一个坚定的理解,否则您可能会陷入困境。您案例的示例代码:

CREATE OR REPLACE FUNCTION my_func(
         _search_term            text = NULL  -- default value NULL to allow short call
       , _publication_date_query date = NULL 
    -- , more parameters
       )
  RETURNS SETOF articles AS
$func$
DECLARE
   sql       text;
   sql_order text;   -- defaults to NULL

BEGIN
   sql := concat_ws(' AND '
    ,'SELECT * FROM articles WHERE status <> ''DELETED'''  -- first WHERE clause is immutable
    , CASE WHEN _search_term <> ''            THEN '$1 @@ textsearchable_index_col' END  -- ELSE NULL is implicit
    , CASE WHEN _publication_date_query <> '' THEN 'publication_date > $2'          END  -- or similar ...
 -- , more more parameters
   );

   IF search_term <> '' THEN  -- note use of $1!
      sql_order  := 'ORDER BY ts_rank_cd(textsearchable_index_col, $1) + GREATEST(0,(-1*EXTRACT(epoch FROM age(last_edited)/86400))+60)/60 DESC';
   END IF;

   RETURN QUERY EXECUTE concat_ws(' ', sql, sql_order, 'LIMIT 500')
   USING  to_tsquery(_search_term || ':*')  -- $1  -- prepare ts_query once here!
        , _publication_date_query           -- $2  -- order of params must match!
     -- , more parameters
   ;

END
$func$  LANGUAGE plpgsql;
更多:

注意
concat_ws()
的策略用法。见:

下面是一个相关的答案,有很多解释:


那么问题在于
$1
什么是
搜索词
?如果它类似于
column\u a='some\u string'
,那么它将不适用于准备好的语句,因为这些语句不能用于动态SQL。
search\u term
是用户输入的一个任意字符串值。那么有没有其他方法来清理我的用户输入?
search\u term
不能只是一个任意字符串值。执行时,它必须是一个计算为布尔值的表达式,否则您的第二个代码片段也会出错。请显示一个和一些示例输入。不要将整个代码片段与大量不相关的噪声一起转储,而忽略了重要的部分。首先,这两种尝试都不利于清理用户输入。正在打开SQL注入漏洞。。。
SELECT * FROM my_func(_publication_date_query => '2016-01-01');