2

请考虑以下对象:

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,这是我所期望的。

但是,当我查看此查询的解释计划时(今天是 10/11/13):

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

它扫描所有三个表。

有谁知道以检查约束可以利用它的方式强制检查/插值函数的任何方法?

4

1 回答 1

3

问题是where子句必须与check constraint. 由于两者date_trunc()都不current_date不可变的,它们不会在查询中“内联”,这意味着这些函数评估只会在查询执行时发生,在查询规划阶段之后,因此规划器将不知道条件是否匹配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);
于 2013-10-11T22:55:04.740 回答