sql - 实现表级检查约束

标签 sql oracle relational-database constraints range

我们有一个表格,其中包含取决于基本金额的价格。例如,如果基本金额小于或等于 100,则价格为 10,但如果基本金额大于 100 但小于或等于 1000,则价格为 20,最后如果基本金额大于1000 那么价格是 30。我们的表格的简化版本应该是这样的:

PRICE_CODE START_RANGE     END_RANGE  PRICE_AMOUNT 
100               0,00        100,00         10,00           
100             100,01       1000,00         20,00          
100            1000,01   99999999,99         30,00           
110               0,00   99999999,99         15,00 

使用列级别检查约束,您可以轻松确保每条记录都包含有效的范围信息。问题是我们还应该需要某种表级别检查约束,以确保每个价格代码的范围信息不包含任何重叠或间隙,如本例所示:

PRICE_CODE START_RANGE     END_RANGE  PRICE_AMOUNT 
100               0,00        200,00         10,00           
100             100,01       1000,00         20,00          
100            1100,01   99999999,99         30,00           

我创建了一个有效的验证过程,但问题是我在数据库中没有找到任何可以调用验证逻辑的地方。当然,您不能放置在记录级触发器中,但是当可以进行单独的插入、更新和删除并且范围应该只针对最终结果进行验证时,语句级触发器也不会工作。验证逻辑应该是这样的:

SELECT * FROM (              
SELECT price_code, start_range, end_range, price_amount
     , lag (end_range) OVER (PARTITION BY price_code ORDER BY end_range) prev_end
     , lead (start_range) OVER (PARTITION BY price_code ORDER BY start_range) next_start
  FROM my_test
ORDER BY price_code, start_range, end_range) 
 WHERE start_range <= prev_end
    OR end_range >= next_start
    OR (next_start - end_range) > 0.01
    OR (start_range - prev_end) > 0.01

一种方法当然是将验证逻辑放在数据访问层,但仍然可以通过直接使用 SQL 来绕过验证。我感兴趣的是,是否有人对如何在数据库中实现这种“表级约束”有一些想法,以确保没有人能够提交无效的范围数据。我们使用的是 Oracle,所以我对基于 Oracle 的解决方案很感兴趣,但我也对任何其他 RDBMS 如何解决这个问题感兴趣。

最佳答案

是否需要 end_range 列? end_range 值也可以是下一个更高的 start_range 值。如果你这样做,间隙和重叠是不可能的。

关于sql - 实现表级检查约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13468327/

相关文章:

java - Hibernate:如何从 "many"一侧删除 "one"一侧的一对多关系中的实体

mysql - 将非关系表拆分为多个关系表

sql - 带有 If 语句 AND OR 条件的 Oracle 触发器

mysql - 如何选择第二个表中具有最多不同行的行 - MySQL?

mysql - Oracle 在 for 循环中提交

sql - 在左连接中使用 Oracle rank()

mysql - 我的数据库模型的有效性

java - SQLITE 文件大小小?

php - mySQL 查询不存在

sql - 确定 BLOB 的高度和宽度