具有复杂约束的Oracle sql查询

时间:2016-07-01 11:17:42

标签: sql oracle

名为 T1 的表,其值为

Col1    Col2    Col3
Rs1     S       S2
Rs2     SX      S3
Rs3     S       S2  

从csv中,我需要在表中插入一些值,每个列的值分别为Rs4,SX和S3。

我需要应用具有以下约束条件的支票。

  • 一个S3只能属于一个SX,但S3和SX作为一对可以属于多个columns1的值。

oracle的查询是什么?如果上述条件为真,那么我需要运行一个准备好的插入查询。它如何验证?

PS:我们无法创建另一个表。

3 个答案:

答案 0 :(得分:1)

在得知我完全错过了ORACLE标签之后,不得不做一点发现。了解你不知道的事情对我来说非常重要。这篇文章应该有很大的不同。

ORACLE检查的基本问题

  
      
  • 无法在SQL视图上定义检查约束。在表上定义的检查约束必须仅引用其中的列   表。它不能引用其他表中的列。
  •   
  • 检查约束不能包含SQL子查询。
  •   
  • 可以在SQL CREATE TABLE语句或SQL ALTER TABLE语句中定义检查约束。
  •   

重新解决问题

  • 我们知道(Col2,Col3)| #(Col2,CO13)> = 1.
  • 我们知道{Col1}∩(Col2,Col3)
  • 然而,Col1的#Cardinality?可以超过1吗?

显然,业务要求尚未完全解释。

重新解决方案

  1. 将对象添加到数据库。
  2. 虽然添加额外的表已被拒绝,但是可以添加ID列吗?假设Col1不是(Col2,COl3)子集唯一的,那么您可以添加一个真正的ID列,以满足规范化的需要,同时在查询中提供真正的索引功能。

    Col1    Col2    Col3  Col4
    Rs1     S       S2    1
    Rs2     SX      S3    2
    Rs3     S       S2    1
    

    要清楚,Col4仍然是一个ID,因为Col2,Col3的值由Col4决定。 (Col2,Col3) 1:1 Col4

    1. CHECKS
    2.   
          
      • 多个CHECK约束,每个约束都有一个简单的条件强制执行   单个业务规则,优于单个CHECK约束   执行多个业务规则的复杂条件ORACLE - Constraint
      •   
      • 单个列可以有多个引用的CHECK约束   列中的定义。 CHECK的数量没有限制   您可以在列上定义的约束。 ORACLE - Data Integrity
      •   

      如果你可以通过猴子的爱来添加一个专栏...... ,请做...它不仅会让你的生活变得更轻松,而且你也可以让桌面非常高效地查询。但是,对于本文的其余部分,我将假设您无法添加列

      重新制定约束中的问题

      • Col2可能不会与其他Col3一起出现。副Versa。
      • (Col2,Col3)可能有多个Co1 ... Col1可能的基数是多少?它可以重复吗? 我读不了

      写出检查理论

      如果Col1在{(col2,col3)}中确实是唯一的,那么以下内容已经有效:

      ALTER TABLE EXAMPLE3
      ADD CONSTRAINT ch_example3_3way  UNIQUE (C, D, X) --only works if these valus never repeat.
      
      • 另一个主要约束#(Col2,Col3)>除非您知道输入了什么价值以强制执行真正的SARG,否则1根本无法工作。任何Col1 = Col1Col1 IN Col1都与写1 = 1相同。

      ON TRIGGERS

      • 听到这个想法听起来很诱人,快速浏览一下ORACLE车道让我警告不要使用。 ORACLE
      • 的一些原因
        

      ORACLE - USING TRIGGERS

           
          
      • 不要创建递归触发器。   例如,如果在上创建了AFTER UPDATE语句触发器   employees表,触发器本身发出UPDATE语句   在employees表中,触发器以递归方式触发,直到它用完为止   记忆
      •   
      • 明智地在DATABASE上使用触发器。每次创建触发器的事件发生时,都会为每个用户执行它们
      •   
           

      其他问题包括:TOADWORLD - ORACLE WIKI

           
          
      • 未编译 - STORED PROC可以重复使用缓存计划
      •   
      • 没有SELECT触发器支持
      •   
      • 完成触发失败
      •   
      • 已禁用触发器
      •   
      • 无版本控制
      •   
      • 更新栏目
      •   
      • 不支持SYS表触发器
      •   
      • 变异触发器
      •   
      • 隐藏行为
      •   

      仍然有TRIGGER的优点,你仍然可以通过使用查询的第一个结果

      来强制执行数据完整性

      SELECT Col2, Col3 FROM T1 WHERE ROWNUM = 1

      与插入的值* new。* Col2,* new。* Col3进行比较,但这需要触发器每次插入一行...重新编译和一切,。我非常谨慎避免。

      STORED PROCS

      无论你怎么想STORED PROCEDURES,我建议你再考虑一下。 FunctionDMLDDLdatabase managementRECURSIVE LOGICsp_executesql以及更远的所有内容都可以通过{{1}完成}。

      • 易于管理,提供意外或恶意禁用或多处编码的封装。
      • PROC编译一次,可以重用查询计划缓存,提供更好的性能。
      • 提供卓越的可移植性,可以嵌入到 PROCTRIGGERS框架,应用程序及其他内容中。
      • 几乎可以自动化数据库中的任何功能,包括ORMETL,安全性和发现。 Resource management通常通过存储过程运行。

      ORACLE的独特优势

      也许已经忘记了,请考虑这是ORACLE,它允许您通过插入Views CONSTRAINTS来暂停CONSTRAINT。从DEFFERABLE专家的角度来看,这实际上是从你唯一的表格中制作一个临时表...这在你有限ETL权利的困境中非常甜蜜。

      结束评论

      有一些有效的方法可以删除数据中的重复项。

      DDL
      • 注意: rowid是行的物理位置,而rownum表示查询中的逻辑位置。

      最后,我最后一次尝试rowid。不幸的是,时间很晚,ORACLE的免费COMPILER无益。但我认为这个想法很重要。

      DELETE FROM T1
      WHERE rowid NOT IN
                  (SELECT MAX(rowid)
                   FROM T1
                   GROUP BY Col1, Col2, Col3);
      

答案 1 :(得分:1)

最后,我能够通过一些选择查询解决问题,如果应用了条件则很少。我在存储过程中完成了这个。

  SELECT count(col3) 
  INTO V_exist_value
  FROM T3 
  WHERE col3's value = Variable_col3
  AND col1's value <> Variable_col1 
  AND col2's value = Variable_col2;

  IF (V_exist_value >= 1) THEN     
      INSERT INTO T3 (col1, col2, col3)
      VALUES (Variable_col1, Variable_col2, Variable_col3);
  ELSE 
      SELECT count(col3) 
      INTO V_exist_value1 
      FROM T3 
      WHERE col3's value = Variable_col3;

      IF (V_exist_value1 = 0) THEN
        INSERT INTO T3 (col1, col2, col3)
      VALUES (Variable_col1, Variable_col2, Variable_col3);
  ELSE 
        RAISE Exception_col3_value_exists;
      END IF;

  END IF;

答案 2 :(得分:0)

如果您不想使用触发器,则必须对表格进行标准化。

  1. 创建第二个表 - 比如T1_PAIRS - 将存储所有允许的对(col2,col3)。
  2. 在表格col2中的T1_PAIRS列上创建唯一约束 - 此约束仅允许COL2的唯一值 - 例如,不超过一个S3值在所有对中使用==&gt;这强制执行规则:“一个S3只能属于一个SX”
  3. 在此表( col2, col3 )中的T1_PAIRS列上创建主键。
  4. ( col2, col3 )表中T1创建引用T1_PAIRS表主键的外键约束。
  5. 最后在(col1, col2, col3) columnt上创建一个唯一约束来强制执行规则==&gt; S3和SX作为对可以属于多个columns1的值(但不超过column1的一个值)“
  6. 一个例子:

    CREATE TABLE T1_PAIRS (
       Col2 varchar2(10), Col3 varchar2(10),
       CONSTRAINT T1_PAIRS_PK PRIMARY KEY( col2, col3 ),
       CONSTRAINT T1_col2_UQ UNIQUE( col2 )
    );
    
    INSERT ALL
        INTO T1_PAIRS( col2, col3 ) VALUES( 'S', 'S2' )
        INTO T1_PAIRS( col2, col3 ) VALUES( 'SX', 'S3' )   
    SELECT 1 FROM dual;
    
    ALTER TABLE T1
    ADD CONSTRAINT col2_col3_pair_fk 
    FOREIGN KEY ( col2, col3 ) REFERENCES T1_pairs( col2, col3 );
    
    ALTER TABLE T1
    ADD CONSTRAINT pair_can_belong_to_multi_col1 UNIQUE( col1, col2, col3 );