IBM Informix ESQL/C Programmers Manual读书笔记(十一)
注意:未再学习INFORMIX,是初学时的笔记
可能会有错误,最好比对英文原版
/* 使用系统描述符区域探测 */
ALLOCATE DESCRIPTOR 分配系统描述符内存区域
DESCRIBE..USING SQL DESCRIPTOR 根据列列表信息初始化系统描述符区
GET DESCRIPTOR 获得系统描述符区域字段的信息
SET DESCRIPTOR 将信息放入系统描述符区域
/* 对于使用游标的SELECT and EXECUTE FUNCTION语句 */
OPEN..USING SQL DESCRIPTOR 从特定系统描述符区域获取输入参数
FETCH..USING SQL DESCRIPTOR 将行的内容放入系统描述符区域
/* 对于只返回单行的SELECT and EXECUTE FUNCTION语句 */
EXECUTE..INTO SQL DESCRIPTOR 将单行信息放入系统描述符区域
/* 对于非SELECT语句 */
EXECUTE..USING SQL DESCRIPTOR 从特定系统描述符区域获取输入参数
/* 对于使用插入游标的INSERT语句 */
PUT..USING SQL DESCRIPTOR 将行放入插入缓冲区,从SDA获取列值
DEALLOCATE DESCRIPTOR 释放分配的SDA
/* 分配SDA内存 */
默认分配描述符数目为100,可以加入WITH MAX子句扩大数目
初始化SDA中的COUNT字段
只是分配描述信息,而不是DATA字段
/* 初始化SDA */
设定COUNT字段,其值为SELECT、INSERT列列表中的列数目和表达式,或EXECUTE
FUNCTION返回的值数目
为每列初始化描述符字段
当使用SDA来获取输入参数时,不可使用DESCRIBE来初始化。必须用SET DESCRIPTOR显示
设定SDA中相应的字段
ALLOCATE DESCRIPTOR 为每一列描述符分配内存区域
DESCRIBE..USING SQL DESCRIPTOR 为每一描述符的DATA段分配内存。但是当
DESCRIBE..USING SQL DESCRIPTOR 对SELECT段从列中获取数据INTO lvarchar 宿主变量时并不分配内存。
当你fetch lvarchar数据到SDA时,必须显示指定列值的DATA段所用内存,如下:
1),定义合适大小的lvarchar宿主变量
2),用 SET DESCRIPTOR 指定宿主变量为DATA段。SET DESCRIPTOR 需要在
DESCRIBE..USING SQL DESCRIPTOR 语句之后,但在 FETCH..USING SQL DESCRIPTOR语
句之前。
3),执行 FETCH..USING SQL DESCRIPTOR 语句以接受SDA中的列数据。
EXEC SQL BEGIN DECLARE SECTION;
lvarchar lvarch_val[50];
int i;
EXEC SQL END DECLARE SECTION;
EXEC SQL allocate descriptor ’desc’;
EXEC SQL prepare stmt1 from ’select opaque_col from table1’;
EXEC SQL describe stmt1 using sql descriptor ’desc’;
EXEC SQL declare cursor curs1 for stmt1;
EXEC SQL open curs1;
EXEC SQL set descriptor ’desc’ value 1
data = :lvarch_val, length = 50;
while (1) {
EXEC SQL fetch curs1 using sql descriptor ’desc’;
EXEC SQL get descriptor ’desc’ value 1 :lvarch_val;
printf("Column value is %s\n", lvarch_val);
/* 从SDA中指定 与获取值 */
SET DESCRIPTOR 将值赋予SDA中的字段
GET DESCRIPTOR 从SDA字段中获取值
/* SET DESCRIPTOR */
设定COUNT字段匹配你要提供给SDA的描述符数量,通常是WHERE子句中输入参数的数目。
EXEC SQL set descriptor sysdesc COUNT=:hostvar;
为每列的值设定描述符字段。item_num为你想使用的列描述符的数目,DESCRIP_FIELD是
描述符字段相应的值。
EXEC SQL set descriptor sysdesc VALUE :item_num
DESCRIP_FIELD=:hostvar;
set field值可为WHERE子句提供输入参数,或者修改SDA中相应描述符的内容。
TYPE字段的常量值在sqltypes.h中,但你不能直接在 SET DESCRIPTOR 语句中使用常量,
应当在 SET DESCRIPTOR 语句中将此常量值赋予一个宿主变量:
$int i;
i = SQLINT;
EXEC SQL set descriptor ’desc1’ VALUE 1 TYPE = :i;
/* 如果你在描述中使用 lvarchar指针宿主变量,并带有FETCH和PUT语句以使用SDA,你必
你必须在SET DESCRIPTOR语句中显式指定TYPE类型为 124(CLVARCHARPTRTYPE)。*/
EXEC SQL BEGIN DECLARE SECTION;
lvarchar *lv;
EXEC SQL END DECLARE SECTION;
/* where tab has lvarchar * column */
EXEC SQL prepare stmt from “select col from tab”;
EXEC SQL allocate descriptor 'd';
/* The following describe will return SQLLVARCHAR for the
type of the column */
EXEC SQL describe stmt using sql descriptor 'd';
/* You must set type for *lv variable */
EXEC SQL set descriptor 'd' value 1 DATA = :lv, TYPE = 124;
EXEC SQL declare c cursor for stmt;
EXEC SQL open c;
EXEC SQL fetch c using sql descriptor 'd';
/* 使用GET DESCRIPTOR 语句*/
此句可以得到SDA中被描述的值的个数到COUNT字段
EXEC SQL get descriptor sysdesc VALUE :item_num
:hostvar=DESCRIP_FIELD;
这些文件描述符值通常是被 SELECT/INSERT/EXECUTE FUNCTION说明。也常被用在
FETCH..USING SQL DESCRIPTOR 语句之后,用于拷贝数据库服务器返回的值到宿主变量之中。
/* 指定输入参数的值:*/
因为 DESCRIBE..USING SQL DESCRIPTOR 语句并不分析WHERE子句,你的程序必须将数
量/类型和输入参数的值存储在SDA区,用以显式描述这些参数。
当你执行一个参数化语句时,必须使用USING SQL DESCRIPTOR子句指定包含输入参数定位
的SDA区。
1,对于SELECT中的WHERE子句,使用 OPEN..USING SQL DESCRIPTOR. 这条语句控制一个
序列、滚动、UPDATE、HOLD游标。如果SELECT只是返回单行,使用 EXECUTE..INTO..USING
SQL DESCRIPTOR语句代替游标。
2,对于 DELETE/UPDATE 语句中的 WHERE 子句,使用EXECUTE..USING SQL DESCRIPTOR语
句。
3,对于 INSERT 语句中的 VALUES 子句,使用 EXECUTE..USING SQL DESCRIPTOR 语句。
如果INSERT与插入游标相关,则使用PUT..USING SQL DESCRIPTOR 语句替代。
/* 将数据库中的列值放入SDA */
当你动态创建一个SELECT语句,不能使用 FETCH..INTO hostvar子句,因为你不能在
prepared语句中使用宿主变量。需要使用 FETCH..USING SQL DESCRIPTOR 语句将每一列
的值放入它们表示符的DATA段。
对于多值,必须使用SELELCT游标和函数游标。
如果单行,使用 EXECUTE..INTO SQL DESCRIPTOR
一旦列值放入了SDA,可使用 GET DESCRIPTOR 从他们的数据字段中放入合适的主机变量
。必须设置 LENGTH 和 TYPE 噢。
/* 此时参考demo4.ec例子程序 */
/* 执行一个游标函数 */
1,为自定义函数定义一个函数游标。
DECLARE ....CURSOR EXECUTE FUNCTION
2,OPEN 语句执行函数并打开游标
3,FETCH..USING SQL DESCRIPTOR 语句,接受从游标返回的值,放入SDA区
4,GET DESCRIPTOR 语句,接受SDA区中返回的值,放入SDA区
5,DEALLOCATE DESCRIPTOR
SPL函数如果在RETURN语句带有 WITH RESUME 关键字可以返回多行值。
/* 操作未知列列表基本步骤 */
/* 处理INSERT中的输入参数 */
1,PREPARE INSERT 语句,定义一个表示符
2,ALLOCATE DESCRIPTOR 语句
3,探测列的数量和数据类型。使用 DESCRIBE..USING SQL DESCRIPTOR 语句。DESCRIBE
语句将每一列的描述符放入选择列表。
4,GET DESCRIPTOR 语句将未知列的数目COUNT存入宿主变量。
5,SET DESCRIPTOR 语句将设定相关的DATA和VALUE字段。如果想插入NULL值,设定
INDICATOR 字段为-1,并且不在 SET DESCRIPTOR 语句设定任何DATA段。
6,设定INSERT语句以在数据库插入值。
7,DEALLOCATE DESCRIPTOR
/* 处理INSERT游标 */
1,PREPARE INSERT 语句,之后 DECLARE..CURSOR..
2,使用 OPEN 打开(创建)INSERT游标
3,PUT..USING SQL DESCRIPTOR。PUT 之后,列值从SDA放入INSERT缓冲区。重复如此直到
没有行。
4,FLUSH
5,CLOSE。cursorname
/* 处理参数化的SELECT语句 */
/* 使用SDA定义WHERE子句中的输入参数 */
1,探测输入参数的数量和数据类型
2,ALLOCATE DESCRIPTOR
3,WHERE..SET DESCRIPTOR COUNT..指定WHERE子句中输入参数的数量
4,对每一子句都使用 SET DESCRIPTOR 设定 DATA/TYPE/LENGTH 字段。
注意:CHAR VCHAR类型,LENGTH为字符数组的字节大小。DATETIME INTERVAL类型的
LENGTH为编码限定大小。
如果使用了指示变量,还要设定IDATE ILENGTH ITYPE字段。使用VALUE 关键字识别每个描述符。
从SDA获取输入参数的定义,使用 USING SQL DESCRIPTOR 子句
/* 执行参数化的返回多行的SELECT语句 */
OPEN 语句打开游标
FETCH..USING SQL DESCRIPTOR 语句获取返回值
如含有 WHERE 子句中的输入参数,则 OPEN 语句包含 USING SQL DESCRIPTOR 子句。
如含有未知列,FETCH ..USING SQL DESCRIPTOR 语句会将返回值写入SDA
/* 执行参数化的单例SELECT */
使用 EXECUTE..USING SQL DESCRIPTOR..INTO 语句 代替游标SELECT中的 OPEN..USING
SQL DESCRIPTOR
IBM Informix ESQL/C Programmers Manual读书笔记(十)
注意:为之前学习INFORMIX时笔记,有错误,未审阅和进一步学习
最好比对英文原版
/* 动态管理数据结构 */
1,system-descriptor area,系统描述符区域,是遵循X/Open标准的数据结构,
ALLOCATE DESCRIPTOR, GET DESCRIPTOR, SET DESCRIPTOR, and DEALLOCATE DESCRIPTOR.
2,sqlda是用C语言构建的数据结构,与X/Open标准不同。
/* 系统描述符区域 */
系统描述符区域是ESQL/C为控制返回、发送数据而分配的一块内存区域。
有两个部份:
1),定长部份:COUNT字段,包括系统描述符区域列的数目。
由 DESCRIBE...USING SQL DESCRIPTOR 语句设定COUNT。在发送列值到数据库服务器前,
必须使用 SET DESCRIPTOR 语句来初始化此字段。
2),变长部份:包括系统描述符区域每个值的定长描述符。
每个描述符包含以下内容:
Field DATA TYPE Description
***************************************************************************
DATA char * 列数据的指针
TYPE short 表示列数据的类型,在sqltypes.h和sqlxtype.h中定义
LENGTH short 类型的长度,单位为字节
NAME char * 列名或正被传输的label
INDICATOR short 值为0,表示DATA字段包括非NULL数据
值为-1,表示没有指定数据值是插入NULL
SCALE short 数据段中列数据的等级,仅被DECIMAL和MONEY类型定义
PRECISION short 列数据的精度,仅被DECIMAL和MONEY类型定义
NULLABLE short 列是否可以包含NULL1,允许,0,不允许
IDATA char * 用户自定义指示数据或指示变量数据段
ITYPE short 用户自定义指示变量类型
ILENGTH short 用户自定义指示变量长度
EXTYPEID int4 用户自定义(opaque或distinct)或复合(集合或行)类型
数据的扩展标识符。
EXTYPEID int4 扩展数据名字
ETYPELENGTH short 扩展名字段的长度,单位为字节
EXTYPEOWNERNAME char* 用户自定义和符合数据类型拥有者的名字
EXTYPEOWNERLENGTH short 名字的长度
SOURCEID int4 distinct-type 列源数据的扩展类型。
/* sqlda数据结构 */
sqlda结构有3部份:
1),定长部份:sqlda结构中列字段的数目,由 DESCRIBE...INTO 语句设定sqld字段。
2),变长部份:每个值的sqlvar_struct数据结构,sqlvar_struct为定长数据结构。
sqlda结构中的sqlvar字段指向sqlvar_struct结构数组的起始地址。每一个
sqlvar_struct结构对应一个数据信息。
/* struct sqlvar_struct结构 */
Filed Data Type Description
****************************************************************************
sqltype short 列数据的类型
sqllen short
sqldata char * 列数据的指针
sqlind short * 列数据指示变量的指针。值为0,有非NULL。值为-1,NULL
sqlname char * 列数据的名字或者label名
sqlformat char * 保留字段
sqlitype short 自定义指示变量数据类型
sqlidata char * 指向用户自定义指示变量数据的指针
sqlxid int4 扩展标识符
sqltypename char * 扩展类型名字,用户自定义(opaque或distinct)或复合(
集合或行)类型名字
sqltypelen short 扩展类型名字长度。
sqlownerlen short 扩展类型拥有者名字
sqlsourcetype short 内建的distinct源数据类型
sqlsourceid int4 扩展类型中的源类型
sqlflags int4
3),sqlda自己的描述信息。
Filed Data Type Description
****************************************************************************
desc_name char[19] 描述符名字
desc_occ short sqlda数据结构大小
desc_next struct sqlda * 下一个sqlda结构
DESCRIBE 语句可以在以下数据结构中写信息
1,DESCRIBE...USING SQL DESCRIPTOR 在系统描述符区域存储信息。可以通过 GET
DESCRIBE 语句获取这些信息。
2,DESCRIBE...INTO sqlda_ptr 在sqlda_ptr指针所指向的sqlda结构中存储信息。
如果DESCRIBE成功:
SQLCODE值指示准备好的语句类型。
sqlstype.h头文件中定义了SQL语句类型的常量。检查SQLCODE对应的值确定语句。
如果DESCRIBE语句描述了DELETE或UPDATE,可以指示语句段是否有WHERE子句。
sqltypes.h头文件包含Informix ESQL/C指定的SQL数据类型常量,默认为DESCRIBE使用。
sqlxtype.h定义了X/Open SQL数据类型常量。DESCRIBE在你编译.ec文件使用了-xopen预
处理选项时使用。
/* 探测输入参数 */
你可以使用 DESCRIBE 和 DESCRIBE INPUT 为一个已经准备好但还没有执行的语句返回输
入参数信息。
DESCRIBE INPUT 语句返回值的数量,数据类型,大小,列的名字或者查询表达式。可返回:
带有 IN、BETWEEN、HAVING、ON 子句的 SELECT 语句
SELECT 子查询
SELECT INTO TEMP
DELECT
EXECUTE
/* 带有 WHERE 子句的 INSERT\UPDATE 语句 */
/* 在DESCRIBE分析一个预备好的DELETE和UPDATE语句时,如果包含WHERE子句,设定
* sqlca.sqlwarn.sqlwarn0 和 sqlca.sqlwarn.sqlwarn4 字段为W。设定SQLSTATE值为
* Informix指定警告值,"01I07"。
*/
/* 操作未知语句信息 */
1),定义动态管理结构获取信息。可以是系统描述符区域或者SQLDA结构。
2),使用DESCRIBE语句检查准备好的SELECT语句和描述的各列。
3),指定动态管理结构定位从数据库获取的数据。
/* 使用Fetch数组 */
单一 FETCH 语句从fetch缓冲区到sqlda结构的行数。可由fetch数组增加。
当你fetch simple-large-object时特别有用。
如果不使用fetch数组获取simple large object:
当ESQL/C fetch一个TEXT或BYTE列时,服务器返回列的描述符。
ESQL/C随后请求服务器发送相应的数据。
如果使用fetch数组:
ESQL/C发送一系列的simple-large-object描述符给数据库服务器
数据库服务器在同一时间发送所有的数据。
IBM Informix ESQL/C Programmers Manual读书笔记(九)
/* 与连接有关的环境变量 */
INFORMIXCONTIME
客户端企图连接服务器的最小秒数。
INFORMIXCONRETRY
尝试链接的次数。
INFORMIXSQLHOSTS
UNIX系统上,这个变量指向sqlhosts文件。
WIN系统上,这是网络上服务器的主机名。
INFORMIXSERVER
默认的INFORMIX服务器。
当客户端程序没有显式指定INFORMIXSERVER环境变量时,自动链接到此服务器。
如果第一条SQL语句是connect语句(CONNECT,SET CONNECT),程序根据环境变量
INFORMIXSERVER或者指定语句发起显式连接。
如果是SQL database语句(DATABASE, CREATE DATABASE, START DATABASE),程序发起
隐式连接。
/* 中断SQL请求 */
sqlbreak()库函数可中断数据库服务器,当你想中止当前SQL请求或者请求时间过长时。
或者在较大的查询中,设定SIGNAL(SIG_INT, func_ptr)函数,使ctrl+c时中断。
当数据库在一个大的查询中,如果你想周期性的获得何时可以继续请求的话,可以使用
sqlbreakcallback()函数来确定以下信息:
1,timeout interval,在应用程序恢复控制前等待SQL请求执行的周期时间。
2,callback function,用户自定义的每次超过周期时执行的函数。
/* 不要在使用olipcshm作为网络类型的ESQL/C服务器中使用sqlbreakcallback()函数。
* onipcshm不是一个真正的网络协议,并且并不采用callback function所需要的非阻塞
* I/O。当你对共享内存使用sqlbreakcallback()时,总是返回真值0,但callbackfunc
* 并不执行。
*/
void callbackfunc(mint status);
/* callback合适被调用 callback参数值
* 数据库服务器完成SQL请求时 0
* 在程序对server发出请求后立即 1
* 数据库服务器处理SQL请求超时后去 2
*/
callback可以是下列函数之一:
1, sqldone(),探测数据库是否仍然繁忙。如果返回-439,则繁忙,你可以做终断。
2, sqlbreak(),中断正在执行的SQL服务器操作。
sqlexit()库函数关闭所有连接,包括显式的或者隐式的。如果在数据库打开时调用
sqlexit(),这个函数会导致open transactions回滚。
sqldetach()库函数关闭连接到数据库服务器的子进程。
Informix ESQL/C 提供了'optimized message transfers'功能,允许你对大多数ESQL/C
语句做更小的信息传递,具体实现是,将信息捆绑在一起发送,避免多个小信息包发送发送。
但对以下语句ESQL/C并不进行OPTMSG:
COMMIT WORK
DESCRIBE
EXECUTE
FETCH
FLUSH
PREPARE
PUT
ROLLBACK WORK
SELECT INTO (singleton SELECT)
为使用OPTMSG,必须在客户端设置如下变量:
1,在发起连接前设置OPTMSG环境变量从而允许Optimized Message Transfers
putenv("OPTMSG=1"); /* UNIX */
ifx_putenv("OPTMSG=1"); /* WIN */
2,在ESQL/C应用程序中设置OptMsg全局变量
设置OPTMSG环境变量为1后,必须设置OptMsg全局变量用以指定后面的SQL语句捆绑。
不过当一些SQL语句需要立即被回应,或者在DEBUGGING,或者程序即将结束时,最好禁用。
EXEC SQL include sqlhdr;
OptMsg = 1;
当OPTMSG被启用时,ESQL/C应用程序不能对捆绑语句中的某条做准确的异常处理。
一旦在捆绑语句段中有错误发生,数据库服务器停止执行。
IBM Informix ESQL/C Programmers Manual读书笔记(八)
注意:有错误,为学习INFORMIX时所做
最好比对英文原版
EXEC SQL BEGIN DECLARE SECTION;
mint exception_count;
char overflow[2];
EXEC SQL END DECLARE SECTION;
.
.
EXEC SQL create database db;
EXEC SQL create table tab1 (col1 integer);
EXEC SQL get diagnostics :exception_count = NUMBER,
:overflow = MORE;
/* Figure 11-1. Using GET DIAGNOSTICS to Return Statement Information */
Filed-Name Keyword ESQL/C DATA TYPE Description
NUMBER mint 诊断区最近接受到的异常数量,
1-35000, 当SQL语句执行成功,数量就增加1
MORE char[2] "N"或"Y",超出能存储的异常数,则为Y。
RAW_COUNT mint INSERT/UPDATE/DELETE成功的总数。
/* GET DIAGNOTICS语句返回的异常信息。*/
RETURNED_SQLSTATE char[6] 当前异常的SQLSTATE值。
INFORMIX_SQLCODE int4 Informix指定的状态信息。也设置全局SQLCODE值。
If Informix defines the class (subclass) code, the value is "IX000". If the
International Standards Organization(ISO) defines the class code, the value of
CLASS_ORIGIN is "ISO 9075".If a user-defined routine has
defined the message text of the exception, the value is "U0001".
CLASS_ORIGIN char[255] 如果Informix定义了消息类,职位IX000,如果ISO
标准定义了消息类,值为"ISO 9075",如果用户自定义了异常消息,值为"U0001"
SUBCLASS_ORIGIN char[255] 消息子类,值同上。
MESSAGE_TEXT char[8191] 可变长数组存储。包括异常信息情况,ISAM异常或者
用户定义的信息。
MESSAGE_LENGTH mint MESSAGE_TEXT所包含的信息长度。
SERVER_NAME char[255] 当前CONNECT or DATABASE 的数据库服务器名。
CONNECTION_NAME char[255] 可变长数组,with the actions of a CONNECT or
SET CONNECTION 语句的客户端名字。
EXEC SQL BEGIN DECLARE SECTION;
char class_origin_val[255];
char subclass_origin_val[255];
char message_text_val[8191];
mint messlength_val;
EXEC SQL END DECLARE SECTION;
EXEC SQL create database db;
EXEC SQL create table tab1 (col1 integer);
EXEC SQL get diagnostics exception 1
:class_origin_val = CLASS_ORIGIN,
:subclass_origin_val = SUBCLASS_ORIGIN,
:message_text_val = MESSAGE_TEXT,
:messlength_val = MESSAGE_LENGTH;
EXEC SQL get diagnostics exception 1 :SQLSTATE = RETURNED_SQLSTATE;
运行时Informix自动将diagnositics区域中的RETURNED_SQLSTATE值拷贝到全局变量SQLSTATE。
SQLSTATE有5个字符,前两个为类代码值,后三个为子类代码值。
CLASS CODE值首字母 异常代码定义者 说明
0-4 A-H X/Open与ANSI/ISO定义 子类代码仍以0-4 A-H开头
5-9 依定义实现 子类也依定义实现
I-Z Informix ESQL/C定义
I-Z Informix ESQL/C定义
"IX000" 运行时错误,Informix指定错误消息
"IX001" 运行时错误,GET DIAGNOSTICS语句错误
"U0001" 运行时错误,用户自定义
"01Ixx" 警告,Informix指定
"01U01" 警告,用户自定义
SQLSTATE返回的值:
/*异常情况 值 */
成功 "00000" (可以只检测class code就确定成功)
成功,但没找到行 "02000" (可以只检测class code就确定成功)
成功,但有警告 类代码为"01",子类代码值:
"000"-"006" (ANSI 与 X/Open警告)
"I01"-"I11" (Informix指定)
"U01" (用户自定义)
当有多个异常发生时,可根据GET DIAGNOSTICS返回的NUMBER值循环取出错误。
因为SQLSTATE是全局变量,只存储最近SQL语句发生的异常。所以要使用
RETURNED_SQLSTATE来取出某个错误的SQLSTATE代码值。
WHENEVER 语句让预编译器生成源代码,用以在发生错误、警告或缺少数据时评估 SQL 返
回码并转移到指定的标号。(如果未使用 WHENEVER 语句,默认行为是忽略 SQL 返回码)。
WHENEVER SQLERROR GOTO [Label]:指示预编译器生成源代码,用以在生成负的 sqlcode
值时评估 SQL 返回码并转移到指定标号。
WHENEVER SQLWARNING GOTO [Label]:指示预编译器生成源代码,用以在生成正的
sqlcode 值(除了值 100 之外)时评估 SQL 返回码并转移到指定标号。
WHENEVER NOT FOUND GOTO [Label]:指示预编译器生成源代码,用以在生成为 100 的
sqlcode 值或为 02000 的 sqlstate 值时评估 SQL 返回码并转移到指定标号。(100 值
用来表示没有找到与指定的选择条件匹配的记录,或者已经到达了结果数据集的末尾。)
WHENEVER [SQLERROR | SQL WARNING | NOT FOUND] CALL
WHENEVER [SQLERROR | SQL WARNING | NOT FOUND] CONTINUE:指示预编译器忽略 SQL
IBM Informix ESQL/C Programmers Manual读书笔记(七)
注意:为之前的笔记
未经审阅,有些错误还需阅读英文原文。
没有再学习INFORMIX,将所有笔记一起放出。。。。。
LIST类型存储元素值可重复,且有序的集合。
SQL允许你对集合执行一个只读的SELECT操作并实现一个集合衍生表作为虚拟表。
对集合进行SELECT操作时,并不引用一个ESQL/C集合宿主类型。
应如下操作:
=======
集合表类型:LIST, MULTISET, SET
行类型:命名的或未命名的
SET集合中的元素值均为唯一,且无序。
MULTISET允许重复值。
LIST集合中的元素值可重复,有序的。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
create row type person(name char(255), id int);
create table parents(name char(255), id int, children list(person not null));
/* 从parent表中获取children's names and id:*/
select name, id from table(select children from parents
where parents.id = 1001) c_table(name, id);
执行此查询时,创建了一个满足 p.id = 1001 的虚拟表 c_table。
将集合作为虚拟表来查询更加高效,不必使用很多宿主变量和游标。
EXEC SQL create row type parent_type(name char(255), id int,
<<<<<<< HEAD
children list(person not null));
EXEC SQL create grade12_parents(class_id int,
parents set(parent_type not null));
EXEC SQL select name into :host_var1
from table((select children from table((select parents
from grade12_parents where class_id = 1)) p_table
where p_table.id = 1001)) c_table
where c_table.name like 'Mer%';
=======
children list(person not null));
EXEC SQL create grade12_parents(class_id int,
parents set(parent_type not null));
EXEC SQL select name into :host_var1
from table((select children from table((select parents
from grade12_parents where class_id = 1))
p_table where p_table.id = 1001)) c_table
where c_table.name like 'Mer%';
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
/* 不使用集合的例子 */
EXEC SQL client collection hv1;
EXEC SQL client collection hv2;
EXEC SQL int parent_id;
EXEC SQL char host_var1[256];
.
.
.
EXEC SQL allocate collection hv1;
EXEC SQL allocate collection hv2;
EXEC SQL select parents into :hv1 from grade12_parents
<<<<<<< HEAD
where class_id = 1;
EXEC SQL declare cur1 cursor for select id, children
from table(:hv1);
=======
where class_id = 1;
EXEC SQL declare cur1 cursor for select id, children
from table(:hv1);
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
EXEC SQL open cur1;
for(;;) {
EXEC SQL fetch cur1 into :parent_id, :hv2;
if(parent_id = 1001)
break;
}
EXEC SQL declare cur2 cursor for select name from
table(:hv2));
EXEC SQL open cur2;
for(;;) {
EXEC SQL fetch cur2 into :host_var1;
/* user needs to implement 'like' function */
if(like_function(host_var1, "Mer%"))
break;
}
/* 使用集合表类型的限制 */
<<<<<<< HEAD
1,不可以是 INSERT, DELETE, UPDATE 语句的目标。
2,不可以作为可更新的游标或视图以下的表。
3,不支持序列ordinality。
4,不可以重复引用在同一个FROM子句中的表。例如:
select count(distinct c_id) from parents,
table(parents.children) c_table(c_name, c_id)
where parents.id = 1001;
5,数据库服务器必须静态指定隐含集合表达式的数据类型。
=======
1,不可以是INSERT, DELETE, UPDATE语句的目标。
2,不可以作为可更新的游标或视图以下的表。
3,不支持序列ordinality。
4,不可以重复引用在统一个FROM子句中的表。例如:
select count(distinct c_id) from parents,
table(parents.children) c_table(c_name, c_id)
where parents.id = 1001;
5,数据库服务器必须静态指定下集合表达式的数据类型。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
6,The database server cannot support a reference to a host variable without
casting it to a known collection type. For example, rather than specifying
TABLE(:hostvar), you must cast the host variable:
TABLE(CAST(:hostvar AS type))
TABLE(CAST(? AS type))
<<<<<<< HEAD
如果不把宿主变量CAST为已知集合类型,则数据库服务器不支持对宿主变量的引用。
7,集合表类型LIST不可以保持行的顺序。
8,集合中的数据类型不可以是SERIAL,SERIAL8,BIGSERIAL
DECLARE集合类型变量的时候,显式指定CLIENT关键字。
=======
7,集合表类型LIST不可以保持行的顺序。
8,集合中的数据类型不可以是SERIAL,SERIAL8,BIGSERIAL
DECLARE集合类型变量的时候,必须显式指定CLIENT关键字。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
1,显示指定collection变量:指定集合中元素的类型和集合自身类型。
EXEC SQL BEGIN DECLARE SECTION;
CLIENT COLLECTION LIST(SMALLINT NOT NULL) LIST1;
CLIENT COLLECTION SET(ROW(x CHAR(20),
y SET(INTEGER NOT NULL),
z DECIMAL(10,2)) NOT NULL) row_set;
CLIENT COLLECTION MULTISET(SET(SMALLINT NOT NULL)
NOT NULL) collection3;
EXEC SQL END DECLARE SECTION;
<<<<<<< HEAD
/* Typed 集合类型 */
1,集合类型中的元素类型必须是内建类型。BYTE,TEXT,SERIAL,SERIAL8 都不可以。
且必须对元素类行进行NOT NULL限制。
2,只有SET和LIST可以创建嵌套集合。
3,命名的row类型不可以作为元素类型。然后,你可以指定与已命名row类型字段相同的元素类型。
4,opaque类型
当指定为collection变量的元素类型时,使用的是SQL数据类型,而不是ESQL/C数据类型
。如上例中的 SMALLINT,CHAR,DECIMAL。
=======
集合类型中的元素类型必须是内建类型。BYTE,TEXT,SERIAL,SERIAL8 都不可以。
且必须对元素类行进行NOT NULL限制。
(1),命名的row类型不可以作为元素类型。然后,你可以指定与已命名row类型字段相同的元素类型。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
CREATE ROW TYPE myrow
(
a int,
b float
);
CREATE TABLE mytable
(
col1 int8,
<<<<<<< HEAD
col2 set(myrow not null)
);
EXEC SQL BEGIN DECLARE SECTION;
/* 未命名ROWL类型 */
client collection set(row(a int, b float) not null) my_collection;
EXEC SQL END DECLARE SECTION;
(2),你可以显式定义一个与数据库集合列元素类型不同的集合,只要他们的元素类型可
以互相兼容。自动转换。
=======
col2 set(myrow not null)
);
/* 未命名ROWL类型 */
EXEC SQL BEGIN DECLARE SECTION;
client collection set(row(a int, b float) not null)
my_collection;
EXEC SQL END DECLARE SECTION;
(2),你可以显式定义一个与数据库集合列元素类型相同的集合,只要他们的元素类型可以互相兼容。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
EXEC SQL BEGIN DECLARE SECTION;
client collection set(float not null) set_float;
client collection set(integer not null) set_int;
EXEC SQL END DECLARE SECTION;
EXEC SQL declare cur1 cursor for select * from tab1;
open cur1;
<<<<<<< HEAD
fetch cur1 into :set_float;
=======
fetch cur1 into:set_float;
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
fetch cur1 into :set_int; /* 第一次fetch后,定义了元素类型为float,所以此时产
生类型不匹配错误。*/
<<<<<<< HEAD
/* Untyped集合类型 */
元素类型和集合自身类型均不指定。
仅包含COLLECTION关键字和集合变量名字。
如果你不知道你想访问的集合元素的精确类型,就使用隐式collection变量。
=======
2,隐式指定:元素类型和集合自身类型均不指定。
仅包含COLLECTION关键字和集合变量名字。
如果你不知道你想access的集合元素的精确类型,就使用隐式collection变量。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
你必须获取集合列的定义情况,以便使用未命名collection变量。
EXEC SQL BEGIN DECLARE SECTION;
client collection a_coll;
<<<<<<< HEAD
/* Client Collections */
当SQL语句包含一个collection变量,它有以下语法限制:
1,只可以通过在客户端使用集合衍生表 TABLE(:COLLEC)子句,与 SELECT INSERT
UPDATE DELETE 操作来获取集合元素。
2,INSERT 语句不能在VALUES子句中包含 SELECT,EXECUTE FUNCTION,或者 EXECUTE
PROCEDURE。
3,不能包含 WHERE 子句或表达式
4,不可以使用滚动游标
5,不能包含表达式。
=======
当SQL语句包含一个clollection变量,它有以下语法限制:
1,只可以通过在客户端使用集合衍生表 TABLE(:COLLEC)子句,与 SELECT INSERT
UPDATE DELETE 操作来获取元素。
2,INSERT 语句不能在VALUES子句中包含 SELECT,EXECUTE FUNCTION,或者 EXECUTE
PROCEDURE。
3,不能包含 WHERE 子句或表达式
4,不可以使用游标
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
ESQL/C并不自动分配或释放集合变量的内存,你必须显式指定。
当指向集合的游标处于OPEN状态时,DEALLOCATE COLLECTION 此集合失败
<<<<<<< HEAD
/* 集合列与集合变量的区别:*/
1,当你使用集合衍生表对集合变量进行操作时,语句并不发送给服务器进行处理,而是
ESQL/C处理。
2,当你对集合衍生表进行UPDATE或INSERT操作时,必须带有SET或VALUES子句。
/* 集合变量的初始化 */
必须总是对 Untyped集合变量进行初始化。采用如下语句:
SELECT 集合列 INTO 集合变量 FROM 表名或视图名(不可以是集合衍生表子句)
如果是Typed集合变量,还可以使用如下方法来初始化:
INSERT INTO TABLE(:col_var) VALUES (var);
EXEC SQL ALLOCATE COLLECTION :time_vals;
EXEC SQL SELECT TIME_DATASET INTO :time_vals
FROM readings
WHERE dataset_id = 1356;
=======
集合列与集合变量的区别:
当你使用集合衍生表对集合变量进行操作时,语句并不发送给服务器进行处理,而是
ESQL/C处理。
当你对集合衍生表进行UPDATE或INSERT操作时,必须带有SET或VALUES子句。
可以使用SELECT 集合列 INTO 集合变量 FROM 表名 的方式来对隐式集合变量进行初始化
。并且可以 SELECT 任何类型的集合列 INTO 隐式宿主集合变量。
EXEC SQL ALLOCATE COLLECTION :time_vals;
EXEC SQL SELECT TIME_DATASET INTO :time_vals
FROM readings
WHERE dataset_id = 1356;
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
IFX_INT8CVINT(1423231, &an_int8);
EXEC SQL INSERT INTO TABLE(:time_vals) VALUES (:an_int8);
/* 插入游标 */
插入LIST集合类型时,可以使用 INSERT AT 3 INTO TABLE(:hostcollec)。。。。
插入游标允许你向集合变量插入多个值。但必须是顺序游标,不能是滚动游标和WITH HOLD游标。
EXEC SQL PREPARE ins_stmt FROM
<<<<<<< HEAD
'INSERT INTO TABLE VALUES';
=======
’INSERT INTO TABLE VALUES’;
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
EXEC SQL DECLARE list_curs CURSOR FOR ins_stmt;
EXEC SQL OPEN list_curs USING :a_list;
while (1) {
EXEC SQL PUT list_curs FROM :an_element;
..........
}
EXEC SQL CLOSE list_curs;
EXEC SQL INSERT INTO tab_list(:alist);
EXEC SQL DEALLOCATE :alist;
EXEC SQL FREE ins_stmt;
EXEC SQL FREE list_curs;
<<<<<<< HEAD
/* SELECT from集合变量 */
一,带有集合衍生表子句的SELECT语句允许从集合变量中SELECT元素。有以下限制:
1,SELECT 语句中的list不能包含表达式
2,SELECT 语句中的list必须是 '*'
3,以下SELECT子句和选项不被允许:GROUP BY,HAVING,INTO TEMP,ORDER BY,WHERE,
WITH REOPTIMIZATION
4,FROM 子句不能做连接
二,具体实现:
1,从集合中选择一个元素,事先必须确定只返回一个元素,否则使用SELECT游标:
SELECT * INTO :hostvar FROM table(:col_var);
2,从集合选择一行元素:
EXEC SQL BEGIN DECLARE SECTION;
client collection set(row(a integer) not null) a_set;
row (a integer) a_row;
EXEC SQL END DECLARE SECTION;
EXEC SQL select set_col into :a_set from tab1
where id_col = 17;
EXEC SQL select * into :a_row from table(:a_set);
3,选择多个元素
(1),对集合变量定义一个SELECT游标,限制如下:
集合SELECT游标是一个update游标。定义时不能包含FOR READ ONLY 子句
如果你想修改集合变量中的元素,定义一个SELECT游标作为UPDATE游标使用:
加上FOR UPDATE 子句。然后可以使用 DELECT 或 UPDATE 的WHERE CURRENT OF 子句删除
或更新集合元素。
(2),SELECT游标必须是顺序游标。
/* 更新集合变量 */
1,更新集合中所有元素为同一个值:
使用带有SET 衍生表子句,且不带WHERE CURRENT OF 子句的 UPDATE语句。
EXEC SQL BEGIN DECLARE SECTION;
client collection list(smallint not null) a_list;
int an_int;
EXEC SQL END DECLARE SECTION;
.
EXEC SQL update table(:a_list) (list_elmt) /*list_elmt为SET子句中集合元素的别名*/
set list_elmt = 16;
2,更新集合中某一个元素
$DECLARE xxxx CURSOR FOR SELECT * FROM TABLE(:col_var)
for update;
$OPEN xxxx;
$FETCH xxxx INTO :hostvar;
如果HOSTVAR满足条件:
$UPDATE TABLE(:col_var)(x)
SET x = 10
WHERE CURRENT OF xxxx;
如果只是用字面值插入或更新集合列,不必使用collection宿主变量。
/* 删除集合中的元素 */
删除所有元素:
EXEC SQL DELETE FROM TABLE(:col_var);
删除单个元素:
定义一个FOR UPDATE 的SELECT游标。 FETCH。。INTO。。判定是否满足条件。如果满足
条件的话
DELECT FROM TABLE(:col_var) WHERE CURRENT OF cursor;
在ESQL/C程序中指定嵌套引号时,必须对在单引号字符串中的每一个双引号转义。
EXEC SQL insert into (col1) tab1
values (’SET{\"abcde\"}’);
=======
/* SELECT游标 */
IBM Informix ESQL/C Programmers Manual读书笔记(六)
注意:为之前的笔记
未经审阅,有些错误还需阅读英文原文。
没有再学习INFORMIX,将所有笔记一起放出。。。。。
smart large object类型存储大型的,非关系数据。包括CLOB(character large object)
与BLOB(binary large object)数据类型。可以定位读写并支持更大的文件。
对应的数据类型为 ifx_lo_t。具体定义如下:
EXEC SQL include locator;
.
BEGIN DECLARE SECTION;
EXEC SQL fixed binary 'clob' ifx_lo_t clob_loptr;
EXEC SQL binary 'blob' ifx_lo_t blob_loptr;
END DECLARE SECTION;
/* 在创建一个新的 smart-large-object之前,必须使用ifx_lo_def_create_spec()函数
* 来为LO规格的结构——ifx_lo_create_spec_t 分配内存。这个结构比较难懂,且其实
* 现和功能可能会在未来改变,所以要尽量使用ESQL/C函数来读取和改变它的值。 */
LO-规格结构包含两部份信息:1,磁盘保管信息, 2,创建时间参数
/* 磁盘保管信息 */
=======
预估字节大小 服务器使用这个信息探测对象大小。 ifx_lo_specget_estbytes()
提供一个优化信息。如果值不符,服务器ifx_lo_specset_estbytes()
仍不产生错误,会使用合适的值。
最大字节大小 ifx_lo_specget_maxbytes()
ifx_lo_specset_maxbytes()
分配范围大小 KB单位,通常是一个CHUNK的大小。 ifx_lo_specget_extsz()
ifx_lo_specset_extsz()
sbspace的大小 包含smart LO对象的名字,最多18字节 ifx_lo_specget_sbspace()
ifx_lo_specset_sbspace()
/*创建时间参数 */
指示类型 创建时间参数 说明
/*******************************************************************/
Logging LO_LOG 在日志文件记录SMART LO的改变。慎重使用,日志容量要大
LO_NOLOG
Last access-time LO_KEEP_LASTACCESS_TIME 服务器存储最后读取时间。慎重使用,开
销很大
LO_NO_KEEP_LASTACCESS_TIME
ifx_lo_specset_flags();
ifx_lo_specget_flags();
ifx_lo_col_info(); /* 用列级保管特性更新LO规格结构体 */
ifx_lo_create(); /* 为一个新创建的对象读取包含保管特性的LO规格结构体 */
ifx_lo_spec_free(); /* 释放资源 */
/* 列级保管特性 */
DBA使用 CREATE TABLE 对列级保管特性赋值。PUT 子句指定一个 CLOB、BLOB 列的保管
特性。syscolattribs 系统目录表存储特性。
为打开一个smart LO进行读写操作,ESQL/C程序必须有一个LO指针结构体。此结构体包含
磁盘地址和一个惟一的十六进制标识符。
ifx_lo_copy_to_file(); /* 函数创建一个新的smart LO的LO指针结构体。ifx_lo_t */
ifx_lo_create(); /* 初始化指向新smart LO的LO指针结构体。创建并返回一个
LO描述符 */
ifx_lo_filename(); /* 返回ifx_lo_copy_to_file()函数存储的smart LO指针标识符*/
ifx_lo_from_buffer(); /* 从用户自定义缓冲区复制指定的字节大小到smart LO指针
引用的LO对象 */
ifx_lo_to_buffer();
/* LO文件标识符 */
LO文件标识符是一个整形值,用以标识smart LO。
ifx_lo_readwithseek();
ifx_lo_seek();
ifx_lo_stat();
ifx_lo_tell();
ifx_lo_truncate();
ifx_lo_write();
ifx_lo_writewithseek();
/* 创建 smart LO的步骤 */
1,分配LO规格的结构体内存。 ifx_lo_def_create_spec()
2,确保LO规格结构体包含你想要的保管特性。
3,为新LO创建一个LO指针结构体,并打开LO对象。ifx_lo_create()
4,ifx_lo_write()或ifx_lo_writewithseek() 写入内容。
5,在数据库列中存储LO对象。
/* 访问smart LO */
1,从数据库 SELECT smart LO对象 INTO ifx_lo_t类型的宿主变量。
2,ifx_lo_open()
3,进行读写操作,更新smart LO内容
4,ifx_lo_close()
/* ifx_lo_open和ifx_lo_create使用到的参数 */
LO_RDONLY
LO_DIRTY_READ 只限ifx_open()使用。允许你读取不受约束的数据页。此选项不可用于写
LO_WRONLY
LO_APPEND 要与LO_WRONLY或LO_RDWR结合使用。如果单独使用,是只读打开LO对象。
LO_RDWR
LO_BUFFER 使用基本的数据库缓冲池
LO_NOBUFFER 轻量级IO,使用数据库服务器进程池中的私有缓冲区
LO_LOCKALL
LO_LOCKRANGE
使用 LO_NOBUFFER的注意事项:
结束对LO的操作之后,一定使用ifx_lo_close()函数
所有使用轻量级I/O打开的smart LO共享同样的私有缓冲区。对缓冲区中页的操作可能会
被刷新。
如果smart LO还没有打开,可以使用 ifx_lo_alter() 函数将smart LO从轻量级I/O切换
回BUFFERD I/O。然而,相反的操作会导致错误。
LO_NOBUFFER不能用于写文件
/* 打开一个smart LO的持续时间 */
用ifx_lo_create()和ifx_lo_open()函数打开的文件,只有在你使用了ifx_lo_close()函
数或者会话结束后才被关闭。
即使传输内容结束,也不会关闭噢。
/* 删除一个smart LO */
只有在两种情况都达成的情况下,smart LO才被删除:
1,当前传输被提交
2,打开的smart LO关闭之后
/* 分配、访问一个LO状态结构 */
LO状态结构的函数:
ifx_lo_stat(); /*分配并初始化LO文件描述符的LO状态结构 */
ifx_lo_stat_atime(); /* 事先要设定LO_KEEP_LASTACCESS_TIME。smart LO最后访问的
时间。*/
ifx_lo_stat_cspec(); /* smart LO的状态特性。这些特性存储在LO规格结构体中。 */
ifx_lo_stat_ctime(); /* smart LO状态的最后改变时间,如修改,更改所有者和引用人数 */
ifx_lo_stat_mtime_sec(); /* 最后修改时间,如写入/创建 */
ifx_lo_stat_refcnt(); /* smart LO的引用数 */
ifx_lo_stat_size(); /* smart LO的字节大小 */
/* 修改 smart LO列 */
使用 ALTER TABLE 的 PUT 子句更改CLOB列或BLOB列的保管定位和特性。
你可以改变列存储的sbspace,
/*
*
*
*
*
*
*
*
* 这里看不懂。可参照demo/esqlc目录下的 create_clob.ec get_lo_info.ec
* upd_lo_descr.ec 了解。 */
/* 迁移 simple LO 到 smart LO */
update catalog set advert = ROW ((SELECT cat_picture::blob
FROM stores7:catalog WHERE catalog_num = 10027), pwd
advert.caption)
WHERE catalog_num = 10027;
ALTER TABLE catalog modify cat_descr CLOB,
PUT cat_descr in (sbspc);
=======
IBM Informix ESQL/C Programmers Manual读书笔记(五)
EXEC SQL fixed binary 'clob' ifx_lo_t clob_loptr; EXEC SQL binary 'blob' ifx_lo_t blob_loptr; END DECLARE SECTION; /* 在创建一个新的 smart-large-object之前,必须使用ifx_lo_def_create_spec()函数 * 来为LO规格的结构——ifx_lo_create_spec_t 分配内存。这个结构比较难懂,且其实 * 现和功能可能会在未来改变,所以要尽量使用ESQL/C函数来读取和改变它的值。 */ LO-规格结构包含两部份信息:1,磁盘保管信息, 2,创建时间参数 /* 磁盘保管信息 */ 预估字节大小 服务器使用这个信息探测对象大小。ifx_lo_specget_estbytes() 提供一个优化信息。如果值不符,服务器ifx_lo_specset_estbytes() 仍不产生错误,会使用合适的值。 最大字节大小 ifx_lo_specget_maxbytes() ifx_lo_specset_maxbytes() 分配范围大小 KB单位,通常是一个CHUNK的大小。 ifx_lo_specget_extsz() ifx_lo_specset_extsz() sbspace的大小 包含smart LO对象的名字,最多18字节 ifx_lo_specget_sbspace() ifx_lo_specset_sbspace() /*创建时间参数 */ 指示类型 创建时间参数 说明 /*******************************************************************/ Logging LO_LOG 在日志文件记录SMART LO的改变。慎重使用,日志容量要大 LO_NOLOG Last access-time LO_KEEP_LASTACCESS_TIME 服务器存储最后读取时间。慎重使用,开 销很大 LO_NO_KEEP_LASTACCESS_TIME ifx_lo_specset_flags(); ifx_lo_specget_flags(); ifx_lo_col_info(); /* 用列级保管特性更新LO规格结构体 */ ifx_lo_create(); /* 为一个新创建的对象读取包含保管特性的LO规格结构体 */ ifx_lo_spec_free(); /* 释放资源 */ /* 列级保管特性 */ DBA使用 CREATE TABLE 对列级保管特性赋值。PUT 子句指定一个 CLOB、BLOB 列的保管 特性。syscolattribs 系统目录表存储特性。 为打开一个smart LO进行读写操作,ESQL/C程序必须有一个LO指针结构体。此结构体包含 磁盘地址和一个惟一的十六进制标识符。 ifx_lo_copy_to_file(); /* 函数创建一个新的smart LO的LO指针结构体。ifx_lo_t */ ifx_lo_create(); /* 初始化指向新smart LO的LO指针结构体。创建并返回一个 LO描述符 */ ifx_lo_filename(); /* 返回ifx_lo_copy_to_file()函数存储的smart LO指针标识符*/ ifx_lo_from_buffer(); /* 从用户自定义缓冲区复制指定的字节大小到smart LO指针 引用的LO对象 */ ifx_lo_to_buffer(); /* LO文件标识符 */ LO文件标识符是一个整形值,用以标识smart LO。 ifx_lo_readwithseek(); ifx_lo_seek(); ifx_lo_stat(); ifx_lo_tell(); ifx_lo_truncate(); ifx_lo_write(); ifx_lo_writewithseek(); /* 创建 smart LO的步骤 */ 1,分配LO规格的结构体内存。 ifx_lo_def_create_spec() 2,确保LO规格结构体包含你想要的保管特性。 3,为新LO创建一个LO指针结构体,并打开LO对象。ifx_lo_create() 4,ifx_lo_write()或ifx_lo_writewithseek() 写入内容。 5,在数据库列中存储LO对象。 /* 访问smart LO */ 1,从数据库 SELECT smart LO对象 INTO ifx_lo_t类型的宿主变量。 2,ifx_lo_open() 3,进行读写操作,更新smart LO内容 4,ifx_lo_close() /* ifx_lo_open和ifx_lo_create使用到的参数 */ LO_RDONLY LO_DIRTY_READ 只限ifx_open()使用。允许你读取不受约束的数据页。此选项不可用于写 LO_WRONLY LO_APPEND 要与LO_WRONLY或LO_RDWR结合使用。如果单独使用,是只读打开LO对象。 LO_RDWR LO_BUFFER 使用基本的数据库缓冲池 LO_NOBUFFER 轻量级IO,使用数据库服务器进程池中的私有缓冲区 LO_LOCKALL LO_LOCKRANGE 使用 LO_NOBUFFER的注意事项: 结束对LO的操作之后,一定使用ifx_lo_close()函数 所有使用轻量级I/O打开的smart LO共享同样的私有缓冲区。对缓冲区中页的操作可能会 被刷新。 如果smart LO还没有打开,可以使用 ifx_lo_alter() 函数将smart LO从轻量级I/O切换 回BUFFERD I/O。然而,相反的操作会导致错误。 LO_NOBUFFER不能用于写文件 /* 打开一个smart LO的持续时间 */ 用ifx_lo_create()和ifx_lo_open()函数打开的文件,只有在你使用了ifx_lo_close()函 数或者会话结束后才被关闭。 即使传输内容结束,也不会关闭噢。 /* 删除一个smart LO */ 只有在两种情况都达成的情况下,smart LO才被删除: 1,当前传输被提交 2,打开的smart LO关闭之后 /* 分配、访问一个LO状态结构 */ LO状态结构的函数: ifx_lo_stat(); /*分配并初始化LO文件描述符的LO状态结构 */ ifx_lo_stat_atime(); /* 事先要设定LO_KEEP_LASTACCESS_TIME。smart LO最后访问的 时间。*/ ifx_lo_stat_cspec(); /* smart LO的状态特性。这些特性存储在LO规格结构体中。 */ ifx_lo_stat_ctime(); /* smart LO状态的最后改变时间,如修改,更改所有者和引用人数 */ ifx_lo_stat_mtime_sec(); /* 最后修改时间,如写入/创建 */ ifx_lo_stat_refcnt(); /* smart LO的引用数 */ ifx_lo_stat_size(); /* smart LO的字节大小 */ /* 修改 smart LO列 */ 使用 ALTER TABLE 的 PUT 子句更改CLOB列或BLOB列的保管定位和特性。 你可以改变列存储的sbspace, /* * * * * * * * * 这里看不懂。可参照demo/esqlc目录下的 create_clob.ec get_lo_info.ec * upd_lo_descr.ec 了解。 */ /* 迁移 simple LO 到 smart LO */ update catalog set advert = ROW ((SELECT cat_picture::blob FROM stores7:catalog WHERE catalog_num = 10027), pwd advert.caption) WHERE catalog_num = 10027; ALTER TABLE catalog modify cat_descr CLOB, PUT cat_descr in (sbspc);
IBM Informix ESQL/C Programmers Manual读书笔记(四)
smart large object最大值吃4TB数据,可以设定指定的部份进行读写操作。 simple在ESQL/C中的数据类型为loc_t,不可以直接INSERT INTO一个simple large object,需要使用LOAD语句或者loc_t宿主变量类型。 loc_t并不包含真正的数据,只是一个定位结构体。推荐:在使用它之前初始化数据, 如下: EXEC SQL include locator; byfill(&blob1, sizeof(loc_t), 0); where blob1 is declared as EXEC SQL BEGIN DECLARE SECTION; loc_t blob1; EXEC SQL END DECLARE SECTION; /* Locators are used to store TEXT or BYTE fields (blobs) in ESQL programs. If "loc_loctype" is set to LOCMEMORY, then the blob is stored in primary memory. The memory buffer is pointed to by the variant "loc_buffer". The field "loc_bufsize" gives the size of "loc_buffer". 如果设定为正值,ESQL/C假设程序自己分配内存缓冲区并析构。 如果loc_bufsize设定为-1, 且loc_mflags为0,ESQL/C程序会分配内存以存放 simple-large-object数据。如果分配内存失败,设定"loc_status"字段为-465以指示错 误。 select或者第一次fetch成功后,ESQL/C设定"loc_buffer","loc_bufsize","loc_size"为合适的值。 如果随后要fetch的simple-large-objects过大或过小,要设定loc_mflags为 LOC_ALLOC 常量。使ESQL/C重新分配一个新的内存缓冲区。如果新fetch的数据增大,ESQL/C释放掉 现在的缓冲区并分配相近的缓冲区,重新设定loc_buffer,loc_bufsize和loc_size。 If "loc_loctype" is set to LOCFILE, then the blob is stored in a file. The file descriptor of an open operating system file is specified in "loc_fd". If "loc_loctype" is set to LOCFNAME, the the blob is stored in a file and the name of the file is given. The DBMS will open or create the file at the correct time and in the correct mode. If the "loc_loctype" is set to LOCUSER, "loc_(open/close/read/write)" are called. If the blob is an input to a SQL statement, "loc_open" is called with the parameter "LOC_RONLY". If the blob is an output target for an SQL statement, "loc_open" is called with the parameter "LOC_WONLY". "loc_size" specifies the maximum number of bytes to use when the locator is an input target to an SQL statement. It specifies the number of bytes returned if the locator is an output target. If "loc_loctype" is LOCFILE or LOCUSER, it can be set to -1 to indicate transfer until end-of-file. "loc_indicator" is set by the user to -1 to indicate a NULL blob. It will be set to -1 if a NULL blob is retrieved. If the blob to be retrieved will not fit in the space provided, the indicator contains the size of the blob. "loc_status" is the status return of locator operations. "loc_type" is the "blob" type (SQLTEXT, SQLBYTES, ...). "loc_user_env" is a pointer for the user's private use. It is neither set nor examined by the system. "loc_user_env" as well as the "loc_union" fieds may be used by user supplied routines to store and communicate information. */ typedef struct tag_loc_t { int2 loc_loctype; /* USER: type of locator - see below */ union /* variant on 'loc' */ { struct /* case LOCMEMORY */ { int4 lc_bufsize; /* USER: buffer size */ char *lc_buffer; /* USER: memory buffer to use */ char *lc_currdata_p;/* INTERNAL: current memory buffer,不能被ESQL/C修改*/ mint lc_mflags; /* USER/INTERNAL: memory flags */ /* (see below) */ } lc_mem; struct /* cases L0CFNAME & LOCFILE */ { char *lc_fname; /* USER: file name */ mint lc_mode; /* USER: perm. bits used if creating */ mint lc_fd; /* USER: os file descriptior */ int4 lc_position; /* INTERNAL: seek position */ } lc_file; } lc_union; int4 loc_indicator; /* USER SYSTEM: indicator */ int4 loc_type; /* USER SYSTEM: type of blob */ int4 loc_size; /* USER SYSTEM: num bytes in blob or -1 */ mint loc_status; /* SYSTEM: status return of locator ops */ char *loc_user_env; /* USER: for the user's PRIVATE use */ int4 loc_xfercount; /* INTERNAL/SYSTEM: Transfer count */ mint (*loc_open)(struct tag_loc_t *loc, mint flag, mint bsize); /*成功返回0,否 则返回-1,loc_status(SQLCODE)设为-452 */ mint (*loc_close)(struct tag_loc_t *loc);/*失败的话返回 -1,sql_status(SQLCODE)设为 -453*/ mint (*loc_read)(struct tag_loc_t *loc, char *buffer, mint buflen); (SQLCODE-454) mint (*loc_write)(struct tag_loc_t *loc, char *buffer, mint buflen);-455 mint loc_oflags; /* USER/INTERNAL: see flag definitions below */ } ifx_loc_t; #define loc_fname lc_union.lc_file.lc_fname #define loc_fd lc_union.lc_file.lc_fd #define loc_position lc_union.lc_file.lc_position #define loc_bufsize lc_union.lc_mem.lc_bufsize #define loc_buffer lc_union.lc_mem.lc_buffer #define loc_currdata_p lc_union.lc_mem.lc_currdata_p #define loc_mflags lc_union.lc_mem.lc_mflags /* loc_oflags选项 */ #define LOC_RONLY 0x1 /* read only */ #define LOC_WONLY 0x2 /* write only */ #define LOC_APPEND 0x4 /* write with append */ #define LOC_TEMPFILE 0x8 /* 4GL tempfile blob */ /* 所有这些参数都通过loc_open() 函数打开文件。如果ESQL/C读写文件失败,设定 * loc_status字段为-463或-464。如果不能关闭文件,设定loc_status字段为-462。 * SQLCODE值等同于此。*/ /* 在数据库表中的simple-large-objects列并不真正包含对象数据。只包含一个56字节 * 的simple-large-objects描述符,用以定位存储数据的第一段。这个描述符可以指向 * 一个dbspace blobpage,一个blobspace blobpage或者一个存储系统的一部份。 * * 当数据被保存在一张CD-R时,可以将loc_oflags字段设为LOC_DESCRIPTOR,只处理 * simple-large-objects描述符 */ /* 本章例子文件参看 $INFORMIX/demo/esqlc/目录下的getcd_me.ec 和 updcd_me.ec * dispcat_pic.ec文件 * 尤其要注意loc_indicator的指示NULL作用。 * */
IBM Informix ESQL/C Programmers Manual读书笔记(三)
/* 如果想用字符('F','T')对SQL BOOLEAN列赋值,则必须先定义FIXCHAR并赋其值。*/ EXEC SQL BEGIN DECLARE SECTION; boolean flag; fixchar my_boolflag; int id; EXEC SQL END DECLARE SECTION; id = 1; flag = ’\0’; /* valid boolean assignment to FALSE */ EXEC SQL insert into table2 values (:id, :flag); /* inserts FALSE */ my_boolflag = ’T’ /* valid character assignment to TRUE */ EXEC SQL insert into table2 values (:id, :my_boolflag); /* inserts TRUE*/ rsetnull(CBOOLTYPE, (char *) &flag); /* valid BOOLEAN assignment to NULL */ /* DECIMAL(p)浮点和DECIMAL(p,n)定点。后者是ANSI SQL标准。*/ #define DECSIZE 16 #define DECUNKNOWN -2 struct decimal { int2 dec_exp; /* exponent base 100 */ int2 dec_pos; /* sign: 1=正数, 0=负数, -1=null */ int2 dec_ndgts; /* number of significant digits */ char dec_dgts[DECSIZE]; /* actual digits base 100 */ }; typedef struct decimal dec_t; /* 存储最多32个有效位的浮点数。注意是BASE 100。每个dec_dgts[x]存储两位数。*/ /* Function Description */ decadd() Adds two decimal numbers B-15 deccmp() Compares two decimal numbers B-17 deccopy() Copies a decimal number B-18 decdiv() Divides two decimal numbers B-27 decmul() Multiplies two decimal numbers B-32 decround() Rounds a decimal number B-34 decsub() Subtracts two decimal numbers B-35 dectrunc() Truncates a decimal number B-43 deccvasc() Converts a C char type value to a decimal type value deccvdbl() Converts a C double type value to a decimal type value deccvint() Converts a C int type value to a decimal type value deccvlong() Converts a C 4-byte integer type value to a decimal type value dececvt() Converts a decimal value to an ASCII string B-28 decfcvt() Converts a decimal value to an ASCII string B-28 dectoasc() Converts a decimal type value to an ASCII string dectodbl() Converts a decimal type value to a C double type value dectoint() Converts a decimal type value to a C int type value dectolong() Converts a decimal type value to a C 4-byte integer type value /* 数字格式化显示 */ * 显示*号代替空格 & 用0填充空格占位 # 代表一个数字或空格的位置。 < 左调整。 , 默认显示,仅在左边有数字时显示,可以设置DBMONEY变量来更改显示字符。 . 一个数字模板只能显示一个. ,可设置DBMONEY环境变量更改显示。 - 数字是负的时候显示。 ---,-##.## 对应的-12.34 显示 bbbb-12.34。 + 显示正号。 ( ) 同上配对显示括号的负值。 $ 美元符号,可设值DBMONEY环境变量更改。 DBMONEY环境变量默认为"$,."。 rfmtdec() Converts a decimal value to a string B-181 rfmtdouble() Converts a double value to a string B-183 rfmtlong() Converts a 4-byte integer value to a string B-185 /* 日期格式化显示 */ ddd Sun through Sat mmm Jan through Dec rdatestr() Converts an internal DATE to a character string format B-171 rdayofweek() Returns the day of the week of a date in internal format B-172 rdefmtdate() Converts a specified string format to an internal DATE B-174 rfmtdate() Converts an internal DATE to a specified string format B-178 rjulmdy() Returns month, day, and year from a specified DATE B-193 rleapyear() Determines whether specified year is a leap year B-195 rmdyjul() Returns an internal DATE from month, day, and year B-196 rstrdate() Converts a character string format to an internal DATE B-204 rtoday() Returns a system date as an internal DATE B-205 EXEC SQL BEGIN DECLARE SECTION; DATETIME YEAR TO DAY sale; INTVAL HOUR TO SECOND test_num; EXEC SQL END DECLARE SECTION; /* 可以使用DBDATE和GL_DATE环境变量来定制服务器期望的DATE格式。 * 可以使用DBTIME和GL_DATETIME环境变量来定制服务器所期望的DATETIME格式。 */ 在头文件datetime.h中有定义了八个名字和五个宏,可以在操作DATETIME和INTERVAL 值时使用它们: TU_YEAR 用于year修饰符域的名字 TU_MONTH 用于month修饰符域的名字 TU_HOUR 用于hour修饰符域的名字 TU_DAY 用于day修饰符域的名字 TU_MINUTE 用于minute修饰符域的名字 TU_SECOND 用于second修饰符域的名字 TU_FRAC 用于开始的fraction修饰符域的名字 TU_Fn 用于结束的fraction(n)修饰符域的名字(n=1-5) TU_LEN(q) 返回修饰符q中的数字的位数。 TU_START(q) 从修饰符q返回开始单元。 TU_END(q) 从修饰符q返回结束单元。 TU_DTENCODE(s,e) 从开始单元s和结束单元e组合成DATETIME修饰符。 TU_IENCODE(p,s,e) 从带有精度p的开始单元s和结束单元e组合成INTERVAL修饰符。 当把DATETIME和INTERVAL数据库值存放到datetime和interval宿主变量时,在宿主变量的 定义时可以省略修饰符。同时,也不必初始化修饰符。在这种情形下,数据库服务器把 dt_qual或in_qual域初始化为与数据库中的定义同样的值。返回值是数据库中的值。 可以让数据库服务器自动把DATETIME和INTERVAL类型的数据库值转换成字符串。在把这些 值放到宿主变量:char、string或fixchar之前,会进行隐式的数据转换。 To explicitly convert a DATETIME value to a DATE value: 1. Use the dtextend() function to adjust the DATETIME qualifier to year to day. 2. Apply the dttoasc() function to create a character string in the form yyyy-mm-dd. 3. Use The rdefmtdate() function with a pattern argument of yyyy-mm-dd to convert the string to a DATE value. To explicitly convert a DATE value to a DATETIME value: 1. Declare a host variable with a qualifier of year to day (or initialize the qualifier with the value that the TU_DTENCODE(TU_YEAR,TU_DAY) macro returns). 2. Use the rfmtdate() function with a pattern of yyyy-mm-dd to convert the DATE value to a character string. 3. Use the dtcvasc() function to convert the character string to a value in the prepared DATETIME variable. 4. If necessary, use the dtextend() function to adjust the DATETIME qualifier. INTERVAL值遵循一下两组限定: 1,YEAR TO MONTH 2,DAY TO FRACTION 或者是两组集合中的子集。 Function Name Description dtaddinv() Adds an interval value to a datetime value B-45 dtcurrent() Gets the current date and time B-46 dtcvasc() Converts an ANSI-compliant character string to a datetime value dtcvfmtasc() Converts a character string with a specified format to a datetime value dtextend() Changes the qualifier of a datetime value B-52 dtsub() Subtracts one datetime value from another B-53 dtsubinv() Subtracts an interval value from a datetime value B-55 dttoasc() Converts a datetime value to an ANSI-compliant character string dttofmtasc() Converts a datetime value to a character string with a specified format incvasc() Converts an ANSI-compliant character string to an interval value incvfmtasc() Converts a character string with a specified format to an interval value intoasc() Converts an interval value to an ANSI-compliant character string intofmtasc() Converts an interval value to a character string with a specified format invdivdbl() Divides an interval value by a numeric value B-161 invdivinv() Divides an interval value by another interval value B-163 invextend() Extends an interval value to a different interval qualifier invmuldbl() Multiplies an interval value by a numeric value B-167
IBM Informix ESQL/C Programmers Manual读书笔记(二)
/* Informix数据类型常量,均定义在sqltypes.h文件中。 * 包括SQL数据类型常量。宿主C语言数据类型,例如 * double CDOUBLETYPE 105 * dec_t or decimal CDECIMALTYPE 107 * fixchar CFIXCHARTYPE 108 * string CSTRINGTYPE 109 * date CDATETYPE 110 * dec_t or decimal CMONEYTYPE 111 * datetime or dtime_t CDTIMETYPE 112 * ifx_loc_t or loc_t CLOCATORTYPE 113 */ /* 当两个数据的类型不一致时,Informix会自动转换他们的类型。 1,比较。例如 CHAR 邮编与 INT整型比对。 2,Fetch or insert 3,算数运算。 */ /* C TO N或 N TO C空间不足时,sqlca.sqlwarn.sqlwarn1值为W,且SQLSTATE值为 * 01004。 * BOOLEAN TO C时,BOOLEAN值'\01','\00'自动转换为FIXCHAR值 'T'或'F'。 * * 算术转换: * Operand Type Convert To * FLOAT DECIMAL(17) * SMALLFLOAT DECIMAL(9) * INTEGER DECIMAL(10,0) * SMALLINT DECIMAL(5,0) For example, for an arithmetic operation between a fixed-point decimal of DECIMAL(8,3) and a FLOAT value, Informix ESQL/C converts the FLOAT value to a floating-point decimal of DECIMAL(17). The arithmetic result has a data type of DECIMAL(17). Function Name Description See The risnull() Checks whether a C variable is null B-191 The rsetnull() Sets a C variable to null B-197 The rtypalign() Aligns data on correct type boundaries B-206 The rtypmsize() Gives the byte size of SQL data types B-209 The rtypname() Returns the name of a specified SQL data type B-211 The rtypwidth() Returns the minimum number of characters that a character data type needs to avoid truncation */ /* * This section describes the characteristics of these data types and the differences *among them. * Table 4-1. ESQL/C Character Data Types * ESQL/C Character Data Type Null Terminated Contains Trailing Blanks * char Y Y * fixchar N Y * string Y Returns a trailing blank only if the column contains an empty string. * varchar Y Y * lvarchar Y */ 你可以将带有\0结束符的C字符串放入FIXCHAR变量(空间要够大)。但这不是一个好主意 ,当数据库服务器将这个FIXCHAR放入列中时,终结符也被放入。 /* * When the IFX_PAD_VARCHAR environment variable is set to 1, the client sends * the VARCHAR data type with padded trailing spaces. When this environment is * not set (the default), the client sends the VARCHAR data type value without * trailing spaces. The IFX_PAD_VARCHAR environment variable must be set only at * the client side and is supported only with IBM Informix ESQL/C Version 9.53 and * 2.90 or later and IBM Informix Version 9.40 or later. * */ 如果你不指定lvarchar宿主变量的大小,它等同于一字节的char类型。 如果指定size,等同于C语言同等大小的CHAR类型。 如果lvarchar宿主变量是一个指针,指针指向的数据最大可以2GB。 lvarchar类型设计为当你insert和select用户自定义或不明类型时,可以表现为字符串格 式。必须使用 ifx_var() 函数操作lvarchar指针。 /* An application can fetch data from a database column of type CHAR or * VARCHAR into a character (char, string, fixchar, varchar, or lvarchar) host * variable. If the column data does not fit into the character host variable, * Informix ESQL/C truncates the data. To notify the user of the truncation, * Informix ESQL/C performs the following actions: It sets the * sqlca.sqlwarn.sqlwarn1 warning flag to W and the SQLSTATE variable to * 01004. It sets any indicator variable that is associated with the * character host variable to the size of the character data in the column. * * * Inserting CHAR Data An application can insert data from a character host * variable (char, string, fixchar, varchar, or lvarchar) into a database * column of type CHAR. If the value is shorter than the size of the database * column then the database server pads the value with blanks up to the size * of the column. If the value is longer than the size of the column the * database server truncates the value if the database is non-ANSI. No warning * is generated when this truncation occurs. If the database is ANSI and the * value is longer than the column size then the insert fails and this error * is returned: -1279: Value exceeds string column length. * */ /* 以by函数开头的函数操作和返回fixed-length字符串。 * 以rst和st(除了stchar)开头的函数,操作或返回终结符结尾的字符串。 * rdownshit和rupshit操作有终结符的字符串,但是不返回值。 */ Function Name Description bycmpr() Compares two groups of contiguous bytes B-10 bycopy() Copies bytes from one area to another B-12 byfill() Fills an area you specify with a character B-13 byleng() Counts the number of bytes in a string B-14 ldchar() Copies a fixed-length string to a null-terminated string B-170 rdownshift() Converts all letters to lowercase B-176 rstod() Converts a string to a double value B-200 rstoi() Converts a string to a short integer value B-201 rstol() Converts a string to a 4-byte integer value B-202 rupshift() Converts all letters to uppercase B-209 stcat() Concatenates one string to another B-232 stchar() Copies a null-terminated string to a fixed-length string B-233 stcmpr() Compares two strings B-234 stcopy() Copies one string to another string B-235 stleng() Counts the number of bytes in a string B-235