2013-10-11 49 views
1

請考慮以下對象:計劃不使用檢查約束

create table invoices_2011 (
    invoice_id bigint not null, 
    invoice_date date not null, 
    constraint invoice_line_2011_ck1 CHECK (invoice_date >= '2011-01-01' AND 
     invoice_date < '2012-01-01') 
); 

create table invoices_2012 (
    invoice_id bigint not null, 
    invoice_date date not null, 
    constraint invoice_line_2012_ck1 CHECK (invoice_date >= '2012-01-01' AND 
     invoice_date < '2013-01-01') 
); 

create table invoices_2013 (
    invoice_id bigint not null, 
    invoice_date date not null, 
    constraint invoice_line_2013_ck1 CHECK (invoice_date >= '2013-01-01' AND 
     invoice_date < '2014-01-01') 
); 

create or replace view invoices as 
select * from invoices_2011 
union all 
select * from invoices_2012 
union all 
select * from invoices_2013; 

如果我看看說明計劃以下查詢:

select * from invoices where invoice_date > '2013-10-01'; 

這表明,只有實際的物理表被掃描的是invoices_2013,這是我所期望的。

然而,當我看解釋計劃爲此查詢(今天是13年10月11日):

select * from invoices where invoice_date > date_trunc ('month', current_date) 

它會掃描所有三個表。

有沒有人知道有任何方式強制檢查/插值函數的方式使檢查約束可以使用它?

回答

2

問題是where子句必須匹配check constraint。由於date_trunc()current_date都不是immutable,所以它們將不會在查詢中「內聯」,這意味着這些功能評估只會在查詢計劃階段之後的查詢執行時發生,因此計劃人員將不知道該條件是否與check constraint

匹配

爲了給規劃者需要查詢將不得不動態

create or replace function select_from_invoices(
    _d date 
) returns setof invoices as $body$ 

begin 

return query execute $$ 
    select * 
    from invoices 
    where invoice_date > $1 
    $$ 
    using date_trunc('month', _d) 
; 

end; 
$body$ language plpgsql; 

現在查詢將只計劃建成date_trunc結果串接到查詢字符串後的信息。

執行:

select * 
from select_from_invoices(current_date);