Oracle Query输出不正确

时间:2019-03-01 11:01:50

标签: sql oracle

            CREATE OR REPLACE PROCEDURE test_con(p_table_owner IN varchar2, p_table_name IN varchar2, p_result OUT sys_refcursor) AS BEGIN OPEN p_result
FOR
SELECT *
FROM
    (SELECT CASE
                  WHEN uc.constraint_type ='C' THEN
                         (SELECT DECODE(COUNT(*), 1, 'CHECK on single column', 'CHECK Table level')
                          FROM dba_cons_columns ucc2
                          WHERE ucc2.constraint_name = uc.constraint_name
                          AND ucc2.owner = uc.owner
                          AND ucc2.table_name = uc.table_name)
                  WHEN uc.constraint_type = 'P' THEN 'PRIMARY KEY'
                  ELSE ''
              END AS constraint_type,
              uc.constraint_name AS CONSTRAINT_NAME,
              uc.delete_rule AS "DELETE_ACTION",
              NULL AS "UPDATE_ACTION",
              uc.status AS "STATUS_ENABLED",
              NULL AS "STATUS_FOR_REPLICATION",
              uc.search_condition AS "CONSTRAINT_KEYS",
              NULL AS data_compression,
              NULL AS default_uid,
              NULL AS partition_qty,
              (SELECT LISTAGG(ucc1.column_name, ',') WITHIN GROUP (ORDER BY ucc1.column_name) 
                 FROM dba_cons_columns ucc1
                WHERE uc.constraint_name = ucc1.constraint_name
                  AND uc.table_name = ucc1.table_name
                  AND uc.owner = ucc1.owner) AS column_names
       FROM dba_constraints uc
       WHERE uc.OWNER = 'HR'
         AND uc.TABLE_NAME = 'EMP'
         );

 END;














SELECT *
FROM
    (SELECT CASE
                  WHEN uc.constraint_type ='C' THEN
                         (SELECT DECODE(COUNT(*), 1, 'CHECK on single column', 'CHECK Table level')
                          FROM dba_cons_columns ucc2
                          WHERE ucc2.constraint_name = uc.constraint_name
                          AND ucc2.owner = uc.owner
                          AND ucc2.table_name = uc.table_name)
                  WHEN uc.constraint_type = 'P' THEN 'PRIMARY KEY'
                  ELSE ''
              END AS constraint_type,
              uc.constraint_name AS CONSTRAINT_NAME,
              uc.delete_rule AS "DELETE_ACTION",
              NULL AS "UPDATE_ACTION",
              uc.status AS "STATUS_ENABLED",
              NULL AS "STATUS_FOR_REPLICATION",
              uc.search_condition AS "CONSTRAINT_KEYS",
              NULL AS data_compression,
              NULL AS default_uid,
              NULL AS partition_qty,
              (SELECT LISTAGG(ucc1.column_name, ',') WITHIN GROUP (ORDER BY ucc1.column_name) 
                 FROM dba_cons_columns ucc1
                WHERE uc.constraint_name = ucc1.constraint_name
                  AND uc.table_name = ucc1.table_name
                  AND uc.owner = ucc1.owner) AS column_names
       FROM dba_constraints uc
       WHERE uc.OWNER = 'HR'
         AND uc.TABLE_NAME = 'EMP'
         );



         SELECT *
FROM
    (SELECT CASE
                  WHEN uc.constraint_type ='C' THEN
                         (SELECT DECODE(COUNT(*), 1, 'CHECK on single column', 'CHECK Table level')
                          FROM dba_cons_columns ucc2
                          WHERE ucc2.constraint_name = uc.constraint_name
                          AND ucc2.owner = uc.owner
                          AND ucc2.table_name = uc.table_name)
                  WHEN uc.constraint_type = 'P' THEN 'PRIMARY KEY'
                  ELSE ''
              END AS constraint_type,
              uc.constraint_name AS CONSTRAINT_NAME,
              uc.delete_rule AS "DELETE_ACTION",
              NULL AS "UPDATE_ACTION",
              uc.status AS "STATUS_ENABLED",
              NULL AS "STATUS_FOR_REPLICATION",
              uc.search_condition AS "CONSTRAINT_KEYS",
              NULL AS data_compression,
              NULL AS default_uid,
              NULL AS partition_qty,
              (SELECT LISTAGG(ucc1.column_name, ',') WITHIN GROUP (ORDER BY ucc1.column_name) 
                 FROM dba_cons_columns ucc1
                WHERE uc.constraint_name = ucc1.constraint_name
                  AND uc.table_name = ucc1.table_name
                  AND uc.owner = ucc1.owner) AS column_names
       FROM dba_constraints uc
       WHERE uc.OWNER = 'HR'
         AND uc.TABLE_NAME = 'EMP'
         );


         SELECT *
FROM
    (SELECT CASE
                  WHEN uc.constraint_type ='C' THEN
                         (SELECT DECODE(COUNT(*), 1, 'CHECK on column ' || LISTAGG(ucc2.column_name, ',') WITHIN GROUP (ORDER BY ucc2.column_name) , 'CHECK Table level')
                          FROM dba_cons_columns ucc2
                          WHERE ucc2.constraint_name = uc.constraint_name
                          AND ucc2.owner = uc.owner
                          AND ucc2.table_name = uc.table_name)
                  WHEN uc.constraint_type = 'P' THEN 'PRIMARY KEY (clustered)'
                  WHEN uc.constraint_type = 'DEFAULT' THEN 'DEFAULT on column ' || ucc1.column_name
                  ELSE ''
              END AS constraint_type,
              uc.constraint_name AS CONSTRAINT_NAME,
              uc.delete_rule AS "DELETE_ACTION",
              NULL AS "UPDATE_ACTION",
              uc.status AS "STATUS_ENABLED",
              NULL AS "STATUS_FOR_REPLICATION",
              uc.search_condition AS "CONSTRAINT_KEYS",
              NULL AS data_compression,
              NULL AS default_uid,
              NULL AS partition_qty,
              (SELECT LISTAGG(ucc1.column_name, ',') WITHIN GROUP (ORDER BY ucc1.column_name) 
                 FROM dba_cons_columns ucc1
                WHERE uc.constraint_name = ucc1.constraint_name
                  AND uc.table_name = ucc1.table_name
                  AND uc.owner = ucc1.owner) AS column_names
       FROM dba_constraints uc,
       dba_cons_columns ucc1
       WHERE   uc.constraint_name = ucc1.constraint_name
     AND uc.table_name = ucc1.table_name
     AND uc.owner = ucc1.owner
       AND   uc.OWNER = 'HR'
         AND uc.TABLE_NAME = 'EMP'

          UNION ALL SELECT 'DEFAULT on column ' || cc.column_name,
                    'DF_' || cc.column_name AS CONSTRAINT_NAME,
                    NULL AS "DELETE_ACTION",
                    NULL AS "UPDATE_ACTION",
                    NULL AS "STATUS_ENABLED",
                    NULL AS "STATUS_FOR_REPLICATION",
                    cc.data_default AS "CONSTRAINT_KEYS",
                    NULL AS data_compression,
                    NULL AS default_uid,
                    NULL AS partition_qty,
                    cc.column_name
   FROM dba_tab_columns cc
   WHERE cc.owner='HR'
     AND cc.table_name='EMP'
     AND data_default IS NOT NULL );




     SELECT *
FROM
    (SELECT CASE
                  WHEN uc.constraint_type ='C' THEN
                         (SELECT DECODE(COUNT(*), 1, 'CHECK on column ' || LISTAGG(ucc2.column_name, ',') WITHIN GROUP (ORDER BY ucc2.column_name) , 'CHECK Table level')
                          FROM dba_cons_columns ucc2
                          WHERE ucc2.constraint_name = uc.constraint_name
                          AND ucc2.owner = uc.owner
                          AND ucc2.table_name = uc.table_name)
                  WHEN uc.constraint_type = 'P' THEN 'PRIMARY KEY (clustered)'
                  WHEN uc.constraint_type = 'DEFAULT' THEN 'DEFAULT on column ' 
                  ELSE ''
              END AS constraint_type,
              uc.constraint_name AS CONSTRAINT_NAME,
              uc.delete_rule AS "DELETE_ACTION",
              NULL AS "UPDATE_ACTION",
              uc.status AS "STATUS_ENABLED",
              NULL AS "STATUS_FOR_REPLICATION",
              uc.search_condition AS "CONSTRAINT_KEYS",
              NULL AS data_compression,
              NULL AS default_uid,
              NULL AS partition_qty,
              (SELECT LISTAGG(ucc1.column_name, ',') WITHIN GROUP (ORDER BY ucc1.column_name) 
                 FROM dba_cons_columns ucc1
                WHERE uc.constraint_name = ucc1.constraint_name
                  AND uc.table_name = ucc1.table_name
                  AND uc.owner = ucc1.owner) AS column_names
       FROM dba_constraints uc

       WHERE   
      uc.OWNER = 'HR'
         AND uc.TABLE_NAME = 'EMP'

          UNION ALL SELECT 'DEFAULT on column ' || cc.column_name,
                    'DF_' || cc.column_name AS CONSTRAINT_NAME,
                    NULL AS "DELETE_ACTION",
                    NULL AS "UPDATE_ACTION",
                    NULL AS "STATUS_ENABLED",
                    NULL AS "STATUS_FOR_REPLICATION",
                    cc.data_default AS "CONSTRAINT_KEYS",
                    NULL AS data_compression,
                    NULL AS default_uid,
                    NULL AS partition_qty,
                    cc.column_name
   FROM dba_tab_columns cc
   WHERE cc.owner='HR'
     AND cc.table_name='EMP'
     AND data_default IS NOT NULL );



     SELECT *
FROM
    (SELECT CASE
                  WHEN uc.constraint_type ='C' THEN
                         (SELECT DECODE(COUNT(*), 1, 'CHECK on column ' || LISTAGG(ucc2.column_name, ',') WITHIN GROUP (ORDER BY ucc2.column_name) , 'CHECK Table level')
                          FROM dba_cons_columns ucc2
                          WHERE ucc2.constraint_name = uc.constraint_name
                          AND ucc2.owner = uc.owner
                          AND ucc2.table_name = uc.table_name)
                  WHEN uc.constraint_type = 'P' THEN 'PRIMARY KEY (clustered)'
                  WHEN uc.constraint_type = 'DEFAULT' THEN 'DEFAULT on column ' 
                  ELSE ''
              END AS constraint_type,
              uc.constraint_name AS CONSTRAINT_NAME,
              uc.delete_rule AS "DELETE_ACTION",
              NULL AS "UPDATE_ACTION",
              uc.status AS "STATUS_ENABLED",
              NULL AS "STATUS_FOR_REPLICATION",
              uc.search_condition AS "CONSTRAINT_KEYS",
              NULL AS data_compression,
              NULL AS default_uid,
              NULL AS partition_qty,
              (SELECT LISTAGG(ucc1.column_name, ',') WITHIN GROUP (ORDER BY ucc1.column_name) 
                 FROM dba_cons_columns ucc1
                WHERE uc.constraint_name = ucc1.constraint_name
                  AND uc.table_name = ucc1.table_name
                  AND uc.owner = ucc1.owner) AS column_names
       FROM dba_constraints uc

       WHERE   
      uc.OWNER = 'HR'
         AND uc.TABLE_NAME = 'T'

          UNION ALL SELECT 'DEFAULT on column ' || cc.column_name,
                    'DF_' || cc.column_name AS CONSTRAINT_NAME,
                    NULL AS "DELETE_ACTION",
                    NULL AS "UPDATE_ACTION",
                    NULL AS "STATUS_ENABLED",
                    NULL AS "STATUS_FOR_REPLICATION",
                    cc.data_default AS "CONSTRAINT_KEYS",
                    NULL AS data_compression,
                    NULL AS default_uid,
                    NULL AS partition_qty,
                    cc.column_name
   FROM dba_tab_columns cc
   WHERE cc.owner='HR'
     AND cc.table_name='T'
     AND data_default IS NOT NULL );

对于检查约束(表级别,如BONUS_CK)...它应该仅在一行中显示数据,并用逗号分隔列名...

像奖金,税金

现在,它为表级约束显示2行,即bonus_ck 查询也应适用于所有版本(10g,11g,12c)

请帮助消除此重复的表级行...

1 个答案:

答案 0 :(得分:1)

在查询过程中,我需要更改一些内容。

首先,在底部的dba_constraintsdba_cons_columns之间有一个联接。这将使您的查询在多列约束的每一列中都有一行。如果您不希望这样做,则必须从查询的主要部分中删除dba_cons_columns。在与此类似的情况下,另一种选择是将联接保留在dba_cons_columns上,并添加一个GROUP BY,其中包含您从dba_constraints中选择的所有列。但是,search_conditionLONG,而您不能GROUP BYLONG列。

如果要用逗号分隔的列名列表,请使用LISTAGG函数。例如,要获取约束中的列列表,可以在子查询中使用以下内容:

              SELECT LISTAGG(ucc1.column_name, ',') WITHIN GROUP (ORDER BY ucc1.column_name) 
                 FROM dba_cons_columns ucc1
                WHERE uc.constraint_name = ucc1.constraint_name
                  AND uc.table_name = ucc1.table_name
                  AND uc.owner = ucc1.owner

LISTAGG将所有分组在一起的值连接在一起。

类似地,要检测您是多列检查约束还是单列检查约束,您需要在dba_cons_columns上使用另一个子查询。您目前正在尝试在WHEN表达式中使用两个不同的CASE子句来做到这一点:我建议仅使用一个子句:写WHEN uc.constraint_type = 'C' THEN ...然后有一个子查询来对数字进行计数约束中的列数,并根据需要显示单列或多列。

最后,请注意Oracle不是SQL Server。看来您正在使用SQL Server中Oracle中不存在的几个术语。删除“聚集”文本:Oracle中没有这样的术语。 (Oracle确实有按索引组织的表,但我从未使用过它们。)还应删除行WHEN uc.constraint_type = 'DEFAULT' ...,因为Oracle中列的默认值未使用约束设置。

我最后得到了以下内容,它似乎可以满足您的要求:

SELECT *
FROM
    (SELECT CASE
                  WHEN uc.constraint_type ='C' THEN
                         (SELECT DECODE(COUNT(*), 1, 'CHECK on single column', 'CHECK Table level')
                          FROM dba_cons_columns ucc2
                          WHERE ucc2.constraint_name = uc.constraint_name
                          AND ucc2.owner = uc.owner
                          AND ucc2.table_name = uc.table_name)
                  WHEN uc.constraint_type = 'P' THEN 'PRIMARY KEY'
                  ELSE ''
              END AS constraint_type,
              uc.constraint_name AS CONSTRAINT_NAME,
              uc.delete_rule AS "DELETE_ACTION",
              NULL AS "UPDATE_ACTION",
              uc.status AS "STATUS_ENABLED",
              NULL AS "STATUS_FOR_REPLICATION",
              uc.search_condition AS "CONSTRAINT_KEYS",
              NULL AS data_compression,
              NULL AS default_uid,
              NULL AS partition_qty,
              (SELECT LISTAGG(ucc1.column_name, ',') WITHIN GROUP (ORDER BY ucc1.column_name) 
                 FROM dba_cons_columns ucc1
                WHERE uc.constraint_name = ucc1.constraint_name
                  AND uc.table_name = ucc1.table_name
                  AND uc.owner = ucc1.owner) AS column_names
       FROM dba_constraints uc
       WHERE uc.OWNER = 'HR'
         AND uc.TABLE_NAME = 'EMP'
         );

我决定将CHECK on column ...更改为CHECK on single column,因为单列名称在查询中的其他位置,并且似乎不值得重复。您始终可以在其中放置一个LISTAGG表达式以获取列名。