帮客户将数据库从11.2.0.1升级到11.2.0.3后,数据库运行正常,不过随后出现了ORA-30004错误。
这个错误以前还真没有碰到过,检查后发现感觉问题似乎不一定和升级有关系:
ORA-30004: WHEN USING SYS_CONNECT_BY_PATH FUNCTION, cannot have separator AS part OF COLUMN VALUE Cause: A COLUMN VALUE contained the string that the SYS_CONNECT_BY_PATH FUNCTION was TO USE TO separate COLUMN VALUES. Action: Specify another separator FOR the SYS_CONNECT_BY_PATH FUNCTION TO USE which does NOT occur IN any COLUMN VALUE, THEN retry. |
从错误信息看,是SYS_CONNECT_BY_PATH函数导致的错误。而客户出现错误的语句也确实包含SYS_CONNECT_BY_PATH函数。导致错误的原因是SYS_CONNECT_BY_PATH处理的列中包含了分隔列。
为了确认这一点,特别在11.2.0.1环境中再现这个问题:
SQL> SELECT * FROM v$version; BANNER -------------------------------------------------------------------------------- Oracle DATABASE 11g Enterprise Edition Release 11.2.0.1.0 - Production PL/SQL Release 11.2.0.1.0 - Production CORE 11.2.0.1.0 Production TNS FOR 32-bit Windows: Version 11.2.0.1.0 - Production NLSRTL Version 11.2.0.1.0 - Production SQL> CREATE USER u1 IDENTIFIED BY u1 DEFAULT tablespace users; 用户已创建。 SQL> GRANT CONNECT, resource TO u1; 授权成功。 SQL> conn u1/u1 已连接。 SQL> CREATE TABLE t_conn (id NUMBER, fid NUMBER, name varchar2(30)); 表已创建。 SQL> INSERT INTO t_conn VALUES (1, 0, 'a'); 已创建 1 行。 SQL> INSERT INTO t_conn VALUES (2, 1, 'b'); 已创建 1 行。 SQL> INSERT INTO t_conn VALUES (3, 2, 'c'); 已创建 1 行。 SQL> SELECT sys_connect_by_path(name, ',') FROM t_conn START WITH id = 1 CONNECT BY prior id = fid; SYS_CONNECT_BY_PATH(NAME,',') -------------------------------------------------------------------------------- ,a ,a,b ,a,b,c SQL> UPDATE t_conn SET name = 'b,' WHERE id = 2; 已更新 1 行。 SQL> commit; 提交完成。 SQL> SELECT sys_connect_by_path(name, ',') FROM t_conn START WITH id = 1 CONNECT BY prior id = fid; ERROR: ORA-30004: 使用 SYS_CONNECT_BY_PATH 函数时, 不能将分隔符作为列值的一部分 未选定行 |
显然确认了问题只是由于数据错误所致,而与升级没有任何关系。
根据客户错误的SQL语句,定位了表中的错误数据。将包含分隔符的数据更新后,问题消失。