2015-10-08 53 views
0

當使用本標準的SQL一切工作正常(即正確地更換):Postgres的參數替代語法錯誤

begin transaction; 
prepare testquery2 (varchar) AS SELECT * FROM hotel WHERE name=$1; 
execute testquery2 ('Hotel'); 
end transaction; 

但有了這個特殊的Postgres的SQL:

begin transaction; 
prepare testquery1 (varchar) AS SELECT * FROM cache WHERE AGE(now() ,last_modified) > interval $1; 
execute testquery1 ('5 minutes'); 
end transaction; 

- >錯誤:語法錯誤達到或接近 「$ 1」

+1

正如您所指的是「標準SQL」。標準SQL中的間隔語法是'interval'5分鐘',但我認爲你仍然不能使用'interval $ 1 minute'。你可以做的是:'interval'1'minute * $ 1'符合SQL標準 –

回答

2

後續回覆在這裏是正確的,但我不認爲任何帖子徹底解決了海報的問題。

根本的問題涉及到區間日期/時間類型,Postgres的文檔中描述如下: http://www.postgresql.org/docs/9.1/static/datatype-datetime.html

提出的解決方案由原始的海報,因爲該位失敗,從文檔拉:

When writing an interval constant with a fields specification, or when assigning a string to an interval column that was defined with a fields specification, the interpretation of unmarked quantities depends on the fields. For example INTERVAL '1' YEAR is read as 1 year, whereas INTERVAL '1' means 1 second. Also, field values "to the right" of the least significant field allowed by the fields specification are silently discarded. For example, writing INTERVAL '1 day 2:03:04' HOUR TO MINUTE results in dropping the seconds field, but not the day field.

其結果是原來的海報的解決方案不能工作,這是很容易通過只准備和執行這個簡單的測試顯示:

prepare testquery1 (varchar) AS SELECT interval '$1'; 
PREPARE 
vkmlm=> execute testquery1 ('5 minutes'); 
interval 
---------- 
00:00:01 
(1 row) 

一種解決方法,您可以使用將遵循以下方針格式化間隔查詢:

prepare testquery2 (text) as select (INTERVAL '$1' MINUTES); 
PREPARE 
vkmlm=> EXECUTE testquery2('5'); 
interval 
---------- 
    5 minutes 
(1 row) 

但這是不夠理想。我們大多數人都希望將變量與關鍵字結合使用。幸運的是,這樣做有一個非常簡單的方法,我相信這是海報最初尋找的內容:

vkmlm=> prepare testquery3 (varchar) AS SELECT $1::interval; 
PREPARE 
vkmlm=> execute testquery3 ('5 minutes'); 
interval 
---------- 
00:05:00 
(1 row) 
-1

解決方案 - 使用引號:

begin transaction; 
prepare testquery1 (varchar) AS SELECT * FROM cache WHERE AGE(now() ,last_modified) > interval '$1'; 
execute testquery1 ('5 minutes'); 
end transaction; 

像Postgres似乎不一致,因爲不使用標準的SQL?

+1

'interval'語法只對文字有效;參數不是文字。你會遇到'PREPARE selint(integer)AS SELECT INTEGER $ 1;'或類似的問題。解析後,參數在綁定時被替換。所以你必須使用一個強制轉換,或者@a_horse_with_no_name爲間隔建議,乘以一個常量。 –

+0

您發佈的解決方案不正確。我希望你沒有把它投入生產...... – kamelkev