使用ASCII错误信息文件
有两个方法显示错误信息:一是有finderr显示,二是用rofferr来打印一个错误信息或错误信息范围。
这两个脚本文件在informix用户的bin目录下,而ASCII文件在$INFORMIX/msg/errmsg.txt,错误号的范围从-1到-33000,在用finderr或rofferr时,可以省略减号。个别信息有正的错误号,在使用时必须加上加号前缀。
**************************************
用ESQL/C编程
概述
使用informix-esql/c语句的C程序通常包括下列元素,本章将逐一讲述:
head files头文件
include files包含文件
host variables宿主变量
indicator variables指示变量
SQL语句
在程序中也可以包含动态定义的语句,将在第九章讲述。
本章提供了下列主题的详细说明:
1在esql/c程序中使用头文件
2对esql/c提供预处理
3在C程序中嵌入SQL语句
4识别C变量
5处理与编译C程序
********************
在C程序中嵌入SQL语句
SQL语句用$符号或EXEC SQL关键字嵌入到C程序中,使用关键字与ANSI标准一致。
esql/c中的大小写敏感性
informix-esql/c预处理器对变量名的大小写不敏感。
由PREPARE语句产生的语句id号和由DECLARE语句产生的游标名默认是不敏感的。如果希望预处理器对游标名和语句id大小写敏感,可以在esql的命令行中加入-cs参数。
*插入注释
你可以用双减号作为注释符号在任何的INFORMIX-ESQL/C行中加入注释。注释持续到一行的结束。
同时也可以在INFORMIX-ESQL/C行中使用标准的C注释。如:
----------------------------------------------------
$database stores5; -- stores5 database is open now!
printf("/nDatabase opened/n"); /* This isn’t an ESQL/C line*/
/* so it needs a regular C notation for a comment*/
$begin work; /*You can also use a C comment here*/
---------------------------------------------------
头文件
随informix-esql/c提供有几个头文件,均位于$INFORMIXDIR的/incl子目录下,说明如下:
sqlca.h包含有存储了错误状态代码的结构。这个文件在程序预处理时被自动包含,以检查SQL语句的成功或失败。
sqlda.h包含有存储了数值指针和动态定义变量描述的结构。
sqlstype.h包含了与SQL语句相应的整形常量,与DESCRIBE语句一同使用。
sqltypes.h包含了与C语言和SQL数据类型相应的字符串定义,与DESCRIBE语句一同使用。
varchar.h包含了可用的VARCHAR数据类型的宏。
locator.h包含了存储有blob地址信息的结构。
sqlxtype.h包含了在X/Open模式下工作时与C语言和SQL数据类型对应的字符串定义。
decimal.h包含存储有DECIMAL数据类型定义的结构
datetime.h包含存储有DATETIME和INTERVAL数据类型定义的结构。
在使用时可以用$include把头文件加入到esql/c代码中。
在包含时可以用或不用双引号,但如果要包含的文件是绝对地址的话就要用双引号。
预处理器按下列顺序查找包含文件:
1、在当前目录中
2、在$INFORMIXDIR/incl/esql中
3、在/usr/include中
$define和$undef语句
其他的ESQL/C预处理语句与C语言中相应语句有一样的语法形式,只不过它们在informix-esql/c预处理期间发挥作用:
$define
$undef
ifdef,ifndef,else,elif,endif语句
informix-esql/c预处理器不支持所有的$if语句,仅支持$ifdef和$ifndef语句检查一个变量名是否定义。
预处理器处理下列语句:
$ifdef测试一个名称并执行其后各语句,如果其被$define定义。
$ifndef测试一个名称,如果没有定义则执行其后各语句。
$elif
$else
$endif
在SQL语句中使用宿主变量
宿主变量是指在SQL语句中使用的普通的C变量。当你在SQL语句中使用宿主变量时,要在其名称前加上一个$或:,例如宿主变量hostvar,如果在SQL语句中出现时则为$hostvar或:hostvar。
用冒号作为宿主变量前缀符合ANSI标准。
定义宿主变量
除非在定义时加有$前缀或是定义在EXEC SQL BEGIN DECLARE SECTION / EXEC SQL END DECLARE SECTION之内,否则宿主变量就定义为普通的C变量。
下面是一个使用$格式定义宿主变量的例子:
/* pointer to a character */
$ char * hostvar;
/* integer */
$ int hostint;
/* double */
$ double hostdbl;
/* character array */
$ char hostarr[80];
/* structure */
$ struct {
int svar1;
int svar2;
...
} hoststruct;
下面用的是EXEC SQL格式的例子:
EXEC SQL BEGIN DECLARE SECTION
char *hostvar;
int hostint;
double hostdbl;
char hostarr[80];
EXEC SQL END DECLARE SECTION
EXEC SQL BEGIN DECLARE SECTION
struct {
int svar1;
int svar2;
...
} hoststruct;
EXEC SQL END DECLARE SECTION
初始化宿主变量
INFORMIX-ESQL/C允许你用标准的C表达式定义宿主变量。但是,字符串初值中不能含有嵌入的分号或是ESQL/C关键字。下面是有效的初值。
$int varname = 12;
$long cust_nos[8] = {0,0,0,0,0,0,0,9999};
宿主变量作用域
宿主变量作用域与标准C语言作用域适用相同规则。
除非清楚地定义为外部或静态变量,否则一个宿主变量定义为一个自动变量。
在函数中定义的宿主变量局部于该函数并屏蔽了外部同名变量。
在同一个代码块中不可重复定义同一变量。
定义一个块(block)
保证在一个块内定义的宿主变量局部于该块的方法是使用${和$}对来打开和关闭一个块。或者还可以更简单地用一个花括号对,{和}来标注一个块。例如在下例中的宿主变量blk_int只在括号块内有效,而p_int则在块的内外部都有效。
$int p_int
...
$select customer_num into $p_int from customer
where lname = "Miller";
...
${
$ int blk_int
...
$blk_int = $p_int;
select customer_num into blk_int from customer
where lname = "Miller";
...
$}
...
块的嵌套可达16层,全局层是第一层。
在ANSI标准语法中不支持${和$}符号。
宿主变量的类型
由于宿主变量出现在SQL语句中,故都与一个SQL数据类型有关。另外,一个宿主变量必须被定义为一个C的数据类型。SQL数据类型与C数据类型的关系总结如下:
-----------------------------------------------------------------------
SQL Type ESQL/C Predefined C Language Type
Data Type
CHAR(n) fixchar array[n], or char array [n + 1] or char *,
CHARACTER(n) string array [n+1]
BYTE loc_t
TEXT
DATE long int
DATETIME datetime or dtime_t
DECIMAL decimal or dec_t
DEC
NUMERIC
MONEY
SMALLINT short int
FLOAT double
DOUBLE PRECISION
INTEGER long int
INT
INTERVAL interval or intrvl_t
SERIAL long int
SMALLFLOAT float
REAL
VARCHAR(m,x) varchar[m+1] or char array[m+1]
string array[m+1]
------------------------------------------------------------------------
结构体作为宿主变量
结构体可以被声明为informix-esql/c宿主对象。在esql/c语句中,你可以命名结构体变量作为一个整体或作为其独立的部件。如果使用结构体名,则其被填充到一个部件名列表中去。结构体可以嵌套。
$struct customer_t
{
int c_no;
char fname[32];
char lname[32];
} cust_rec;
$struct customer_t cust2_rec;
在上述声明前提下:
$insert into customer values ($cust_rec);
等价于
$insert into customer
values ($cust_rec.c_no, $cust_rec.fname,
$cust_rec.lname);
typedef表达式作为宿主变量
ESLQ/C支持标准C的typedef表达式而且允许它们作为宿主变量,如下列代码创建了smallint类型作为一个短整形类型和serial类型作为长整形类型。然后声明一个变量row_nums作为serial类型,另一个变量counter作为smallint类型。
$typedef short smallint;
$typedef long serial;
$serial row_nums [MAXROWS];
$smallint counter;
不能用typedef来声明一个多维数组或联合作为宿主变量。
宿主变量的空值
esql/c提供了一个用来测试宿主变量是否为空的函数(risnull),另一个函数用来设置宿主变量为空(rsetnull).
一个INFORMIX-ESQL/C样例
这个例子使用一个没有自由参数的select语句,也就是说,所有需要运行select语句的信息在编译时都包含在程序中。
demo1.ec读取stores5数据库的customer表中的名和姓(以字母C开始)。两个宿主变量$fname和$lname用来存放从customer表中读取的数据,声明了一个游标用来管理从表中得到的信息。记录被一行一行地读取的同时姓名输出到屏幕上。
-----------------------------------
1 #include <stdio.h>
2 $include sqlca;
3
4 /* Uncomment the following line if the database has
5 transactions: */
6
7 /* $define TRANS; */
8
9 $define FNAME_LEN 15;
10 $define LNAME_LEN 15;
11
12 main()
13
14 {
15 $char fname[ FNAME_LEN + 1 ];
16 $char lname[ LNAME_LEN + 1 ];
17
18 printf( "/nDEMO1 Sample ESQL program running./n/n");
19
20 $database stores5;
21
22 $declare democursor cursor for
23 select fname, lname
24 into $fname, $lname
25 from customer
26 where lname > "C";
----------------------------------
1-3行
#include<stdio.h>语句从/usr/include目录包含了UNIX头文件stdio.h。这个文件使demo1可以使用I/O库。sqlca.h文件是一个ESQL/C的头文件,定义了有错误发生时保存ESQL/C错误信息的结构。
4-10行
这几行代码会在ESQL/C预处理的第一阶段进行处理。第4到6行是第七行的注释,如果去除define TRANS的注释,一个指示数据库符号就被创建,并使用事务。第9到10行定义常量FNAME_LEN和LNAME_LEN,它们在后面的宿主变量定义中要用到。
15-16行
这几行为fname和lname定义宿主变量,宿主变量接收从表中得到的数据,并提供向表中写入的数据。fname字符数组的长度比其关联列的长度大1,多出的一个字节用来存放字符串终结符。
18行
告诉程序用户程序开始执行了。
20行
这行是程序中的第一条SQL语句。它打开名为stores5的数据库。在打开前,这个数据库必须已经创建了。
22到26行
这几行含有创建一个名为democursor的游标的DECLARE语句用来管理从customer表中读取的数据。从表中读取的数据类型由第23到26行中的DECLARE语句中的SELECT语句来确实。根据SELECT语句,只有姓的起始字符为C的人的姓名会被选取。
----------------------------------------
27 $ifdef TRANS;
28 $begin work;
29 $endif;
30
31 $open democursor;
32
33 for (;;)
34 {
35 $fetch democursor;
36 if (sqlca.sqlcode != 0) break;
37 printf("%s %s0,fname, lname");
38 }
39
40 $close democursor;
41
42 $ifdef TRANS;
43 $commit work;
44 $endif;
45
46 printf("/nProgram Over./n");
47 }
-------------------------------------
27-29行
这几和由ESQL/C的预处理器第一阶段进行处理。如果设置了TRANS符号,则在$ifdef和$endif之间的行就被编译。在此例中,28行上的BEGIN WORK语句被编译进代码中。
31行
OPEN语句打开了democursor游标。
33-38
这一段是一包含fetch语句的loop循环。loop的每个动作中fetch语句都通过democursor游标从表中选择一行并把数据放到宿主变量fname和lanme中,只要sqlca.sqlcode为零,数据就被成功读取,然后循环结束。如果发生错误,数据库服务器将设置sqlca.sqlcode为一个非零值。当所有匹配SELECT规则的行读取后,数据库服务器设置sqlca.sqlcode为100。所以当sqlca.sqlcode不为0时,循环退出。
40行
CLOSE语句断开游标与SLEECT语句的联接。
42-43
如果设置了TRANS符号,第43行就被编译。本例中,28行中的BEGIN WORK语句应该已经被编译进代码中。
44-45
最后两行告诉用户程序结束并关闭主函数。
第二章
ESQLC的数据类型
一,为宿主变量选择数据类型
宿主变量出现在SQL语句中,都与一个SQL的数据类型相关联。SQL,ESQLC,C的数据类型对照表见附表。
字符数据类型的选择
如果你使用字符数据类型,可以在char,string,fixchar,varchar四种类型中选择一种作为宿主变量类型,这几种类型的区别如下:
char此类型用空格填充尾部直到CHAR型字段长度,并带有字符串终止符,声明时要将长度在字段长度上加1。
string此类型数据与chra的不同在于在插入字符串终止符前截掉尾部空格。声明时也要将长度在字段长度上加1。
fixchar此类型与char类型基本相同,除了它不在尾部加上字符串终止符。也就是声明时可以与对应的字段长度相同。
varchar此类型实际上是字符数组,其后添加了字符终止符,声明时长度要在字段最大长度加1。
数据转换
当两个宿主变量的数据类型不同,或者两列的数据类型不同时,ESQL/C就尝试将其中一个转换为另一个的类型以使它们相同。这包括把一个以数字形态表示的文本型转换为数值型。例如,为了比较一个数值与一个文本型数值,就有必要进行这种转换。
即使变量声明没有按照前术的对照关系,如果转换有意义的话,ESQL/C也尝试进行转换。
转换可能发生在多种情形下,下面是一些常见的转换情形:
1、如果你设定一个比较两个不同类型的值的时候。
2、如果你用一个类型的宿主变量向表中插入值而接收该值的列是另一类型时。
3、如果一个数值与另一类型的数值进行操作时,在操作前两个值都要转换为一个DECIMAL类型的值。
如果数值型转换为字符型,则为其创建一个字符串。
如果不能转换,原因或者是转换没有意义,或者是接收的变量过小无法放下转换后的值,ELSQ/C返回的值如下所示,N代表一个数值型数据,C代表一个字符型数据。
---------------------------------------------------------
转换 问题 结果
C->C 放不下 字符串被截断;sqlca.sqlwarn.sqlwarn1设为W;
指示变量被设为原始串大小。
N->C 放不下 字符串用星号填充;sqlca.sqlwarn.sqlwarn1设为W;
指示变量设为一个正整数。
C->N 不是一个数 the number is undefined;sqlca.sqlcode设为一个负数。
C->N 溢出 同上
N->N 溢出 同上
---------------------------------------------------------
在DATETIME类型和DATE类型间转换
ESQLC没有提供自动转换DATETIME和DATE类型的函数。可以使用现在函数和中间字符变量来进行转换。
要转换一个DATETIME类型的值,有以下几步:
1、用dtextend来调整DATETIME为年到日
2、用tdtoasc创建一个yyyy-mm-dd格式的字符串。
3、用rdefmtdate加一个模式参数将字符串转换为DATE值。
数据类型函数概述
下表列出了informix中作用于两种以上数据类型的库函数,对空值操作的函数,或者格式化某些变量类型的函数。以rtyp打头的为不同数据类型提供了机器无关的大小和对齐信息。以rfmt打头的把一个数值转换为一个格式化字符串。
---------------------------------------------------------
函数名 说明
rfmtdouble 把一个双精度数值转换为一个字符串
rfmtlong 把一个长整型数转换为一个格式化字符串
risnull 检查一个C变量是否为空
rsetnull 设置一个C变量为空
rtypalign 在适当类型边界上对齐数据
rtypmsize 给出SQL数据类型的字节大小
rtypname 转换数据类型为字符串
rtypwidth 给出最小转换字节大小
----------------------------------------------------------
RISNULL
目的:检查一个变量是否为空
语法:
int risnull(type,ptrvar)
int type;
char * ptrvar;
ptrvar是一个指向C变量的指针。
type是一个对应于C变量的数据类型的整数。
返回值:
1 变量为空
0 变量不空
------------------------------------------------------------
RSETNULL
目的:
本函数将一个C变量设为与数据库空值对应的值
语法:
------------------------------------------------------------
int rsetnull(type,ptrvar)
int type;
char *ptrvar;
----------------------------------------------
ptrvar是一个指向C变量的指针
type是一个对应于C变量的数据类型的整数
这个函数对应的例子中,更新表的语句:
$update stock set unit_price=$unit_price where current of upcurs
功能是更新游标中的当前行中的unit_price列的值,其中的where子句为where current of upcurs,是指游标upcurs中的当前行。
#define LCASE(c) (isalpha(c) ? (isupper(c) ? tolower(c) : c) : c)
称为条件表达式,一般形式为:a>b? a:b,含义为如果a>b,则该条件表达式值为a,否则该条件表达式值为b。
条件表达式的结合方向为自右向左,即如果有条件表达式a>b?a:c>d?c:d,则其等价于a>b?a:(c>d?c:d),所以上术程序中的表达式的计算是:先判断字符c是否为字母,如果是则再判断c是否为大写字母,如果不是字母则表达式值为非字母字符c,如果是大写字母,则将c转换为小写字母,如果不是大写字母(即为小写字母),则直接取c值。
用if语句表达如下:
if isalpha(c) then
if isupper(c) then
tolower(c)
printf(c)
else
printf(c)
endif
else
printf(c)
endif
在标准C语言中,以0代表逻辑假,以非0代表逻辑真。
字符串:format[]="($$,$$$,$$$.&&)"是一个格式化串,用来对数值进行格式化。其中$用来在最左端添加一个浮动的$符号,&用来在显示域中可能为空的位置上显示0。
p78
本文介绍 Informix ESQL/C 的基本概念,包括如何在 C 程序中嵌入 SQL 语句、宿主变量的定义与使用、预处理指令的应用等关键知识点。此外还探讨了数据类型的选择及转换等问题。
2273

被折叠的 条评论
为什么被折叠?



