Мне кажется, я понимаю, чего вы пытаетесь достичь. Согласно комментариям, вы неправильно используете IN
. IN
ожидает список литералов или список значений от select, но ваше значение CLOB не является ни тем, ни другим, это просто длинная строка, которую необходимо обработать, прежде чем вы сможете использовать ее в SELECT
, как вы упомянули в комментариях.
Для обработки вашего CLOB со списком имен, разделенных ,
, вы можете найти первую запятую в CLOB и извлечь значение из начала CLOB, пока этот первый разделитель и найденное значение не будут помещены в коллекцию (разделитель удаляется из c и значение обрезано, это может быть необязательным, поскольку я не уверен, как именно выглядит ваш ввод). Затем вы удаляете найденное значение из начала CLOB и повторяете, пока в этом CLOB не останется ничего для обработки. Если у вас есть список значений в коллекции, вы можете использовать его как SELECT
в исходном SELECT
.
Попробуйте этот пример:
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;
/