Разделенный запятыми вывод столбца в один spsc plsql - PullRequest
0 голосов
/ 19 февраля 2019

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 голосов
/ 19 февраля 2019

Использование LISTAGG и GROUP 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_.)

(Примечание 2: theredid, по-видимому, не является функциональной разницей между выводом вашего другого 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            | <em>null</em>         | <em>null</em>         | <em>null</em>             | <em>null</em>             | TABLE_NAME | NONCLUSTERED
U_TABLE_NAME__OTHER1_OTHER2 | nonclustered, unique located on PRIMARY              | OTHER1,OTHER2 | <em>null</em>         | <em>null</em>         | <em>null</em>             | <em>null</em>             | TABLE_NAME | NONCLUSTERED

db <> fiddle здесь

0 голосов
/ 19 февраля 2019

Но я бы хотел, чтобы он возвращал только одну строку на индекс. В случае нескольких столбцов столбец 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...