2017-08-07 153 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」,可能與您所期望的不同。