Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1634323
  • 博文数量: 201
  • 博客积分: 2812
  • 博客等级: 少校
  • 技术积分: 3029
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-18 18:28
个人简介

从事数据库工作多年,目前看好分布式NeSQL/HTAP数据库在企业客户市场的发展。未来的主要方向是——致力于 NewSQL/HTAP 数据库的推广普及。

文章存档

2016年(1)

2015年(8)

2014年(23)

2013年(50)

2012年(32)

2011年(87)

分类: 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语句被执行了!

阅读(5066) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~