2012-03-19 47 views
0

我想在PL/pgSQL過程中創建一個SQL select語句。這一切都很好,直到我不得不將date添加到選擇。問題是,在select語句中比較日期時,我的日期必須用單引號''(例如'01 .01.2011')括起來,但在我的情況下,它已經是text類型,我不能將它添加到那裏。PostgreSQL execute + date

下面是應該有同樣的問題示例代碼:

CREATE OR REPLACE FUNCTION sample(i_date timestamp without time zone) 
    RETURNS integer AS 
$BODY$ 
DECLARE 
    _count integer := 0; 
    _sql text := ''; 
BEGIN 

    IF i_date IS NOT NULL THEN 
    _cond := _cond || ' AND t.created>' || i_date; 
END IF; 

_sql := 'SELECT count(*) FROM test t WHERE 1=1' || _cond; 

EXECUTE _sql INTO _count; 
RETURN _count; 

END; 
$BODY$ 
LANGUAGE plpgsql VOLATILE 
COST 100; 

是否有任何其他的方式來「逃避」的日期?或者其他一些建議?

+0

我有點困惑,你的意思是t.created在你的例子中是varchar在數據庫中? – 2012-03-19 15:02:14

+0

不,這是日期。但是如果i_date沒有圍繞它,那麼它就是在計算方程而不是比較兩個日期。 – srumjant 2012-03-20 07:49:45

回答

2

要安全有效地將值的值插入到動態構建和執行的SQL字符串中,有很多可能性。最好的一個是使用USING clause這樣的:

CREATE OR REPLACE FUNCTION sample(_date timestamp without time zone) 
RETURNS integer AS 
$BODY$ 
BEGIN 
    RETURN QUERY EXECUTE ' 
    SELECT count(*)::int 
    FROM test t 
    WHERE t.created > $1' 
    USING _date; 
END; 
$BODY$ LANGUAGE plpgsql VOLATILE; 

其實,這是一個壞榜樣,因爲它可以簡化爲:

CREATE OR REPLACE FUNCTION sample(_date timestamp) 
RETURNS integer AS 
$BODY$ 
    SELECT count(*)::int 
    FROM test 
    WHERE created > $1; 
$BODY$ LANGUAGE sql; 

另一種方法是使用quote_literal()
我在這裏寫了更多關於dynamic SQL in plpgsql的信息。

+0

謝謝Erwin! quote_literal()對我來說很完美。 – srumjant 2012-03-20 07:20:34

0

我想這樣的方式執行相同的命令

declare 
    _count integer := 0; 
    _sql text := ''; 
begin 
    _sql := 'SELECT count(*) FROM test t WHERE 1=1'; 
    EXECUTE _sql INTO _count; 
    RETURN _count; 
end; 

和它給錯誤的_integer只是聲明語句之後......不知道怎麼出來與problem..I甚至嘗試了一些來自postgre原始站點和文檔示例的例子,但他們甚至沒有運行SQL服務器允許運行的方式...

+0

您必須創建函數並調用它。 – srumjant 2013-08-02 10:59:07