Turning rows into columns
22/04/2022 1 Comment
It’s odd how some things pass you by in new Oracle releases. Today I discovered “sys.odcinumberlist” and “sys.odcivarchar2list“.
I was wanting to generate a pre-defined list for a join to ensure each value was represented, and came up with the new in Oracle 12 function “sys.odcinumberlist”, so not new! Well, there’s 2 straightforward functions: “sys.odcinumberlist” and “sys.odcivarchar2list”.
How are they used?
SELECT column_value AS number_list
FROM sys.odcinumberlist(1,2,5,7,9,5,2,-34,5,43,2,0)
ORDER BY number_list;
NUMBER_LIST
-----------
-34
0
1
2
2
2
5
5
5
7
9
43
12 rows selected.
Note how I have had to alias the "column value" virtual column to allow mne to sort the list
SELECT column_value AS char_list FROM sys.odcivarchar2list('A','V','DD');
CHAR_LIST
---------
A
V
DD
Nice, simple, with a limit of 32768 items in the list. So how was I using it? I was checking to see which profiles existed in a database (the list was somewhat longer than this, as was the SQL, but this is good for a demo) so I generated my full list of known profiles to join to the existing profiles in each database.
WITH my_profiles AS (
SELECT
column_value AS profile_name
FROM
sys.odcivarchar2list(
'DEFAULT'
, 'SOME_OTHER_PROFILE' --etc etc etc
)
)
SELECT
mp.profile_name
, nvl( profile , '<does-not-exist>') AS profile
, resource_name
, limit
FROM
my_profiles mp
LEFT OUTER JOIN dba_profiles dp ON ( mp.profile_name = dp.profile )
ORDER BY
profile
, resource_name;
PROFILE_NAME PROFILE RESOURCE_NAME LIMIT
-------------------- -------------------- ------------------------------ -----------
SOME_OTHER_PROFILE <does-not-exist>
DEFAULT DEFAULT COMPOSITE_LIMIT UNLIMITED
DEFAULT DEFAULT CONNECT_TIME UNLIMITED
DEFAULT DEFAULT CPU_PER_CALL UNLIMITED
DEFAULT DEFAULT CPU_PER_SESSION UNLIMITED
DEFAULT DEFAULT FAILED_LOGIN_ATTEMPTS 10
DEFAULT DEFAULT IDLE_TIME UNLIMITED
DEFAULT DEFAULT INACTIVE_ACCOUNT_TIME UNLIMITED
DEFAULT DEFAULT LOGICAL_READS_PER_CALL UNLIMITED
DEFAULT DEFAULT LOGICAL_READS_PER_SESSION UNLIMITED
DEFAULT DEFAULT PASSWORD_GRACE_TIME 7
DEFAULT DEFAULT PASSWORD_LIFE_TIME 180
DEFAULT DEFAULT PASSWORD_LOCK_TIME 1
DEFAULT DEFAULT PASSWORD_REUSE_MAX UNLIMITED
DEFAULT DEFAULT PASSWORD_REUSE_TIME UNLIMITED
DEFAULT DEFAULT PASSWORD_ROLLOVER_TIME -1
DEFAULT DEFAULT PASSWORD_VERIFY_FUNCTION NULL
DEFAULT DEFAULT PRIVATE_SGA UNLIMITED
DEFAULT DEFAULT SESSIONS_PER_USER UNLIMITED
There’s a number of other ways to do this, including using the UNPIVOT function, creating your own table type, etc, but this was the nice and simple option I was looking for.