从事数据库工作多年,目前看好分布式NeSQL/HTAP数据库在企业客户市场的发展。未来的主要方向是——致力于 NewSQL/HTAP 数据库的推广普及。
分类: Sybase
2014-03-13 17:07:36
最近遇到一个问题,用户的开发人员编写的一个存储过程中执行LOAD TABLE语句失败,但是在存储过程中不能获得语句执行的状态信息。经过尝试,找到了问题原因和解决方法,在这里与大家分享。由于涉及用户保密的原因,本文用到测试表、存储过程进行了修改,但能够说明问题!
一、问题再现
-- 1. 创建测试表 (crt_table.sql)
create table test11 (
id int not null ,
age tinyint null ,
name char (8) null ,
primary key (id)
)
--2. 准备数据文件/tmp/test11.dat
1|!aaaaaaaa|!
2|!bbbbbbbb|!
3|!cccccccc|!
--3. 创建存储过程 (crt_proc.sql)
CREATE PROCEDURE proc1()
BEGIN
declare @sqlcode int;
message 'load table test11' type info to client ;
LOAD TABLE test11
(
id '|!' ,
name '|!'
)
FROM '/tmp/test11.dat'
FORMAT ASCII
STRIP ON
ESCAPES OFF
QUOTES OFF
NOTIFY 500000
ROW DELIMITED BY '\x0a'
WITH CHECKPOINT ON;
SELECT sqlcode INTO @sqlcode;
IF @sqlcode <> 0 THEN
message 'load table sqlcode = ', @sqlcode, '; error msg = ', errormsg(@sqlcode) type info to client;
END IF;
END; --proc1 end
--4. 使用dbisql执行crt_table.sql和crt_proc.sql脚本,创建测试表和测试存储过程。并把test11.dat文件放入/tmp目录。
--5. 使用dbisql或isql 连接到IQ Server,执行存储过程proc1.
(1) 在第一次执行的时候成功,下面是我环境下的输出:
> dbisql -c "uid=DBA;pwd=sql" -nogui -onerror continue
(DBA)> proc1
load table test11
1 row(s) affected
Execution time: 0.081 seconds
(2) 在执行第二次的时候报错(因为有重复记录了),proc1存储过程中load语句之后的 IF 语句没有执行。
> dbisql -c "uid=DBA;pwd=sql" -nogui -onerror continue
(DBA)> proc1
load table test11
Could not execute statement.
Tried to insert a duplicate value into a unique index
DBA.test11.ASIQ_IDX_T754_I4_HG on row 4.
-- (s_ohcins.cxx 722)
SQLCODE=-1002003, ODBC 3 State="HY000"
Line 1, column 1
proc1
(Continuing after error)
二、解决方法
解决方法 1: 在存储过程外部判断sqlcode
在这种情况下,当存储过程中的某个SQL语句执行出错时,IQ会终止存储过程的执行,不会再执行出错语句后面的存储过程代码。解决它的办法之一是在调用存储过程之后,在存储过程外部判断sqlcode。例如, 在调用proc1之后,立即执行
select sqlcode,@@error, errormsg(sqlcode) ,这样是可以获得错误代码和错误消息的:
(DBA)> select sqlcode,@@error, errormsg(sqlcode)
sqlcode @@error errormsg(sqlcode)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-1002003 -6 Tried to insert a duplicate value into a unique index ??? on row ???. ???
解决方法 2: 修改存储过程定义,增加 on exception resume 字句。
下面是修改后的存储过程代码:
CREATE PROCEDURE proc1 ()
ON EXCEPTION RESUME
BEGIN
declare @sqlcode int;
message 'load table test11' type info to client ;
LOAD TABLE test11
(
id '|!' ,
name '|!'
)
FROM '/tmp/test11.dat'
FORMAT ASCII
STRIP ON
ESCAPES OFF
QUOTES OFF
NOTIFY 500000
ROW DELIMITED BY '\x0a'
WITH CHECKPOINT ON;
SELECT sqlcode INTO @sqlcode;
IF @sqlcode <> 0 THEN
message 'load table sqlcode = ', @sqlcode, '; error msg = ', errormsg(@sqlcode) type info to client;
END IF;
END;
执行修改后的存储过程,输出如下:
> dbisql -c "uid=DBA;pwd=sql" -nogui -onerror continue
(DBA)> proc1
load table test11
load table sqlcode = -1002003; error msg = Tried to insert a duplicate value into a unique index ??? on row ???. ???
1 row(s) affected
Execution time: 0.016 seconds
这次执行,存储过程proc1内部的IF语句被执行了!