Неверный вывод Oracle Query - PullRequest
0 голосов
/ 01 марта 2019
            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 голосов
/ 01 марта 2019

Проходя по вашему запросу, я бы изменил несколько вещей.

Во-первых, внизу у вас есть соединение между dba_constraints и dba_cons_columns.Это приведет к тому, что в вашем запросе будет одна строка для каждого столбца ограничения из нескольких столбцов.Если вы этого не хотите, вам придется удалить dba_cons_columns из основной части вашего запроса.В ситуациях, подобных этому, другим вариантом было бы сохранить соединение на dba_cons_columns и добавить GROUP BY, содержащий все столбцы в dba_constraints, из которых вы выбирали.Однако search_condition - это LONG, и вы не можете GROUP BY a LONG столбец.

Если вам нужен список имен столбцов через запятую, используйте функцию 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, чтобы сделать это: я бы предложил использовать только одно: write 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, чтобы получить имя столбца.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...