Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1333157
  • 博文数量: 185
  • 博客积分: 50
  • 博客等级: 民兵
  • 技术积分: 3934
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-11 13:11
个人简介

iihero@ChinaUnix, ehero.[iihero] 数据库技术的痴迷爱好者. 您可以通过iihero AT qq.com联系到我 以下是我的三本图书: Sybase ASE in Action, Oracle Spatial及OCI高级编程, Java2网络协议内幕

文章分类

全部博文(185)

文章存档

2014年(4)

2013年(181)

分类: Sybase

2013-07-19 11:31:58

使用C接口访问Sybase ASE,有多种方式。见到itpub论坛上有人问起,索性做一个简单的demo。发现,使用SQL/C比Open Client接口更直观,比较适合喜欢偷懒的coder.下边介绍详细过程.

 

1. 数据库环境

数据库iihero, 有用户spring/spring1, 使用sa用户登录,执行如下脚本(test_proc.sql),目的是创建一个示例表及数据,并为它创建一个存储过程,给后边的程序用.

 


  1. use iihero  
  2. go  
  3.   
  4. setuser 'spring'  
  5. go  
  6.   
  7. if exists ( select 1 from sysobjects where name = 'test_proc' )  
  8. drop proc test_proc  
  9. go  
  10.   
  11. if exists ( select 1 from sysobjects where name = 't123')  
  12. drop table t123  
  13. go  
  14.   
  15. create table t123(id int primary key, col2 varchar(32) not null)  
  16. insert into t123 values(1, 'iihero')  
  17. insert into t123 values(2, 'Sybase')  
  18. insert into t123 values(3, 'ASE')  
  19. go  
  20.   
  21. create proc test_proc (@id_min int, @num_t123 int output) with recompile  
  22. as  
  23. select @num_t123 = count( a.id ) from iihero.spring.t123 a where a.id > = @id_min  
  24. go   
  25.   
  26. setuser  
  27. go  
  28.   
  29. declare @num_t123 int  
  30. exec spring.test_proc 1, @num_t123 output  
  31. -- select @num_123 = count(a.id) from iihero.spring.t123 a where a.id>=1  
  32. select @num_t123  
  33. go  
  34.   
  35.    


 

最后它有一段验证过程.结果显然是3了.

 

2. 看我们的程序.

就是通过嵌入式SQL访问这个存储过程test_proc,并返回结果(example.cp), 内容如下:

 


  1. #define ERREXIT    -1  
  2. #define STDEXIT    0  
  3.   
  4. #include   
  5.   
  6. /* Declare the SQLCA. */  
  7. EXEC SQL INCLUDE SQLCA;  
  8.   
  9. EXEC SQL BEGIN DECLARE SECTION;  
  10. #define TYPESIZE     13  
  11. #define    TIDSIZE     6  
  12. EXEC SQL END DECLARE SECTION;  
  13.   
  14. #define  EOLN    '/0'  
  15.   
  16. void error_handler(void)  
  17. {  
  18.     fprintf(stderr, "/n** SQLCODE=(%ld)", sqlca.sqlcode);  
  19.   
  20.     if (sqlca.sqlerrm.sqlerrml)  
  21.     {  
  22.         fprintf(stderr, "/n** ASE Error ");  
  23.         fprintf(stderr, "/n** %s", sqlca.sqlerrm.sqlerrmc);  
  24.     }  
  25.   
  26.     fprintf(stderr, "/n/n");  
  27.   
  28.     exit(ERREXIT);  
  29. }  
  30.   
  31. void warning_handler(void)  
  32. {  
  33.   
  34.     if (sqlca.sqlwarn[1] == 'W')  
  35.     {  
  36.         fprintf(stderr,   
  37.             "/n** Data truncated./n");  
  38.     }  
  39.   
  40.     if (sqlca.sqlwarn[3] == 'W')  
  41.     {  
  42.         fprintf(stderr,   
  43.             "/n** Insufficient host variables to store results./n");  
  44.     }      
  45.     return;  
  46. }  
  47.   
  48. int main()  
  49. {  
  50.     EXEC SQL BEGIN DECLARE SECTION;  
  51.     /* storage for login name and password. */  
  52.     char    username[30];  
  53.     char    password[30];  
  54.     EXEC SQL END DECLARE SECTION;  
  55.       
  56.     EXEC SQL BEGIN DECLARE SECTION;  
  57.     CS_INT id_min;  
  58.     CS_INT num_t123;  
  59.     CS_SMALLINT retcode;  
  60.     EXEC SQL END DECLARE SECTION;      
  61.       
  62.     EXEC SQL WHENEVER SQLERROR CALL error_handler();  
  63.     EXEC SQL WHENEVER SQLWARNING CALL warning_handler();  
  64.     EXEC SQL WHENEVER NOT FOUND CONTINUE;      
  65.       
  66.     strcpy(username, "spring");  
  67.     strcpy(password, "spring1");  
  68.     EXEC SQL CONNECT :username IDENTIFIED BY :password;  
  69.     EXEC SQL USE iihero;  
  70.       
  71.     printf("Begin test!/n");  
  72.       
  73.     id_min = 0;  
  74.     exec sql exec :retcode = test_proc :id_min, :num_t123 output;  
  75.       
  76.     printf("num_t123=%ld/n", num_t123);  
  77.       
  78.     EXEC SQL DISCONNECT DEFAULT;  
  79.       
  80.     printf("End test!/n");  
  81.       
  82.     return STDEXIT;  
  83. }  


 

3. 编译和链接

Sybase ASE中的SQL/C编程,需要进行预编译,编译,链接三个步骤.

首先要从命令行里进入vc6的dos环境, 就是进入控制台窗口,运行VC98/bin下边的VCVARS32.bat文件.

确保你的LIB变量有%SYBASE%/%SYBASE_OCS%/lib这个路径.

a. 预编译: (预编译命令是cpre)

E:/MyDocument/MYBOOKS/ASE/code/esqlc>cpre -CMSVC -m -O example.c example.cp
Precompilation Successful. No Errors or Warnings found.
Statistical Report:
        Program name: cpre
        Options specified: /m
        Input file name: example.cp
        Listing file name:
        Target file name: example.c
        ISQL file name:
        Tag ID specified:
        Compiler used: MSVC
        Open Client version: CS_VERSION_150
        Number of information messages: 11
        Number of warning messages: 0
        Number of error messages: 0
        Number of SQL statements parsed: 11
        Number of host variables declared: 6
        Number of SQL cursors declared: 0
        Number of dynamic SQL statements: 0
        Number of stored Procedures generated: 1
        Connection(s) information:
                User id:
                Server:
                Database:

b. 编译: (它还需要%SYBASE%/%SYBASE_OCS%/include/sybesql.c编译成obj文件)

因此使用如下命令,编译两个.c文件:

E:/MyDocument/MYBOOKS/ASE/code/esqlc>cl /DDEBUG=1 /D_DEBUG=1 /DNET_DEBUG=1 /Od /
Z7 /MD /nologo /DWIN32 -Id:/sybase/OCS-15_0/include d:/sybase/OCS-15_0/include/s
ybesql.c example.c /c
sybesql.c
example.c
Generating Code...

 

c. 链接:

E:/MyDocument/MYBOOKS/ASE/code/esqlc>link example.obj sybesql.obj /out:example.e
xe libsybct.lib libsybcs.lib MSVCRT.lib
Microsoft (R) Incremental Linker Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

 

3. 最后结果:

E:/MyDocument/MYBOOKS/ASE/code/esqlc>example.exe
Begin test!
num_t123=3
End test!

 

上述过程只是简单的演示一下一个简单的存储过程在SYBASE ESQL/C中的使用. 有兴趣可以一试.

至于编译器,VC6, VC7/8/9,都应该支持.

之所以使用命令行,是因为不想依赖于集成开发环境.

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