检查SQL语句中的嵌套查询

时间:2010-12-08 15:06:34

标签: sql oracle

我试图添加一个约束(在Oracle中),它限制用户创建一个已经存在的字段中包含'smth','smth else'或'one more thing'的条目。基本上,这就是我写它的方式:

ALTER TABLE sometable
ADD CONSTRAINT sometable_text_chk
CHECK (
    caption IN ( 
        SELECT caption
        FROM sometable
        WHERE text NOT IN ('smth', 'smth else', 'one more thing')
    )
)

不幸的是,似乎不允许在这种情况下嵌套查询。可能有一种解决方法。

4 个答案:

答案 0 :(得分:2)

基本上你试图根据另一个表中的数据对一个表中数据的有效性进行某种一般性检查(注意:实际上可能没有,等待OP澄清他的问题)。

解决方法是:

  • 对于一般情况 - 在复杂的数据验证方面你可以在触发器中做很多事情(包括即使是最简单的更新查询也会暂停你的数据库,所以要小心使用)
  • 对于更具体的情况,您正在尝试完成一些动态验证(更具代表性的示例会很有用) - 您可以使用验证的“快照”动态维护CHECK约束(这归结为保持在check语句中引用的表的副本,所以它非常难看)
  • 也许你可以进行外键检查。这不是你通常设计数据库的方式,但如果从语义上看它 - 你声称(用你的CHECK)这个表和其他实体之间存在关系。好吧,如果那个实体没有被实现为单独的表,也许应该是? (这些问题是有时候设计不良的指标)

答案 1 :(得分:1)

ALTER TABLE sometable 
ADD CONSTRAINT sometable_text_chk 
CHECK (text not in ('smth', 'smth else', 'one more thing'))
/

此致 罗布。

答案 2 :(得分:0)

您无法添加此类CHECK约束,您需要从字面上提供可能值的完整列表:

CHECK (caption IN (Word1, Word2, Word3 ...))

但是你可以用其他方式做:

CHECK (Caption <> 'smth' and caption <> 'smth else' and caption <> 'one more thing')

但是你从某些表中丢失了支票。

答案 3 :(得分:0)

我承认这可能有点矫枉过正。如果你可以创建一个快速刷新的,提交时刷新的物化视图,其定义可以计算表中坏值的数量,(可能如下所示):

select count(*) as rows_with_errors
  from data_table   a
  join lookup_table b on(a.caption = b.caption);

查询应该返回零,因为data_table中的值可能不包含lookup_table中的值。然后在物化视图本身上创建一个检查约束,CHECK(rows_with_errors = 0)。

只要将更新或插入提交到data_table,物化视图就会刷新。但是(这就是事情),如果你在lookup_table中存在的data_table中输入一个值,count(*)将返回一个非零值,这将导致物化视图上的检查约束失败,从而导致整个insert / update语句将失败/回滚。瞧!