我想创建一个约束来验证值(来自“nominal_value”列)在“stats_type”列中被分类为“minimum”的值等于或小于被分类为“average”的值。换句话说,给定对应的元组,除了列“oid”、“stats_type”和“nominal_value”之外,我想确保标记为“最小值”的值总是等于或小于标记为“平均值”的值。
这很难解释,所以我举了下面这个例子:
CREATE TABLE price (
oid SERIAL NOT NULL,
product INTEGER NOT NULL,
territory INTEGER NOT NULL,
stats_type INTEGER NOT NULL,
year INTEGER NOT NULL,
nominal_value NUMERIC(6,2) NOT NULL,
data_source INTEGER NOT NULL,
CONSTRAINT pk_price PRIMARY KEY (oid),
CONSTRAINT price_1 UNIQUE (product, territory, stats_type, year, data_source),
CONSTRAINT price_2 CHECK (nominal_value > 0)
);
INSERT INTO price (oid, product, territory, stats_type, year, nominal_value, data_source) VALUES (1, 55, 5611, 1, 2014, 120, 3);
INSERT INTO price (oid, product, territory, stats_type, year, nominal_value, data_source) VALUES (2, 55, 5611, 2, 2014, 160, 3);
INSERT INTO price (oid, product, territory, stats_type, year, nominal_value, data_source) VALUES (3, 55, 5615, 1, 2014, 60, 3);
INSERT INTO price (oid, product, territory, stats_type, year, nominal_value, data_source) VALUES (4, 55, 5611, 3, 2014, 180, 3);
INSERT INTO price (oid, product, territory, stats_type, year, nominal_value, data_source) VALUES (5, 62, 5615, 1, 2013, 1500, 3);
INSERT INTO price (oid, product, territory, stats_type, year, nominal_value, data_source) VALUES (6, 62, 5615, 2, 2013, 1300, 3);
“统计类型”标签包括:1 =最小,2 =平均,3 =最大。
看前两排;除了“oid”、“stats_type”和“nominal_value”之外,它们是相等的;所以我想确认一下120(在第一行中标记为最小值)是否小于或等于160(标记为平均值的值)?在这种情况下,答案为是,因此通过了验证。
现在,最后两行(5和6)也有关于列“product”、“territory”、“year”和“data_source”的匹配。但是,碰巧第5行中的名义值1500不应小于第6行中的1300(因为1500应该是最小值,1300应该是平均值)。
我该怎么做呢?有没有可能用“检查”约束来完成这样的任务?
3条答案
按热度按时间but5z9lq1#
由于需要查询表,因此无法使用check约束来完成此操作。您可以使用触发器:
触发功能检查所有条件(最小值〈平均值〈最大值)。
cqoc49vn2#
由于您的场景非常复杂,可以按任何顺序执行插入操作,因此我建议您事先在辅助表中执行插入操作,例如price_check。
然后,您可以放置一个触发器来执行SQL,例如:
它将只返回有效的最小值,并使用它在最终表上执行插入。注意,我使用了INNER JOIN,因此没有平均值对的最小值将不会返回,您必须使用LEFT JOIN来完成此操作。
类似地,您可以设计price_check查询,将无效行放入price_log表中,以便稍后手动检查它们。
或者,您可以在您的表上放置INSTEAD OF INSERT触发器,而不需要辅助表,但即使如此,创建LOG表来手动检查和修复无效行也是一种很好的做法。
gjmwrych3#
可以考虑使用postgresql函数对表进行所有的插入/更新(或upsert),然后可以使用case逻辑来识别可以插入的内容,并为不正确的输入数据事件指定真实的的API状态返回代码,可以使用PL/pgSQL、python或任何其他适合postgres的可扩展语言来编写。
例如