我创建了一个Oracle表函数,它可以在表中删除和插入传递的值。
是的,我知道函数不应该这样做,我必须使用存储过程,但不幸的是,我不能在另一个工具中使用存储过程,所以我误用了这个函数,并添加了PRAGMA,这样这个函数就可以在函数体中使用COMMIT
了。这个函数可以按照我想要的方式工作,但是字符串文字大于4000个字符时有一个问题。我认为CLOB
和DBMS_CLOB
函数可以处理大字符串,但我仍然得到错误
ORA-01704:字符串文字太长
01704. 00000 -“字符串文字太长”
- 原因:字符串文字长度超过4000个字符。
- 操作:使用最多4000个字符的字符串文字。
较长的值只能使用绑定变量输入。
这是因为我传递的字符串非常大,超过了4000个字符,输入参数p_val
定义为CLOB
并不重要,传递字符串时4000个字符总是限制?
create or replace FUNCTION table_fn_test (p_val CLOB, p_action VARCHAR2, p_random NUMBER, p_user VARCHAR2)
RETURN my_t_tf_tab PIPELINED
IS
PRAGMA AUTONOMOUS_TRANSACTION;
v_count NUMBER :=0;
v_dup NUMBER :=0;
v_info VARCHAR2(50) :='';
v_val CLOB;
v_index NUMBER := 1;
BEGIN
IF p_val IS NOT NULL THEN
v_val := p_val || ',';
WHILE DBMS_LOB.INSTR(v_val, ',', v_index) > 0
LOOP
IF p_action = 'insert' THEN
SELECT COUNT(*) INTO v_dup FROM my_table WHERE COL2 = TRIM(DBMS_LOB.SUBSTR(v_val,DBMS_LOB.INSTR(v_val,'#',v_index)-v_index,v_index)) AND COL1 = RPAD(' ' || TRIM(DBMS_LOB.SUBSTR( v_val,DBMS_LOB.INSTR(v_val,',',v_index)-DBMS_LOB.INSTR(v_val,'#',v_index)-1,DBMS_LOB.INSTR(v_val,'#',v_index)+1)),15,' ');
IF v_dup = 0 THEN
INSERT INTO my_table(COL2,COL1) VALUES (TRIM(DBMS_LOB.SUBSTR(v_val,DBMS_LOB.INSTR(v_val,'#',v_index)-v_index,v_index)), RPAD(' ' || TRIM(DBMS_LOB.SUBSTR( v_val,DBMS_LOB.INSTR(v_val,',',v_index)-DBMS_LOB.INSTR(v_val,'#',v_index)-1,DBMS_LOB.INSTR(v_val,'#',v_index)+1)),15,' '));
v_count := v_count + SQL%ROWCOUNT;
v_info := v_count || ' row(s) inserted';
END IF;
ELSIF p_action = 'delete' THEN
DELETE FROM my_table WHERE COL2 = TRIM(DBMS_LOB.SUBSTR(v_val,DBMS_LOB.INSTR(v_val,'#',v_index)-v_index,v_index)) AND COL1 = RPAD(' ' || TRIM(DBMS_LOB.SUBSTR( v_val,DBMS_LOB.INSTR(v_val,',',v_index)-DBMS_LOB.INSTR(v_val,'#',v_index)-1,DBMS_LOB.INSTR(v_val,'#',v_index)+1)),15,' ');
v_count := v_count + SQL%ROWCOUNT;
v_info := v_count || ' row(s) deleted';
END IF;
v_index := DBMS_LOB.INSTR(v_val, ',', v_index) + 1;
END LOOP;
COMMIT;
END IF;
FOR rec IN (SELECT COL1, COL2 from my_table )
LOOP
PIPE ROW(my_t_tf_tab(rec.COL2, rec.COL1 ));
END LOOP;
END table_fn_test;
1条答案
按热度按时间xdyibdwo1#
当传递文字时,4000个字符始终是限制?
是的,除非你的数据库配置了更大的32 k限制(从技术上讲,它是字节,而不是字符,这可能是这里的问题)。
问题出在你的调用上,而不是函数本身。你需要构造一个CLOB来传入--如何传递取决于你在哪里/如何调用它。
在SQL中,你可以将几个较短的字符串连接在一起:
如果你有一个很大的字符串作为开始,这显然有点痛苦,因为你必须在复制和粘贴它时将其分解。如果值在文件中或从应用程序传递,那么你应该尽早读取并将其视为CLOB,所以它永远不会受到这个限制。