ESQL/C

ESQL/C
    很多来自网络,自己整理了一下。

    ☆ 概念
  利用高级语言的过程性结构来弥补SQL语言实现复杂应用方面的不足。
  嵌入SQL的高级语言称为主语言或宿主语言
  在混合编程中,SQL语句负责操作数据库,高级语言语句负责控制程序流程
  预编译方法:由DBMS的预处理程序对源程序扫描,识别出SQL语句,把它们转换成主语言调用语句,以使主语言编译器能识别它,最后由主语言编译器将整个源程序编译成目标码。

    ☆ 嵌入式SQL的一般形式
  所有的嵌入式SQL语句都必须加前缀EXEC SQL
  在C语言中:  EXEC SQL <SQL语句>
  例如:EXEC SQL DROP TABLE Student
;

    ☆ 嵌入式SQL与主语言的通信
  向主语言传递SQL语句执行状态信息,使语言能够据此信息控制程序流程,用SQL通信区(SQLCA【SQL Communication Area】)实现。
  主语言向SQL语句提供参数,主要用主变量(Host Variable)实现;
  将SQL语句查询数据库的结果交主语言进一步处理,主要用主变量和游标(Cursor)实现。

    ☆ SQL通信区
  SQLCA中有一个存放每次执行SQL语句后返回代码的变量SQLCODE。
  每次执行完SQL语句后都应该测试一下SQLCODE的值,以了解该SQL语句执行情况并做相应处理,如果SQLCODE等于预定的常量SUCCESS,则表示SQL语句成功,否则在SQLCODE中存放错误代码。
  SQLCA(SQL Communication Access) 系由系统提供之系统记录架构,作为back end与 front end 之间沟通之用,当发生 I/O 状态时,系统会记录该状态于SQLCA 中,front end 即可依据其其内容得知 I/O 运作是否成功,再决定往后执行的步骤。SQLCA 为系统定义之 GLOBAL变量,以下为其架构并介绍其内容与用途:  
DEFINE SQLCA RECORD  
          SQLCODE    INTEGER
,   
          SQLERRM    CHAR(
71 ) ,   
          SQLERRP    CHAR(
8 ) ,   
          SQLERRD    ARRAY
[ 6 ]  OF INTEGER ,   
          SQLAWARN   CHAR(
8 )  
END RECORD 
 
  .SQLCODE :表示 I/O 的结果  
 
0    表示 I/O 成功  
 
100  表示 NOTFOUND  
 < 
0  表示 I/O 失败
  
  .SQLERRM :保留未用
  .SQLERRP :保留未用
  
  .SQLERRD :为一个含有6个INTEGER数组  
  SQLERRD
[ 1 ] :保留未用  
  SQLERRD
[ 2 ] :新增时 SERIAL 字段所传回之值  
  SQLERRD
[ 3 ] :处理资料的笔数  
  SQLERRD
[ 4 ] :查询时预估的 CPU COST  
  SQLERRD
[ 5 ] :SQL指令之错误位移  
  SQLERRD
[ 6 ] :最后一个 ROWID 值
  
  .SQLAWARN :为一个含有8个字符的字符串,以记录I/O时产生的警告讯息。若正确无误,则相对应之字符设定为空白,否则会被设定为
" W " 。  
  SQLAWARN
[ 1 ] :若第2至第8字符中任意一个被设成 " W " ,则此字符亦为 " W " ,否则为空白。  
  SQLAWARN
[ 2 ] :若资料太长而被截掉时,会被设成  " W " 。  
  SQLAWARN
[ 3 ] :若 aggregate function(如 SUM,AVG,MAX,MIN) 处理时遇到 NULL 值,则会被设成 " W " 。  
  SQLAWARN
[ 4 ] :若查询时,若欲查询的字段数目和 INTO 之变量数目不合时,会被设成  " W " 。  
  SQLAWARN
[ 5 ] :如转换 float 成 integer 时,则会被设成  " W " 。  
  SQLAWARN
[ 6 ] :保留未用  
  SQLAWARN
[ 7 ] :保留未用  
  SQLAWARN
[ 8 ] :保留未用  

    ☆ 主变量 
  一个主变量既可是输入主变量也可是输出主变量。
  主变量必须在SQL语句EXEC SQL BEGIN DECLARE SECTION与EXEC SQL END DECLARE SECTION之间进行说明。
  例如:
  EXEC SQL BEGIN DECLARE SECTION
;
  int    i = 0 ;
  EXEC SQL END DECLARE SECTION ;
  SQL语句的主变量名前要加冒号作为标志。
  在SQL语句之外,主变量直接引用,不须加冒号。

    ☆ 使用游标查询
   EXEC  SQL  DECLARE  cur  CURSOR   FOR   select  name,sex  from  student  where  no  like  :no; // 定义游标
  
EXEC  SQL  OPEN  cur; // 打开游标
  
for (;;){
    
EXEC  SQL  fetch  cur into :name,:sex; // 推进游标
    
if (sqlca.sqlcode == 100 ) // 没有满足条件的数据
        
break ;
    
// 操作数据
  }
  
EXEC  SQL  close  cur; // 关闭游标
  
EXEC  SQL free  cur; // 释放游标

    ☆ 使用事务
  事务的三个常用操作:开始事务( BEGIN   WORK ),提交事务( COMMIT   WORK ),回滚( ROLLBACK   WORK ),
  例如:
  
EXEC   SQL   BEGIN   WORK ;
  ……
// 数据库操作
  
if (sqlca.sqlcode < 0 )
    
EXEC   SQL  ROLLBACK    WORK ;
  
else
    
EXEC   SQL  COMMIT    WORK ;


    ☆ CURRENT形式的UPDATE语句和DELETE语句
  UPDATE和DELETE语句都是集合操作,如果只想修改或删除其中的某个记录,则需要用带游标的SELECT语句查出所有满足条件记录,从中进一步找出要修改或删除的记录,然后用CURRENT形式的UPDATE和DELETE语句处理。
  用DELCARE语句说明游标。如果是为CURRENT形式的UPDATE语句作准备,则SELECT语句中要用 FOR UPDATE OF<列名>用来指明查询出的数据在指定列是可修改的。如果是为CURRENT形式的DELETE语句作准备,则不必使用上述子句。
  检查该记录是否为该修改或删除的记录。如果是,则修改或删除之。这时UPDATE和DELETE语句中要用子句  WHERE CURRENT OF<游标名>,表示修改或删除的是最近一次取出的记录,即游标指针指向的记录。
  
  例如:
char yn
;
EXEC SQL BEGIN DELCARE SECTION ;
char Sno [ 20 ] , Sname [ 20 ] , NEWSname [ 20 ] ;
EXEC SQL END DECLARE SECTION ;
EXEC SQL DECLARE cur CURSOR FOR SELECT Sno ,  Sname FROM Student WHERE Sno like ' 01 %' FOR UPDATE OF Sname ;
EXEC SQL OPEN cur
while(
1 ) { /*用循环结构逐条处理结果集中的记录*/
    EXEC SQL FETCH cur INTO :Sno
, :Sname ;
    if(sqlca.sqlcode == 100 )
        break
;                /*若查询结果处理完或出现错误,则退出循环*/
    printf( " no=%s,name=%s " , Sno , Sname) ;
    printf( " UPDATE Name(y/n)? " ) ;         /*问用户是否需要修改*/
    scanf( " %c " ,  &yn) ;
    if(yn = 'y' or yn = 'Y')                     /*需要修改*/
    {
       printf(
" INPUT NEW Name: " ) ;
       scanf( " %d " , &NEWSname) ;
       EXEC SQL UPDATE Student SET Sname  =  :NEWSname WHERE CURRENT OF cur ;
    } ;  
} ;
EXEC SQL CLOSE cur ;

    ☆ 数据类型
   1 、SQL与C数据类型的对应简单类型 
SQL        C 
CHAR(n)        
char (n + 1
CHARCTER(n)    
char   *  
SMALLINT    
short
INTERGER    
int
SMALLFLOAT    
float  
FLOAT
/ DOUBLE     double  
SERIAL        
long   int  
DATE         
long   int
VARCHAR        
string
  
2 、数据类型转换 
转换类型     转换后 
FLOAT        DECIMAL(
16
SMALLFLOAT    DECIMAL(
8
INTERGER    DECIMAL(
10 , 0 )
SAMLLINT    DECIMAL(
5 , 0 )

    ☆ 有关CHAR类型的函数
   1 、以空值结尾的串的操作函数 
rdownshift(
char   * s)        把一个字符串中的所有字母转换成小写形式。 
rupshift(
char   * s)        把一个字符串中的所有字母转换成大写形式。 
stcat(
char   * s,  char   * dest)    把一个字符串同另一个字符串相连接。 
stcmpr(
char   * s1,  char   * s2)    比较两个字符串。 
stcopy(
char   * from,  char   * to)    把一个字符串拷贝到另一个字符串。 
stleng(
char   * string )    统计字符串的长度。 

  
2 、定长串的操作函数 
bycmpr(
char  byte1, byte2, rpt len)    比较两组连续的字节内存块。 
bycopy(
char   * from,  char   * to,  int  len)    把一块内存的内容拷贝到另一块内存。 
byfill(
char   * to,  int  len,  char  ch)    用字符填充指定的内存块。 
byleng(
char  from,  int  count)    统计有效字符的数目。有效字符是指字符串去除了末尾空格所剩的字符。 

  
3 、字符串操作函数 
ldchar(
char   * from,  int  num,  char   * to)    拷贝定长串到空值结尾的串。 
stchar(
char   * from,  char   * to,  int  num)    拷贝空值结尾的串到定长串。 

  
4 、字符串函数简单数值转换 
rstod(
char   * str,  double   * dblval)    把以空值结束的字符串转换成C的double型 
rstoi(
char   * str,  int   * intval)    把以空值结束的字符串转换成C的int类型。 
rstol(
char   * str,  long   * lngval)    把以空值结束的字符串转换成C的long类型。

    ☆ DATE类型的函数
   1 、创建内部日期 
rdefmtdate(
long   * jdate,  char   * frmt  char   * str)    生成具有确定格式的日期字符串。(str字符串和fmt必须按月、日、年的同一顺序)
返回代码:0操作成功;
- 1204在str参数中有非法的月份; - 1206在str参数中有非法的日期; - 1209由于str中没有包含年、月、日各部分间的定界符,str的长度必须准确定义为6或8个字节长; - 1212fmt中没有包含年、月、日部分。 
fmt和str的有效组合 
fmt        str 
" mmddyy "       " DEC 25th 1997 "  
" mmm.dd.yyyy "      " dec 25 1997 "  
" mmm.dd.yyyy "      " DEC-25-1997 "  
" mmm.dd.yyyy "      " 12251997 "  
" mmm.dd.yyyy "      " 12/25/1997 "  
" yy/mm/dd "      " 97/12/25 "  
" yy/mm/dd "      " 1997,December, 25th "  
" yy/mm/dd "      " In the year 1997, the month of December, its 25th day "  
" dd-mm-yy "      " This 25th day of December, 1997 "  

rmdyjul(
short  mdy[ 3 ],  long   * jdate) 用三个短整数生成一个内部日期这三个整数是有关年、月、日的数字值。(年必须以完整的形式表达) 
返回代码:0操作成功。 
- 1204在mdy[ 2 ]中有非法年份。  - 1205在mdy[ 1 ]中有非法月份。  - 1206在mdy[ 0 ]中有非法日期。 

rstrdate(
char   * str,  long   * jdate)    将一个字符串日期转换成一内部格式的日期。 
rtoday(
long   * jdate)    从系统日期创建一个内部日期值。 

  
2 、从内部日期转换成其他类型 
rfmtdate(ling jdate, 
char   * fmt,  char   * str)    从内部格式的日期类型值创建格式化的字符串。返回代码:0操作成功。  - 1210内部日期不能被转换成月 - - 年格式。 - 1211程序存储溢出,即存储分配错误。
 
rjulmdy(
long  jdate,  short  mdy[ 3 ]) 从一个内部日期生成一个含有3个短整数的数组对应内部日期的月、日、年。 
rdatestr(
long  jdate,  char   * str) 从一个内部日期值创建缺省的日期字符串。 
rdayofweek(
long  jdate) 给定一内部格式表示的日期,此函数返回所对应的星期中的某一天。 
rleapyear(
int  year) 用来判断给定的年份是否为闰年。 返回值:TRUE( 1 )是闰年;FALSE( 0 )不是闰年

    ☆ 简单数值类型的格式化函数
rfmtdouble( double  dbval,  char   * fmt,  char   * str)    将双精度格式化为指定的模板格式。 
rfmtlong(
double  longval,  char   * fmt,  char   * str)    将长整型值格式化为指定的模板格式。 
可以构成格式模板串的字符: 
* 以星号代替空格。 
& 以0代替空格。 
#代表一个数字或空格的位置。 
< 左调整,显示一个逗号,仅当左边有数字时才显示。 
.显示一个小数点,一个格式模板串只能有一个小数点。 
- 显示负号,当数字为负的时候显示。 
+ 显示正号,当数字为正的时候显示。 
(显示一个负号,同(一起显示负值。 
)显示一个负号,同)一起显示负值。 
$显示美元符号。

    ☆ 处理空值的数值类型函数
risnull( int  type,  char   * c)    检查C变量是否为空值。 
rsetnull(
int  type,  char   * c)    给C变量置空值。 

    ☆ 其他函数
typalign( int  pos,  int  type)    返回一具有指定数据类型变量的下一个位置。 
rtypmsize(
int  sqltype,  int  sqllen)    返回你必须分配在存储单元中的指定的C或RDSQLD的字节数。 
rtyname(
int  sqltype)    返回一包含指定RDSQL类型名的以空结尾的串。 
rtypwidth(
int  sqltype, intsqllen)    返回一具有RDSQL类型的值转换为一字符类型时避免截取所需的最小字符数。

你可能感兴趣的:(ESQL/C)