有两个表
任务是: 一个国家所有城市的人口总和应该小于或等于一个国家的人口。 -
我尝试在表国家/地区创建约束,但由于查询
而收到错误ALTER TABLE country
ADD CONSTRAINT check_pop_sum
CHECK (population <= ANY(SELECT SUM(POPULATION)
FROM CITY
GROUP BY COUNTRY_CODE));
答案 0 :(得分:1)
您可以使用触发器执行此操作。检查一下:
CREATE TRIGGER check_population
BEFORE INSERT
ON CITY
FOR EACH ROW
DECLARE
POPULATION_AMOUNT_CITY NUMBER;
POPULATION_AMOUNT_COUNTRY NUMBER;
BEGIN
SELECT SUM(POPULATION) INTO POPULATION_AMOUNT_CITY FROM CITY WHERE CODE = :NEW.Country_code;
SELECT Population INTO POPULATION_AMOUNT_COUNTRY FROM COUNTRY WHERE CODE = :NEW.Country_code;
IF (POPULATION_AMOUNT_CITY + :NEW.POPULATION) > POPULATION_AMOUNT_COUNTRY THEN
RAISE_APPLICATION_ERROR(-20000, 'Population exceeded');
END IF;
END;
答案 1 :(得分:-1)
您描述的情况不是合法的数据完整性问题。所以无论如何实施,解决方案都不是约束。数据完整性主要关注数据的有效性,而不是准确性。准确性根本不是数据库的关注点。
数据完整性可分为两类:无上下文完整性和上下文完整性。无上下文完整性是指您可以在不参考任何其他数据的情况下验证数据的有效性。如果您尝试将整数值写入日期字段(例如,域检查)或将整数字段设置为“3”而不是3,或者将范围定义为“介于100和2000之间”时将其设置为3。
上下文完整性是指必须将有效性视为组的一部分。例如,任何外键。值3本身可能完全有效,但如果不存在不同表中的正确行,则可能无法进行有效性检查。
另一方面,准确性完全不同。让我们再看一下约束到100到2000之间范围的整数字段。假设值599被写入该字段。有效吗?是的,它符合所有适用的限制。这准确吗?没有办法说出来。数据本身的准确性来自数据库外部。
但是,在县内添加所有城市人口并将其与整个县人口进行比较的能力是否意味着我们可以在这里检查准确性?
不是真的,或者不是很重要。在插入新城市或更新城市人口价值时,我们可以测试所有城市人口的总数是否超过县人口。我们可以提醒用户注意问题,但我们无法告诉用户问题出在哪里。是插入还是更新中的错误?在先前输入的现有城市中,人口价值是否过大?对于许多城市来说,有几个这么大的价值吗?所有城市人口价值是否正确但国家人口是否太少?
从数据库中,没有办法说出来。我们所能做的最好的是验证不正确的总数并警告用户。但我们不能说“城市XYZ的人口太大”,因为我们无法判断这是否是问题所在。我们能做的最好的事情就是警告县内所有所有城市的总数超过了整个县定义的人口数量。由数据所有者决定问题实际发生的位置。
这似乎是一个小差异,但约束确定数据无效并且不允许操作继续(“数据完整性:防止虚假数据首先进入数据库”)。
对于城市人口,数据无效。我们甚至无法确定它是否错误,它绝对是正确的。没有理由阻止操作完成并且数据进入数据库。
如果能够有一些验证准确性的能力,那就太好了,但请注意,这甚至不是这种情况。当城市数据输入数据库时,大多数人口的人口价值可能非常错误。在最终超过县人口之前,您不会发现问题。我想,有些检查比没有检查好,但它只会在不准确导致值太大的情况下发出警报。也可能是不准确导致价值太小。因此,必须从一开始就实施某种准确性检查,以检测是否存在任何不准确之处 - 太大或太小。
那将保持数据的准确性,而不是数据库中的一些错位操作。