逗号分隔的列输出到一个plsql sproc中

时间:2019-02-19 08:35:41

标签: sql oracle

SPROC应该也兼容11g以下的版本。

创建了此过程,但是它为基于多列的索引显示2行。我想将其显示为一行,并用逗号分隔值

当前,如果我在表上执行此操作(以获取索引信息)。它向我显示2行索引(多列),但我希望每个索引仅返回一行。如果有多列,则INDEX_KEYS列应将所有列反映为逗号分隔的列表。

CREATE OR REPLACE PROCEDURE test_1 (
    p_table_owner   IN VARCHAR2,
    p_table_name    IN VARCHAR2,
    p_result        OUT SYS_REFCURSOR
)
    AS
BEGIN
OPEN p_result FOR 
SELECT
    index_name,
    index_description,
    ltrim(sys_connect_by_path(index_keys,','),',') as Index_Keys,
    include_cols,
    index_filter,
    data_compression,
    allow_page_locks,
    table_name,
    index_type    
 from 
  (
  Select t.*,  
    row_number() over (partition by INDEX_NAME order by INDEX_NAME) as rn
    from 
    (
     SELECT      

        ON dis.index_owner      = di.owner AND
           dis.index_name       = di.index_name AND
           dis.partition_name   = dip.partition_name
        JOIN dba_ind_columns ci
        ON ci.index_owner   = di.owner AND
           ci.index_name    = di.index_name
    WHERE
      --  di.table_owner = 'CON$' AND
       di.table_name = 'CON$' AND
        di.partitioned = 'YES' AND
       dip.composite = 'YES' ) t      
)
where connect_by_isleaf = 1
connect by index_name  = prior index_name
and rn = prior rn+1
start with rn =1 ;

End;

2 个答案:

答案 0 :(得分:1)

  

但是我希望每个索引只返回一行。   多列,则INDEX_KEYS列应反映所有列   作为逗号分隔的列表。

您可以在 Oracle 11g 中进行尝试:

CREATE OR REPLACE PROCEDURE test_1 (
    p_table_owner   IN VARCHAR2,
    p_table_name    IN VARCHAR2,
    p_result        OUT SYS_REFCURSOR
)
    AS
BEGIN
   OPEN p_result FOR 
   SELECT
    index_name,
    index_description,
    LISTAGG (index_keys,',') WITHIN GROUP (    ORDER BY        index_name    ) "Index_Keys",
    include_cols,
    index_filter,
    data_compression,
    allow_page_locks,
    table_name,
    index_type        
    from 
    (
    SELECT
        di.index_name AS "INDEX_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'clustered'
                ELSE 'nonclustered'
            END
        ||
            CASE
                WHEN di.uniqueness = 'UNIQUE' AND
                     substr (
                    di.index_name,
                    1,
                    3
                ) = 'PK_' THEN ', unique, primary key'
                WHEN di.uniqueness = 'UNIQUE' THEN ', unique'
            END
        ||
            CASE
                WHEN di.uniqueness = 'NONUNIQUE' THEN ''
                ELSE ''
            END
        ||
        ' located on PRIMARY' AS "INDEX_DESCRIPTION",
        ci.column_name AS "INDEX_KEYS",
        NULL AS "INCLUDE_COLS",
        NULL AS "INDEX_FILTER",
        NULL AS "DATA_COMPRESSION",
        NULL AS "ALLOW_PAGE_LOCKS",
        di.table_name AS "TABLE_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'CLUSTERED'
                ELSE 'NONCLUSTERED'
            END
        AS "INDEX_TYPE"
                      FROM
        dba_indexes di
        JOIN dba_ind_columns ci
        ON ci.index_owner   = di.owner AND
           ci.index_name    = di.index_name
                      WHERE
       -- di.table_owner = 'CON$' AND
        di.table_name = 'CON$' AND
        partitioned = 'NO'
    UNION ALL
    SELECT
        di.index_name AS "INDEX_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'clustered'
                ELSE 'nonclustered'
            END
        ||
            CASE
                WHEN di.uniqueness = 'UNIQUE' AND
                     substr (
                    di.index_name,
                    1,
                    3
                ) = 'PK_' THEN ', unique, primary key'
                WHEN di.uniqueness = 'UNIQUE' THEN ', unique'
            END
        ||
            CASE
                WHEN di.uniqueness = 'NONUNIQUE' THEN ''
                ELSE ''
            END
        ||
        ' located on PRIMARY' AS "INDEX_DESCRIPTION",
        ci.column_name AS "INDEX_KEYS",
        NULL AS "INCLUDE_COLS",
        NULL AS "INDEX_FILTER",
        NULL AS "DATA_COMPRESSION",
        NULL AS "ALLOW_PAGE_LOCKS",
        di.table_name AS "TABLE_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'CLUSTERED'
                ELSE 'NONCLUSTERED'
            END
        AS "INDEX_TYPE"
    FROM
        dba_indexes di
        JOIN dba_ind_partitions dip
        ON dip.index_owner   = di.owner AND
           dip.index_name    = di.index_name
        JOIN dba_ind_columns ci
        ON ci.index_owner   = di.owner AND
           ci.index_name    = di.index_name
    WHERE
        --di.table_owner = 'CON$' AND
       di.table_name = 'CON$' AND
        di.partitioned = 'YES' AND
        dip.composite != 'YES'
    UNION ALL
    SELECT
        di.index_name AS "INDEX_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'clustered'
                ELSE 'nonclustered'
            END
        ||
            CASE
                WHEN di.uniqueness = 'UNIQUE' AND
                     substr (
                    di.index_name,
                    1,
                    3
                ) = 'PK_' THEN ', unique, primary key'
                WHEN di.uniqueness = 'UNIQUE' THEN ', unique'
            END
        ||
            CASE
                WHEN di.uniqueness = 'NONUNIQUE' THEN ''
                ELSE ''
            END
        ||
        ' located on PRIMARY' AS "INDEX_DESCRIPTION",
        ci.column_name AS "INDEX_KEYS",
        NULL AS "INCLUDE_COLS",
        NULL AS "INDEX_FILTER",
        NULL AS "DATA_COMPRESSION",
        NULL AS "ALLOW_PAGE_LOCKS",
        di.table_name AS "TABLE_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'CLUSTERED'
                ELSE 'NONCLUSTERED'
            END
        AS "INDEX_TYPE"
    FROM
        dba_indexes di
        JOIN dba_ind_partitions dip
        ON dip.index_owner   = di.owner AND
           dip.index_name    = di.index_name
        JOIN dba_ind_subpartitions dis
        ON dis.index_owner      = di.owner AND
           dis.index_name       = di.index_name AND
           dis.partition_name   = dip.partition_name
        JOIN dba_ind_columns ci
        ON ci.index_owner   = di.owner AND
           ci.index_name    = di.index_name
    WHERE
      --  di.table_owner = 'CON$' AND
       di.table_name = 'CON$' AND
        di.partitioned = 'YES' AND
       dip.composite = 'YES' )       
       group BY index_name,index_description,INCLUDE_COLS,index_filter ,data_compression, allow_page_locks, table_name,index_type ;

END;

请注意,我已将table_name用作'CON$'。用您的table_name替换为我的名字table_name

编辑:

  

对使其也适用于10g版本有什么帮助吗?才知道   我们也可能需要它。

Oracle 10g 中,您可以执行以下操作:

CREATE OR REPLACE PROCEDURE test_1 (
    p_table_owner   IN VARCHAR2,
    p_table_name    IN VARCHAR2,
    p_result        OUT SYS_REFCURSOR
)
    AS
BEGIN
OPEN p_result FOR 
SELECT
    index_name,
    index_description,
    ltrim(sys_connect_by_path(index_keys,','),',') as Index_Keys,
    include_cols,
    index_filter,
    data_compression,
    allow_page_locks,
    table_name,
    index_type    
 from 
  (
  Select t.*,  
    row_number() over (partition by INDEX_NAME order by INDEX_NAME) as rn
    from 
    (
     SELECT      
        di.index_name AS "INDEX_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'clustered'
                ELSE 'nonclustered'
            END
        ||
            CASE
                WHEN di.uniqueness = 'UNIQUE' AND
                     substr (
                    di.index_name,
                    1,
                    3
                ) = 'PK_' THEN ', unique, primary key'
                WHEN di.uniqueness = 'UNIQUE' THEN ', unique'
            END
        ||
            CASE
                WHEN di.uniqueness = 'NONUNIQUE' THEN ''
                ELSE ''
            END
        ||
        ' located on PRIMARY' AS "INDEX_DESCRIPTION",
        ci.column_name AS "INDEX_KEYS",
        NULL AS "INCLUDE_COLS",
        NULL AS "INDEX_FILTER",
        NULL AS "DATA_COMPRESSION",
        NULL AS "ALLOW_PAGE_LOCKS",
        di.table_name AS "TABLE_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'CLUSTERED'
                ELSE 'NONCLUSTERED'
            END
        AS "INDEX_TYPE"
                      FROM
        dba_indexes di
        JOIN dba_ind_columns ci
        ON ci.index_owner   = di.owner AND
           ci.index_name    = di.index_name
                      WHERE
       -- di.table_owner = 'CON$' AND
        di.table_name = 'CON$' AND
        partitioned = 'NO'
    UNION ALL
    SELECT      
        di.index_name AS "INDEX_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'clustered'
                ELSE 'nonclustered'
            END
        ||
            CASE
                WHEN di.uniqueness = 'UNIQUE' AND
                     substr (
                    di.index_name,
                    1,
                    3
                ) = 'PK_' THEN ', unique, primary key'
                WHEN di.uniqueness = 'UNIQUE' THEN ', unique'
            END
        ||
            CASE
                WHEN di.uniqueness = 'NONUNIQUE' THEN ''
                ELSE ''
            END
        ||
        ' located on PRIMARY' AS "INDEX_DESCRIPTION",
        ci.column_name AS "INDEX_KEYS",
        NULL AS "INCLUDE_COLS",
        NULL AS "INDEX_FILTER",
        NULL AS "DATA_COMPRESSION",
        NULL AS "ALLOW_PAGE_LOCKS",
        di.table_name AS "TABLE_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'CLUSTERED'
                ELSE 'NONCLUSTERED'
            END
        AS "INDEX_TYPE"
    FROM
        dba_indexes di
        JOIN dba_ind_partitions dip
        ON dip.index_owner   = di.owner AND
           dip.index_name    = di.index_name
        JOIN dba_ind_columns ci
        ON ci.index_owner   = di.owner AND
           ci.index_name    = di.index_name
    WHERE
        --di.table_owner = 'CON$' AND
       di.table_name = 'CON$' AND
        di.partitioned = 'YES' AND
        dip.composite != 'YES'
    UNION ALL
    SELECT       
        di.index_name AS "INDEX_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'clustered'
                ELSE 'nonclustered'
            END
        ||
            CASE
                WHEN di.uniqueness = 'UNIQUE' AND
                     substr (
                    di.index_name,
                    1,
                    3
                ) = 'PK_' THEN ', unique, primary key'
                WHEN di.uniqueness = 'UNIQUE' THEN ', unique'
            END
        ||
            CASE
                WHEN di.uniqueness = 'NONUNIQUE' THEN ''
                ELSE ''
            END
        ||
        ' located on PRIMARY' AS "INDEX_DESCRIPTION",
        ci.column_name AS "INDEX_KEYS",
        NULL AS "INCLUDE_COLS",
        NULL AS "INDEX_FILTER",
        NULL AS "DATA_COMPRESSION",
        NULL AS "ALLOW_PAGE_LOCKS",
        di.table_name AS "TABLE_NAME",
        CASE
                WHEN di.index_type = 'IOT - TOP' THEN 'CLUSTERED'
                ELSE 'NONCLUSTERED'
            END
        AS "INDEX_TYPE"
    FROM
        dba_indexes di
        JOIN dba_ind_partitions dip
        ON dip.index_owner   = di.owner AND
           dip.index_name    = di.index_name
        JOIN dba_ind_subpartitions dis
        ON dis.index_owner      = di.owner AND
           dis.index_name       = di.index_name AND
           dis.partition_name   = dip.partition_name
        JOIN dba_ind_columns ci
        ON ci.index_owner   = di.owner AND
           ci.index_name    = di.index_name
    WHERE
      --  di.table_owner = 'CON$' AND
       di.table_name = 'CON$' AND
        di.partitioned = 'YES' AND
       dip.composite = 'YES' ) t      
)
where connect_by_isleaf = 1
connect by index_name  = prior index_name
and rn = prior rn+1
start with rn =1 ;

End;

答案 1 :(得分:1)

使用LISTAGGGROUP BY

Oracle设置

CREATE TABLE table_name (
  id     NUMBER CONSTRAINT PK_TABLE_NAME__ID PRIMARY KEY,
  value  NUMBER,
  other1 NUMBER,
  other2 NUMBER,
  CONSTRAINT U_TABLE_NAME__OTHER1_OTHER2 UNIQUE ( other1, other2 )
);

查询

(注1:dbfiddle不允许访问dba_*表,因此下面的查询使用user_*表,而没有注释掉适用于dba_版本的部分。)< / i>

(注2:在您不同的UNION ed查询的输出之间似乎没有功能上的区别,因此我删除了di.partitioned上的过滤器。如果存在非显而易见的则可以将它们放回去并在外部查询中执行LISTAGG分组。)

select di.index_name as "INDEX_NAME",
       CASE WHEN di.index_type='IOT - TOP' THEN 'clustered' ELSE 'nonclustered' END
       ||
       CASE WHEN di.uniqueness = 'UNIQUE' THEN ', unique' END
       ||
       CASE WHEN cons.constraint_type = 'P' THEN ', primary key' END
       ||
       ' located on PRIMARY' AS "INDEX_DESCRIPTION",
       LISTAGG( ci.column_name, ',' ) WITHIN GROUP ( ORDER BY ci.COLUMN_POSITION ) as "INDEX_KEYS",
       null as "INCLUDE_COLS",
       null as "INDEX_FILTER",
       null as "DATA_COMPRESSION",
       null as "ALLOW_PAGE_LOCKS",
       di.table_name as "TABLE_NAME",                    
       case
       when di.index_type='IOT - TOP'
       then 'CLUSTERED'
       else 'NONCLUSTERED'
       end AS "INDEX_TYPE"
from   /*dba*/user_indexes di
       INNER JOIN /*dba*/user_constraints cons
       ON (    cons.owner = di.table_owner
           AND cons.table_name = di.table_name
           -- AND cons.index_owner = di.owner
           AND cons.index_name = di.index_name 
       )
       join /*dba*/user_ind_columns ci
       on ci.index_name = di.index_name
where  di.table_name = 'TABLE_NAME'
--and    di.table_owner = 'OWNER'
GROUP BY di.table_name, di.index_name, cons.constraint_type, di.uniqueness, di.index_type 

输出

INDEX_NAME                  | INDEX_DESCRIPTION                                    | INDEX_KEYS    | INCLUDE_COLS | INDEX_FILTER | DATA_COMPRESSION | ALLOW_PAGE_LOCKS | TABLE_NAME | INDEX_TYPE  
:-------------------------- | :--------------------------------------------------- | :------------ | :----------- | :----------- | :--------------- | :--------------- | :--------- | :-----------
PK_TABLE_NAME__ID           | nonclustered, unique, primary key located on PRIMARY | ID            | null         | null         | null             | null             | TABLE_NAME | NONCLUSTERED
U_TABLE_NAME__OTHER1_OTHER2 | nonclustered, unique located on PRIMARY              | OTHER1,OTHER2 | null         | null         | null             | null             | TABLE_NAME | NONCLUSTERED

db <>提琴here