It could be done in an old way with one user defined function spliting a string by delimiter and returning an array of elements. In that case the simple plsql fuction could be like here:
create or replace Function Get_Least(P_LIST VARCHAR2, P_DELIMITER VARCHAR2 := ',') Return NUMBER AS
BEGIN
Declare
elements STRING_ARRAY := STRING_ARRAY();
least_element Number(12) := 999999999999;
Begin
elements := split(P_LIST , P_DELIMITER);
For i In 1..elements.count Loop
If To_Number(elements(i)) < least_element Then
least_element := To_Number(elements(i));
End If;
End Loop;
RETURN least_element;
End;
END get_Least;
Here are the user defined type STRING_ARRAY and SPLIT() function:
create or replace TYPE STRING_ARRAY AS
VARRAY(4000) OF VARCHAR2(1000);
/
create or replace FUNCTION split ( csvString IN VarChar2, delimiter IN VarChar2 := ',')
RETURN STRING_ARRAY AS
BEGIN
Declare
elements STRING_ARRAY := STRING_ARRAY();
CURSOR c IS
SELECT COL1
FROM ( SELECT INDX, MY_STR1, COL1_ELEMENTS, COL1
FROM ( SELECT 0 "INDX", COL1 "MY_STR1", COL1_ELEMENTS, COL1
FROM(
SELECT
REPLACE(COL1, delimiter || ' ', delimiter) "COL1",
Trim(Length(Replace(COL1, delimiter || ' ', delimiter))) - Trim(Length(Translate(REPLACE(COL1, delimiter || ' ', delimiter), 'A' || delimiter, 'A'))) + 1 "COL1_ELEMENTS"
FROM (SELECT csvString "COL1" FROM DUAL)
)
)
MODEL
DIMENSION BY(0 as INDX)
MEASURES(COL1, COL1_ELEMENTS, CAST('a' as VarChar2(4000)) as MY_STR1)
RULES ITERATE (1000) --UNTIL (ITERATION_NUMBER <= COL1_ELEMENTS[ITERATION_NUMBER + 1]) -- If you don't know the number of elements this should be bigger then you aproximation. Othewrwise it will split given number of elements
(
COL1_ELEMENTS[ITERATION_NUMBER + 1] = COL1_ELEMENTS[0],
MY_STR1[0] = COL1[CV()],
MY_STR1[ITERATION_NUMBER + 1] = SubStr(MY_STR1[ITERATION_NUMBER], InStr(MY_STR1[ITERATION_NUMBER], delimiter, 1) + Length(delimiter)),
COL1[ITERATION_NUMBER + 1] = SubStr(MY_STR1[ITERATION_NUMBER], 1, CASE WHEN InStr(MY_STR1[ITERATION_NUMBER], delimiter) <> 0 THEN InStr(MY_STR1[ITERATION_NUMBER], delimiter)-1 ELSE Length(MY_STR1[ITERATION_NUMBER]) END)
)
)
WHERE INDX > 0 And INDX <= COL1_ELEMENTS; -- And COL1 Is Not Null;
cStr VarChar2(1000);
i Number := 1;
Begin
If c%ISOPEN Then CLOSE c; End If;
OPEN c;
LOOP
FETCH c Into cStr;
EXIT WHEN c%NOTFOUND;
elements.extend;
elements(i) := cStr;
i := i + 1;
END LOOP;
CLOSE c;
RETURN elements;
End;
END split;
/
Test call with string containing comma separated list of numbers
SET SERVEROUTPUT ON
Declare
least_one NUMBER(3);
Numbers_List VARCHAR2(100) := '123, 46, 756, 3, 918, 4';
Begin
least_one := GET_LEAST(Numbers_List);
DBMS_OUTPUT.PUT_LINE(least_one);
End;
--
-- Result:
--
-- anonymous block completed
-- 3
SPLIT() function could split any string by any delimiter (including space character for splitting words in a sentence). It works with db versions without regexp too.
Example: - the same numbers separated by 'xo' - same result
SET SERVEROUTPUT ON
Declare
least_one NUMBER(3);
Numbers_List VARCHAR2(100) := '123xo46xo756xo3xo918xo4';
Begin
least_one := GET_LEAST(Numbers_List, 'xo');
DBMS_OUTPUT.PUT_LINE(least_one);
End;
--
-- Result:
--
-- anonymous block completed
-- 3
Regards...