2012-12-10 23 views
1

我一個Postgres 8.3數據庫上工作,試圖用PL/pgSQL的創建基於輸入到表格日期的表名功能:參數化的表名

我已經創造了一系列的由日期,例如索引表:

drop table one_day_11_13 cascade; 
create table one_day_11_13 as 
select * from master_table where 
timestamp < '2012-11-14' and timestamp >= '2012-11-13'; 

drop table one_day_11_14 cascade; 
create table one_day_11_14 as 
select * from master_table where 
timestamp < '2012-11-15' and timestamp >= '2012-11-14'; 

我想這樣做是創建了作爲參數('11_13', '2012-11-14', '2012-11-13')例如創建上面的第一個表中的PL/pgSQL函數的方式。我無法編碼適當的EXECUTE語句。

做這種事情的最好方法是PL/pgSQL矯枉過正?

回答

4

首先,考慮升級到更新的版本。 8.3 is on its way out.

8.3它可以工作是這樣的:

CREATE OR REPLACE FUNCTION f_recreate_tbl(date, date) 
RETURNS void AS 
$func$ 
DECLARE 
    -- derive tablename from first date 
    _tbl text := 'one_day_' || to_char($1, 'MM_YY'); 
BEGIN 

-- Use IF EXISTS to avoid an exception when table does not exist. 
EXECUTE 
'DROP TABLE IF EXISTS ' || _tbl || ' CASCADE'; 

EXECUTE 
'CREATE TABLE ' || _tbl || ' AS 
SELECT * 
FROM master_table 
WHERE timestamp >= ''' || $1::text || '''::date 
AND timestamp < ''' || $2::text || '''::date'; 

END 
$func$ LANGUAGE plpgsql; 

電話:

SELECT f_recreate_tbl('2012-11-13'::date, '2012-11-14'::date); 
  • 每當你想參數標識,您不能使用純SQL。在PL/pgSQL函數中使用EXECUTE動態SQL,或使用DO statement(9.0+版)。

  • 此版本足夠安全。通過更靈活的輸入,您必須使用quote_ident() and quote_literal()來清除標識符和值,以防止可能的SQL注入。

  • 在現代版本(自8.4開始)中,您可以使用USING子句將轉換參數跳轉到文本。

  • 請勿使用timestamp作爲列名稱。這是數據類型的名稱。

  • 使用DROP TABLEIF EXISTSAlready available in 8.3.

  • 我從日期派生表名並跳過第三個參數。看起來像一個簡化。

+0

感謝您提供了這樣一個深思熟慮的答案。我們使用的是分叉8.3的MPP數據庫,所以感謝您保持答案與所討論的版本一致。我希望我們有9.0的功能..... – user7980

+1

也在更現代的版本中,您可以使用'format'和'%I'格式說明符來代替'quote_ident',從而提供更多可讀的動態查詢。 –