简体   繁体   English

为 Oracle function 定义一个 CLOB 输入参数(或使用 CLOB 输入参数定义一个 function)

[英]Define a CLOB input parameter for Oracle function (OR Define a function with CLOB input parameter)

I am going to run a code block like below:我将运行如下代码块:

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

In which its purpose is to create a function that one of its input argument is CLOB data type.其中其目的是创建一个 function,其输入参数之一是 CLOB 数据类型。 But by executing my code, I get following error:但是通过执行我的代码,我得到以下错误:

ORA-01704: string literal too long ORA-01704: 字符串文字太长

I searched on the internet and also among stackoverflow questions but it didn't get any consequence.我在互联网上以及在 stackoverflow 问题中进行了搜索,但没有得到任何结果。

Could you anyone help me with this issue?你能帮我解决这个问题吗?

I believe I understand what you are trying to achieve.我相信我理解你想要达到的目标。 As per comments your use of IN is wrong.根据评论,您对IN的使用是错误的。 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. IN需要来自 select 的文字列表或值列表,但您的 CLOB 值两者都不是,它只是一个需要先处理的长字符串,然后才能在SELECT中使用它,就像您在评论中提到的那样。

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).要使用以 分隔的名称列表处理您的 CLOB ,您可以在 CLOB 中找到第一个逗号并从 CLOB 的开头提取值,直到第一个分隔符和找到的值被放入集合中(分隔符被删除 ofc 并且值被修剪,这可能是可选,因为我不确定您的输入看起来如何)。 Next you remove found value from the beginning of the CLOB and repeat until there are nothing to process in this CLOB.接下来,您从 CLOB 的开头删除找到的值并重复,直到在此 CLOB 中没有要处理的内容。 Once you have list of values in collection you can use it as SELECT in your original SELECT .一旦您拥有集合中的值列表,您就可以在原始SELECT 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;
/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM