有时加载批量数据时,建议临时删除表上的约束和索引。但是当我这样做时,我遇到了一些依赖问题。我简化的例子:
CREATE TABLE public.t_place_type
(
id serial NOT NULL,
c_name character varying(100),
CONSTRAINT pk_t_place_type PRIMARY KEY (id)
);
CREATE TABLE public.t_place
(
id serial NOT NULL,
c_name character varying(50),
id_place_type integer,
CONSTRAINT pk_t_place PRIMARY KEY (id),
CONSTRAINT fk_t_place_t_place_type FOREIGN KEY (id_place_type)
REFERENCES public.t_place_type (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
CREATE OR REPLACE VIEW public.v_place AS
SELECT p.id,
p.c_name,
pt.c_name AS c_place_type
FROM t_place p
LEFT JOIN t_place_type pt ON pt.id = p.id_place_type
GROUP BY p.id, pt.id, p.c_name;
我的剧本:
ALTER TABLE public.t_place DROP CONSTRAINT fk_t_place_t_place_type;
ALTER TABLE public.t_place DROP CONSTRAINT pk_t_place;
ALTER TABLE public.t_place_type DROP CONSTRAINT pk_t_place_type;
当我运行它时,我收到错误:
错误:无法在表t_place_type上删除约束pk_t_place_type 因为其他对象依赖于它 DETAIL:view v_place依赖于表上的约束pk_t_place_type t_place_type
我很奇怪,视图可以取决于某些约束。 AFAIK postgres不会缓存视图的执行计划。
当我以这种方式改变我的观点时:
CREATE OR REPLACE VIEW public.v_place AS
SELECT p.id,
p.c_name AS c_name,
pt.c_name AS c_place_type
FROM t_place p
LEFT JOIN t_place_type pt ON pt.id = p.id_place_type;
依赖关系消失了,我的脚本成功执行。
所以我的问题是:视图和约束之间存在这种依赖关系的原因是什么。
修改
此处https://www.postgresql.org/docs/9.5/static/sql-select.html#SQL-GROUPBY postgres文档说:
当存在GROUP BY或存在任何聚合函数时,它 对SELECT列表表达式无效以引用未分组 除聚合函数内或未分组列时的列 功能上依赖于分组列,因为它会 否则为一个未分组的人返回一个以上的可能值 柱。如果分组列(或a),则存在功能依赖性 其子集)是包含该表的表的主键 未分组的专栏。
这是这种行为的原因吗?即使我在视图中没有未分组的列?
答案 0 :(得分:1)
如果您在public.t_place_type
上删除PK,那么您在查看中的查询将无效。
会产生此错误:
ERROR: column "pt.c_name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 3: pt.c_name AS c_place_type
^
这是因为,从您的文档引文A functional dependency exists if the grouped columns (or a subset thereof) are the primary key of the table containing the ungrouped column
。
Postgres知道PK代表唯一的行,所以一旦你按照它进行分组,你也可以将该表中的所有列分组并得到相同的结果。
那些给出相同的结果,是未分组的行:
SELECT * FROM public.t_place;
SELECT * FROM public.t_place GROUP BY id;
SELECT * FROM public.t_place GROUP BY id, c_name;
SELECT * FROM public.t_place GROUP BY id, c_name, id_place_type;
SELECT * FROM public.t_place GROUP BY id, id_place_type;
您在选择pt.c_name AS c_place_type
时使用此依赖关系,因为您按主键pt.id
对该表进行了分组,一旦删除它就不存在PK,因此按其分组会{{1}两者都没有在聚合中使用而在pt.c_name
中没有使用。这就是为什么Postgres抱怨视图依赖 - 一旦你放弃这个PK,它的查询将不再起作用。
您可以使用您问题中的修改示例自行尝试:
group by