2017-08-07 127 views
0

试图弄清楚如何使预处理语句在plpgsql中工作以便清理我的代码。PostgreSQL中的准备语句

PREPARE statements(text, text, text, text, text, text, text, text, text, text, text, text) AS 
         'SELECT 
          * 
         FROM 
          articles 
         WHERE 
          ' || $1 || ' AND 
          ' || $2 || ' AND 
          primary_category LIKE ''' || $3 || ''' AND 
          ' || $4 || ' AND 
          ' || $5 || ' AND 
          ' || $6 || ' AND 
          ' || $7 || ' AND 
          ' || $8 || ' AND 
          ' || $9 || ' AND 
          ' || $10 || ' AND 
          ' || $11 || ' AND 
          is_template = ' || §12 || ' AND 
          status <> ''DELETED'' 
         ORDER BY ' || $13 || ' LIMIT 500'; 

        RETURN QUERY EXECUTE statements(search_term, publication_date_query, category_filter, tags_query, districts_query, capability_query, push_notification_query, distance_query, revision_by, publication_priority_query, status_query, only_templates, order_by); 

上面的代码返回

ERROR: syntax error at or near "'SELECT 
         * 
        FROM 
         articles 
        WHERE 
         '" 
LINE 67:  'SELECT 

我declade我的变量,像这样:

DECLARE 
tags_query text := 'true'; 
BEGIN 
     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; 
... 

我在这个新的,请不要马上惊慌,如果它是什么傻,我没有注意到。

编辑:在PostgreSQL版本9.6

编辑:我知道了documentation的。

+0

你想实现什么? –

+0

我想清理我的用户输入。我读了@UsagiMiyamoto,那准备的报表是VS sql注入的方式。 – Spacemoose

+0

您不应该需要连接来构建您的准备好的语句。在链接的文档中,看看在第一个示例中“$ 1”到“$ 4”是如何在声明中使用的。我也非常肯定你不能提供整个表达式作为参数(例如,在你的语句中'$ 1' ='COLUMN = VALUE'和'$ 1 AND ...'),但应该只提供值(即'$ 1' = 'VALUE'和'COLUMN = $ 1 AND ...'在你的声明中),但是我找不到它在你链接的文档中指定的,所以我可能是错的。 – Aaron

回答

0

我看到更多的问题。

  1. PLPGSQL不支持明确准备好的命令 - 所以SQL EXECUTE命令比PLPGSQL EXECUTE命令不同。 PLpgSQL EXECUTE命令的参数是SQL字符串 - 不是准备好的命令的名称。有没有干净的方式,如何从PLpgSQL执行SQL明确准备的命令。所以,在PLpgSQL中组合PREPARE cmd(); EXECUTE cmd()没有任何意义。
  2. 准备语句的参数应该通过清除值 - 它不能用在撇号中。 ''$ n'是另一个废话。只要$ n是安全的。 '$ n'表示字符串“$ n”,可能与您所期望的不同。