I believe I understand what you are trying to achieve. As per comments your use of IN
is wrong. IN
expects list of literals or list of values from select, but your CLOB value is neither, it is just a long string that needs to be processed first before you can use it in SELECT
like you mentioned in comments.
To process your CLOB with list of names delimited with ,
you can find first comma in CLOB and extract value from the beginning of CLOB until this first delimiter and found value is put into collection (delimiter is removed ofc and value is trimmed, this might be optional as I am not sure how your input looks like exactly). Next you remove found value from the beginning of the CLOB and repeat until there are nothing to process in this CLOB. Once you have list of values in collection you can use it as SELECT
in your original SELECT
.
Try this example:
CREATE TABLE table_name (
name_desc VARCHAR2(250) NOT NULL
);
INSERT INTO table_name (name_desc)
VALUES ('Lorem');
INSERT INTO table_name (name_desc)
VALUES ('ipsum');
INSERT INTO table_name (name_desc)
VALUES ('test');
COMMIT;
CREATE OR REPLACE TYPE name_list_tabt IS TABLE OF VARCHAR2(4000);
/
CREATE OR REPLACE PROCEDURE func_name(p_start_date NUMBER,
p_end_date NUMBER,
p_name CLOB) IS
v_delimiter VARCHAR2(1) := ',';
v_name CLOB := p_name;
v_delimiter_pos NUMBER;
v_name_value VARCHAR2(4000);
v_name_list name_list_tabt := name_list_tabt();
BEGIN
-- OTHER CODE ABOVE ...
LOOP
-- Get position of delimiter
v_delimiter_pos := dbms_lob.instr(v_name, v_delimiter, 1, 1);
-- If no comma is found we get rest of the CLOB for last name, if there is no more CLOB to process this will return 0
IF v_delimiter_pos = 0
THEN
v_delimiter_pos := dbms_lob.getlength(v_name);
END IF;
-- Get next name based on delimiter position, can cause error if single name is over 4000 bytes long
v_name_value := dbms_lob.substr(v_name, v_delimiter_pos, 1);
-- Next code will remove found name from CLOB start
v_name := regexp_replace(v_name, v_name_value, NULL, 1, 1);
-- If we reached the end of CLOB, exit
IF v_delimiter_pos = 0
THEN
EXIT;
END IF;
-- Add new name to collection if it is not empty
IF TRIM(REPLACE(v_name_value, v_delimiter)) IS NOT NULL
THEN
v_name_list.extend();
v_name_list(v_name_list.count) := TRIM(REPLACE(v_name_value, v_delimiter));
END IF;
END LOOP;
-- Your select in for loop just to make this code working, adjust as you need
FOR i IN (SELECT *
FROM table_name
WHERE name_desc IN (SELECT /*+ dynamic_sampling(t 2) */
column_value
FROM TABLE(v_name_list) t))
LOOP
dbms_output.put_line(i.name_desc); -- Just some test output
END LOOP;
-- OTHER CODE BELOW ...
END;
/
BEGIN
-- Example with different, even possibly incorrect values
func_name(p_start_date => 1,
p_end_date => 2,
p_name => 'Lorem,ipsum,dolor,sit,amet,consectetur,
,,adipiscing,elit,Etiam,interdum,ligula, , ,');
-- Based on table values and CLOB here output should be "Lorem" and "ipsum"
END;
/