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)
请帮助消除此重复的表级行...
答案 0 :(得分:1)
在查询过程中,我需要更改一些内容。
首先,在底部的dba_constraints
和dba_cons_columns
之间有一个联接。这将使您的查询在多列约束的每一列中都有一行。如果您不希望这样做,则必须从查询的主要部分中删除dba_cons_columns
。在与此类似的情况下,另一种选择是将联接保留在dba_cons_columns
上,并添加一个GROUP BY
,其中包含您从dba_constraints
中选择的所有列。但是,search_condition
是LONG
,而您不能GROUP BY
是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
子句来做到这一点:我建议仅使用一个子句:写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
表达式以获取列名。