sql 善后处理的一些代码

 

sqlca\ oraca\指示器变量,保存了 sql 执行场景,为错误诊断和善后处理提供了方便。

sqlca 与 oraca 比较

1、

1、sqlca 程序级的,oraca 是数据库级的。一个程序有多个连接,则只有一个 sqlca,却可以有多个 oraca.

2、oraca 提供了比 sqlca 更丰富的诊断信息。(runtime errors and status changes )

3、oraca 会带来显著的性能下降。

Oracle Communications Area (ORACA)

结构:

oraca 结构描述 定义于 oraca.h 中 
struct     oraca
{
    
char  oracaid[ 8 ];    /*  Reserved                */
    
long  oracabc;       /*  Reserved                */
 
/*     Flags which are setable by User.  */
 
   
long   oracchf;       /*  <> 0 if "check cur cache consistncy" */
   
long   oradbgf;       /*  <> 0 if "do DEBUG mode checking"     */
   
long   orahchf;       /*  <> 0 if "do Heap consistency check"  */
   
long   orastxtf;      /*  SQL stmt text flag             */
#define   ORASTFNON 0   /* = don't save text of SQL stmt       */
#define   ORASTFERR 1   /* = only save on SQLERROR         */
#define   ORASTFWRN 2   /* = only save on SQLWARNING/SQLERROR  */
#define   ORASTFANY 3      /* = always save             */
    
struct
      {
  unsigned 
short  orastxtl;
  
char   orastxtc[ 70 ];
      } orastxt;         
/*  text of last SQL stmt           */
    
struct
      {
  unsigned 
short  orasfnml;
  
char       orasfnmc[ 70 ];
      } orasfnm;        
/*  name of file containing SQL stmt     */
  
long    oraslnr;         /*  line nr-within-file of SQL stmt      */
  
long    orahoc;          /*  highest max open OraCurs requested   */
  
long    oramoc;          /*  max open OraCursors required          */
  
long    oracoc;          /*  current OraCursors open          */
  
long    oranor;          /*  nr of OraCursor re-assignments       */
  
long    oranpr;          /*  nr of parses                */
  
long    oranex;          /*  nr of executes             */
};

 

 重要的成员:

  struct orasfnm;        /* name of file containing SQL stmt    */
  long   oraslnr;        /* line nr-within-file of SQL stmt     */

使用:

EXEC SQL INCLUDE ORACA;

EXEC ORACLE OPTION (ORACA=YES);

sqlca 可以用来识别 sql语句的执行结果,及详细的错误描述。

ExpandedBlockStart.gif sqlca结构描述,定义于 sqlca.h 中  
struc sqlca
{
unsigned 
char      sqlcaid[ 8 ];
long               sqlabc;
long               sqlcode;
short              sqlerrml;
unsigned 
char      sqlerrmc[ 10 ];
unsigned 
char      sqlerrp[ 8 ];
long               sqlerrd[ 6 ];
unsigned 
char      sqlwarn[ 21 ];
unsigned 
char      sqlstate[ 5 ];
}

 

sqlcaid:标识性域,包含字符串“sqlca”.
Sqlabc:包含sqlca结构的长度。
Sqlerrml:包含sqlerrmc域中数据的实际长度。
Sqlerrmc: 由0或多个字串组成,它对返回的值给以一个更详细的解释。如返回的代码表示表没找到,则此域中包含未找到的表名。
Sqlerrp: 包含一些对用户无用的论断信息。
Sqlstate: 长度为5的字符串,它指示SQL语句的查询结果。与sqlca不同的是,它遵循ANSI/ISOSQL92的标准,所以,尽管不同数据库产品的sqlca结构中sqlcode域的含义不同,但sqlstate域的含义是相同的。

重要的字段:

sqlerrd[4] This component holds an offset that specifies the character position at which a parse error begins in the most recently executed SQL statement. The first character occupies position zero.

当 sql  语句发生解析错误时,这个字段保存了 sql 语句发生错误的偏移。

SQLStmtGetText() 是 odbc 中用来获取最近执行的 sql 语句的函数。


sqlgls() 是嵌入式sql 中 用来获取最近执行的 sql 语句的函数。(#include <sqlcpr.h> ) 好像不总是有用?
可以用 SQLStmtGetText()  和 sqlgls() 获得 sql 操作的类型 ( function_type )。在一些数据库框架中,sql 是用户配置实现的,框架需要根据sql操作类型作为相应的分配 数据交换缓存 的决策,但不知道sql 操作类型。所以上面识别sql 操作类型的机制尤其有用。

ExpandedBlockStart.gif 代码
/*
 *  The sqlvcp.pc program demonstrates how you can use the
 *  sqlvcp() function to determine the actual size of a
 *  VARCHAR struct. The size is then used as an offset to
 *  increment a pointer that steps through an array of
 *  VARCHARs.
 *
 *  This program also demonstrates the use of the sqlgls()
 *  function, to get the text of the last SQL statement executed.
 *  sqlgls() is described in the "Error Handling" chapter of
 *  The Programmer's Guide to the Oracle Pro*C/C++ Precompiler.
 
*/

#include 
< stdio.h >  
#include 
< sqlca.h >
#include 
< sqlcpr.h >

/*   Fake a VARCHAR pointer type.  */  

struct my_vc_ptr 

    unsigned short 
len
    unsigned 
char  arr [ 32767 ]
}; 

/*  Define a type for the VARCHAR pointer  */
typedef struct my_vc_ptr my_vc_ptr; 
my_vc_ptr 
* vc_ptr; 


EXEC  SQL  BEGIN   DECLARE  SECTION; 
VARCHAR   * names;  
int       limit;     /*  for use in FETCH FOR clause   */  
char      * username  =  "scott / tiger"; 
EXEC  SQL  END   DECLARE  SECTION; 
void sql_error(); 
extern void sqlvcp(), sqlgls(); 

main() 

    unsigned 
int  vcplen, function_code, padlen, buflen; 
    
int  i; 
    
char  stmt_buf [ 120 ]

    
EXEC  SQL WHENEVER SQLERROR DO sql_error(); 

    
EXEC  SQL CONNECT :username; 
    printf("\nConnected.\n"); 
     
/*   Find number of rows in table.  */  
    
EXEC  SQL  SELECT   COUNT ( * INTO  :limit  FROM  emp; 
     
     
/*   Declare a cursor for the FETCH statement.  */  
    
EXEC  SQL  DECLARE  emp_name_cursor  CURSOR   FOR  
    
SELECT  ename  FROM  emp; 
    
EXEC  SQL  FOR  :limit  OPEN  emp_name_cursor; 
     
/*   Set the desired DATA length for the VARCHAR.  */  
    vcplen 
=   10
     
/*   Use SQLVCP to help find the length to malloc.  */  
    sqlvcp(
& vcplen,  & padlen); 
    printf("Actual array length 
of   VARCHAR   is   % ld\n", padlen); 
     
/*   Allocate the names buffer for names. 
    Set the limit variable for the FOR clause. 
*/  
    names 
=  ( VARCHAR   * ) malloc((sizeof (short)  +  
    (
int ) padlen)  *  limit); 
    
if  (names  ==   0
    { 
        printf("Memory allocation error.\n"); 
        
exit ( 1 ); 
    }
/*   Set the maximum lengths before the FETCH. 
 *  Note the "trick" to get an effective VARCHAR *.
 
*/  
    
for  (vc_ptr  =  (my_vc_ptr  * ) names, i  =   0 ; i  <  limit; i ++
    { 
        vc_ptr
-> len   =  (short) padlen; 
        vc_ptr 
=  (my_vc_ptr  * )(( char   * ) vc_ptr  +  
        padlen 
+  sizeof (short)); 
    } 
/*   Execute the FETCH.  */  
    
EXEC  SQL  FOR  :limit  FETCH  emp_name_cursor  INTO  :names; 
     
/*   Print the results.  */  
    printf("Employee names
-- \n"); 
    
    
for  (vc_ptr  =  (my_vc_ptr  * ) names, i  =   0 ; i  <  limit; i ++
    { 
        printf
         ("
% . * s\t( % d)\n", vc_ptr -> len , vc_ptr -> arr, vc_ptr -> len ); 
        vc_ptr 
=  (my_vc_ptr  * )(( char   * ) vc_ptr  +  
                  padlen 
+  sizeof (short)); 
    } 
     
/*   Get statistics about the most recent 
 *  SQL statement using SQLGLS. Note that 
 *  the most recent statement in this example 
 *  is not a FETCH, but rather "SELECT ENAME FROM EMP" 
 *  (the cursor).
 
*/  
    buflen 
=  ( long ) sizeof (stmt_buf); 
    
/*   The returned value should be 1, indicating no error.  */  
    sqlgls(stmt_buf, 
& buflen,  & function_code);
    
if  (buflen  !=   0 )
    { 
        
/*  Print out the SQL statement.  */  
        printf("The SQL statement was
-- \n%.*s\n", buflen, stmt_buf); 
     
        
/*  Print the returned length.  */  
        printf("The statement length 
is   % ld\n", buflen); 
     
        
/*  Print the attributes.  */  
        printf("The 
function  code  is   % ld\n", function_code); 
    
        
EXEC  SQL  COMMIT  RELEASE; 
        
exit ( 0 ); 
    }
    
else  
    { 
        printf("The SQLGLS 
function  returned an error.\n"); 
        
EXEC  SQL  ROLLBACK  RELEASE; 
        
exit ( 1 ); 
    } 


void
sql_error() 

    
char  err_msg [ 512 ]
    
int  buf_len, msg_len;

     
    
EXEC  SQL WHENEVER SQLERROR  CONTINUE
 
    buf_len 
=  sizeof (err_msg); 
    sqlglm(err_msg, 
& buf_len,  & msg_len); 
    printf("
% . * s\n", msg_len, err_msg); 
 
    
EXEC  SQL  ROLLBACK  RELEASE; 
    
exit ( 1 ); 

在pro c/c++ 和 odbc 编程中,经常在sql 语句中的某些字段值进行“绑定”。

 

游标

cursor

SQL%ROWCOUNT 

 

指示器变量:

1、用于指示某个输入字段可以为空。

2、用于指示某个输出字段为空或截断。

 

参考资料:

Embedded SQL (in C++)/Oracle 

http://www.ugrad.cs.ubc.ca/~cs304/2005W1/tutorials/tutorials.html

Pro*C/C++ Precompiler Programmer's Guide
Release 9.2
http://download.oracle.com/docs/cd/B13789_01/appdev.101/a97269/toc.htm

 

http://www.lslnet.com/linux/f/docs1/i26/big5217412.htm

转载于:https://www.cnblogs.com/diylab/archive/2009/12/15/1624528.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值