sql—为oracle函数定义clob输入参数(或使用clob输入参数定义函数)

5ssjco0h  于 2021-08-13  发布在  Java
关注(0)|答案(1)|浏览(528)

我将运行如下代码块:

CREATE OR REPLACE FUNCTION func_name (START_DATE NUMBER,END_DATE NUMBER, NAME clob)
                     .
                     .
                     .
        select * from table_name
        where name_desc in NAME
                     .
                     .
                     .
 END;

其中,它的目的是创建一个其输入参数之一为clob数据类型的函数。但通过执行我的代码,我得到以下错误:
ora-01704:字符串文字太长
我在网上搜索了一下,也搜索了一些问题,但没有得到任何结果。
你能帮我解决这个问题吗?

pcrecxhr

pcrecxhr1#

我相信我理解你想要达到的目标。根据你的意见 IN 这是错误的。 IN 需要select中的文本列表或值列表,但clob值两者都不是,它只是一个长字符串,需要先处理它才能在中使用 SELECT 就像你在评论中提到的。
使用以分隔的名称列表处理clob , 您可以在clob中找到第一个逗号,并从clob的开头提取值,直到将第一个分隔符和找到的值放入集合(分隔符从C中删除,值被修剪,这可能是可选的,因为我不确定您的输入到底是什么样的)。接下来,从clob的开始处删除find值,并重复此操作,直到此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;
/

相关问题