请考虑以下对象:
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)
它扫描所有三个表。
是否有人知道以任何方式强制检查/插入函数,以便检查约束可以使用它?
答案 0 :(得分:3)
问题是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);