Error[8]: Undefined offset: 543, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

Pro*C入门手册+语法详解 概述

嵌入式 SQL 是一种结合 C/C++ 等高级语言的计算能力和 SQL 的数据库 *** 作能力的方法。


它允许您从应用程序执行任何 SQL 语句。


Oracle 的嵌入式 SQL 环境称为 ProC。



Pro
C 程序分两步编译。


首先,Pro*C预编译器 识别程序中嵌入的 SQL 语句,并将它们替换为对 SQL 运行时库中函数的适当调用。


输出是纯 C/C++ 代码,所有纯 C/C++ 部分都完好无损。


然后,使用常规 C/C++ 编译器编译代码并生成可执行文件。


有关详细信息,请参阅演示程序部分。


Pro*C 语法 SQL

所有 SQL 语句都需要以EXEC SQL开头并以分号“ ; ”结尾。


您可以将 SQL 语句放置在 C/C++ 块中的任何位置,但限制是声明性语句不在可执行语句之后。


举个例子:

    {
        int a;
        /* ... */
        EXEC SQL SELECT salary INTO :a
                 FROM Employee
                 WHERE SSN=876543210;
        /* ... */
        printf("The salary is %d\n", a);
        /* ... */
    }
预处理器指令

与 ProC 一起使用的 C/C++ 预处理器指令是#include 和#if。


ProC 无法识别#define。


例如,以下代码无效:
应该仅仅是#define 定义的宏不能用于SQL语句。


#define THE_SSN 876543210
/* ... */
EXEC SQL SELECT salary INTO :a
         FROM Employee
         WHERE SSN = THE_SSN;    /* 无效的*/
声明标签

您可以将 C/C++ 标签与 SQL 连接起来,如下所示:

    EXEC SQL WHENEVER SQLERROR GOTO error_in_SQL;
    /* ... */
 error_in_SQL:
    /* 进行错误处理 */

我们将在稍后的错误处理部分讨论WHENEVER的含义。


宿主变量 基本

宿主变量是宿主程序与数据库之间通信的关键。


宿主变量表达式必须解析为左值 (即,它可以被赋值)。


您可以根据 C 语法声明宿主变量,就像声明常规 C 变量一样。


宿主变量声明可以放置在可以放置 C 变量声明的任何位置。


(C++ 用户需要使用声明部分;请参阅C++ 用户部分。


)可用于 Oracle 的 C 数据类型包括:

char
char[n]
int
short
long
float
double
VARCHAR[n] - 这是 Pro*C 预编译器识别的伪类型。


它用于表示空白填充的可变长度字符串。


Pro*C 预编译器会将其转换为具有 2 字节长度字段和n字节字符数组的结构。


您不能对宿主变量使用寄存器 存储类说明符。


宿主变量引用在 SQL 语句中必须以冒号“ : ”为前缀,但在 C 语句中不应以冒号为前缀。


通过宿主变量指定字符串文字时,必须省略单引号;Pro*C 理解您正在根据宿主变量的声明类型指定字符串。


C 函数调用和大多数指针算术表达式不能用作宿主变量引用,即使它们确实可以解析为左值。


以下代码说明了合法和非法的宿主变量引用:

int deptnos[3] = { 000, 111, 222 };
int get_deptno() { return deptnos[2]; }
int *get_deptnoptr() { return &(deptnos[2]); }
int main() {
    int x; char *y; int z;
    /* ... */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y, :z);         /* 合法的 */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x + 1,              /* 合法的: 引用 x */
               'Big Shot',          /* 合法的: 但不是真正的宿主变量 */
               :deptnos[2]);        /* 合法:数组元素很好 */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y,
               :(*(deptnos+2)));    /* 非法:尽管它有一个左值 */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y,
               :get_deptno());      /* 非法:不能函数调用 */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y,
               :(*get_depnoptr())); /* 非法:尽管它有一个左值 */
    /* ... */
}
指针

您可以使用常规 C 语法定义指针,并在嵌入式 SQL 语句中使用它们。


像往常一样,在它们前面加上一个冒号:

int *x;
/* ... */
EXEC SQL SELECT xyz INTO :x FROM ...;

此SELECT语句的结果将写入*x,而不是x。


(x的值为地址,*x为x的值(地址)对应的值;写入x指针地址对应的值,而不是指针地址)
和上面注意区分:C 函数调用和大多数指针算术表达式不能用作宿主变量引用;意思是指针可以作为宿主变量,但是不能将指针进行算术表达式后作为宿主变量引用。


结构体

结构体可以用作宿主变量,如下例所示:

    typedef struct {
        char name[21];    /* one greater than column length; for 'int' */
        ; SSN}
    ; Emp/* ... */
    ;
    Emp bigshot/* ... */
    emp
    EXEC SQL INSERT INTO ( ,ename) eSSNVALUES
        ( :)bigshot;int emp_number[50];
char name[50][11];
/* ... */
EXEC SQL INSERT INTO emp(emp_number, name)
    VALUES (:emp_number, :emp_name);

数组

宿主数组可以通过以下方式使用:

char name[50][11]

这将一次性插入所有 50 个元组。



数组只能是一维的。


示例short 似乎与该规则相矛盾。


然而,Pro*C 实际上认为name 是一维字符串数组,而不是二维字符数组。


您还可以拥有结构体数组。


使用数组存储查询结果时,如果宿主数组的大小(例如n)小于查询返回的实际元组数,则只有前n 个结果元组将输入宿主数组。


指示变量

指示变量本质上是附加到主变量的“ NULL flags”。


您可以将每个宿主变量与可选的指示变量相关联。


指示变量必须定义为 2 字节整数(使用类型short),并且在 SQL 语句中,必须以冒号为前缀;并紧跟其宿主变量。


或者,您可以在宿主变量和指示变量之间使用关键字 INDICATOR 。


这是一个例子:

    ; indicator_var:
    EXEC SQL SELECT xyz INTO :host_var.indicator_var
        FROM ..;/* ... */
    VALUES
    EXEC SQL INSERT INTO R
        (::host_var INDICATOR ,indicator_var. ..);

您可以在SELECT语句的INTO子句中 使用指示变量 来检测输出宿主变量中的NULL或截断值。


Oracle 可以分配给指示变量的值具有以下含义:

含义-1
0列值为NULL,因此宿主变量的值是不确定的。


-2Oracle 将完整的列值分配给宿主变量。


>0Oracle 将截断的列值分配给宿主变量。


指示变量返回的整数是列值的原始长度。


Oracle 将截断的列变量分配给宿主变量,但无法确定原始列值。


您还可以在INSERT或UPDATE 语句 的VALUES和SET 子句中使用指示变量,将是否是NULL分配给输入宿主变量。


您的程序可以分配给指示变量的值具有以下含义:

<
含义-1
Oracle 将为该列分配NULL,而忽略宿主变量的值。


>=0Oracle 会将宿主变量的值分配给该列。


数据类型等效

Oracle 识别两种数据类型:内部和外部。


内部数据类型指定 Oracle 如何在数据库表中存储列值。


外部数据类型指定用于在输入和输出宿主变量中存储值的格式。


在预编译时,为每个宿主变量分配一个默认的 Oracle 外部数据类型。


数据类型等效允许您覆盖此默认等效,并允许您控制 Oracle 解释输入数据和格式化输出数据的方式。



可以使用VAR语句在逐个变量的基础上进行等效。


语法是:

    EXEC SQL VAR <host_var> IS [type_name> ( <)length>] ;char emp_name[21];
EXEC SQL VAR emp_name IS STRING(21);

例如,假设您想从emp 表中选择name,然后将它们传递给需要 C 风格’\0’终止字符串的例程。


您不需要自己明确地用’\0’ 来终止name。


只需将宿主变量等同于STRING外部数据类型,如下所示:

<

emp表中ename列 的长度为 20 个字符,因此您分配emp_name 21 个字符以容纳’\0’ -终止符。


STRING是一种 Oracle 外部数据类型,专门设计用于与 C 样式字符串交互。


当您从ename列中选择一个值到emp_name时,Oracle 将自动为您终止该值。


您还可以使用TYPE语句将用户定义的数据类型等同于 Oracle 外部数据类型。


语法是:

EXEC SQL TYPE <user_type> IS [type_name> ( <)length>] [ ]REFERENCE;typedef

您可以将用户定义的类型声明为指针,可以显式声明为指向标量或结构的指针,也可以隐式声明为数组,然后在TYPE语句中使用此类型。


在这些情况下,您需要在语句末尾使用REFERENCE子句,如下所示:

    unsigned char * ;my_rawVARRAW
    EXEC SQL TYPE my_raw IS (4000); REFERENCE;
    my_raw buffer/* ... */
    =
    buffer malloc (4004);char

作用:说明自定义类型my_raw这个类型等价于数据库的VARRAW(4000)这个外部类型
这里我们分配了比类型长度(4000)更多的内存,因为预编译器也会返回长度,并且可能会在长度之后添加填充以满足您系统上的对齐要求。


总结:EXEC SQL VAR 是将宿主变量等同于数据库的外部变量类型 (当等同于STRING时,会自动以\0结束,注意宿主变量长度要多1,且数据库外部变量的类型指定的长度也要多1)
EXEC SQL TYPE 是将用户自定义的类型等同于数据库的外部变量的类型。


(当定义一个字符指针类型char * 的变量时,可以等同于对应长度的VARRAW的数据库外部变量类型,注意宿主指针的空间要稍大于外部变量的长度)

动态 SQL

虽然嵌入式 SQL 适用于固定应用程序,但有时对于程序来说动态创建整个 SQL 语句很重要。


使用动态 SQL,可以发布存储在字符串变量中的语句。


PREPARE 将字符串转换为 SQL 语句,然后 EXECUTE执行该语句。


考虑以下示例。


    * =s "INSERT INTO emp VALUES(1234, 'jon', 3)" ;:
    EXEC SQL PREPARE q FROM ;s;
    EXEC SQL EXECUTE qchar
或者,PREPARE和EXECUTE可以组合成一个语句:
    * =s "INSERT INTO emp VALUES(1234, 'jon', 3)" ;:
    EXEC SQL EXECUTE IMMEDIATE ;s.
本来执行插入数据语句是:EXEC SQL INSERT INTO  emp ....
但是我们可以通过动态sql来将“insert into ..#”这些关键字存放在变量中,然后通过prepare和execute来完成sql的翻译和执行。


事务

Oracle PRO*C 支持 SQL 标准定义的事务。


事务是 Oracle 将其视为单个工作单元的 SQL 语句序列。


事务从您的第一个 SQL 语句开始。


当您发出“ EXEC SQL COMMIT ”(在当前事务期间永久更改任何数据库)或“ EXEC SQL ROLLBACK ”(撤消自当前事务开始以来的任何更改)时,事务结束。


在当前事务以您的 COMMIT或ROLLBACK语句结束后,下一个可执行 SQL 语句将自动开始一个新事务。



如果您的程序在没有调用EXEC SQL COMMIT的情况下退出,则所有数据库更改都将被丢弃。


EXEC SQL COMMIT; 和EXEC SQL COMMIT RELEASE;区别(ROLLBACK同理):

在Pro*C中 EXEC SQL COMMIT; 会提交事务并释放所有的锁定及其资源,而EXEC SQL COMMIT RELEASE会提交事务并释放所有的锁定及其资源
然后断开与数据库的连接,以后所有的与数据库 *** 作的命令都会报ORA-01012错误,除非重新连接数据库。


错误处理

错误处理在每个可执行的 SQL 语句之后,您的程序可以通过显式检查 SQLCA 或通过使用 WHENEVER 语句的隐式检查来找到执行状态。


下面将详细介绍这两种方式。


SQLCA

SQLCA (SQL Communications Area) 用于检测程序中的错误和状态变化。


此结构包含由 Oracle 在运行时在每个可执行 SQL 语句之后填充的组件。



要使用 SQLCA,您需要使用#include指令包含头文件sqlca.h 。


如果您需要在许多地方包含sqlca.h ,您需要首先使用 #undef SQLCA 取消定义宏SQLCA 。


(因为sqlca.h中有SQLCA宏的判断)sqlca.h的相关块如下:

ifndefSQLCA #
defineSQLCA 1 struct

sqlca /* ub1 */ {
    char [ sqlcaid8];/* b4 */
    long ; sqlabc/* b4 */
    long ; sqlcodestruct
    /* ub2 */ {
        unsigned short ; sqlerrml/* ub1 */
        char [ sqlerrmc70];}
    ; sqlerrm/* ub1 */
    char [ sqlerrp8];/* b4 */
    long [ sqlerrd6];/* ub1 */
    char [ sqlwarn8];/* ub1 */
    char [ sqlext8];}
;/* ... */
void

sqlca中 的字段含义如下:


SQLCA 在其sqlerrm组件中只能容纳最多 70 个字符的错误消息。



要获取较长(或嵌套)错误消息的全文,您需要sqlglm()函数:

sqlglm (char* ,msg_bufsize_t * ,buf_sizesize_t * )msg_length;<

其中msg_buf是您希望 Oracle 存储错误消息的字符缓冲区;buf_size 以字节为单位指定msg_buf的大小;Oracle 将错误消息的实际长度存储在*msg_length中。


Oracle 错误消息的最大长度为 512 字节。


WHENEVER 语句

WHENEVER语句允许您进行自动错误检查和处理。


语法是:

   EXEC SQL WHENEVER <condition> ;action>

Oracle 自动检查 SQLCA 的,如果检测到这样的条件,您的程序将自动执行。


可以是以下任何一种:

含义SQLWARNING
-设置sqlwarn[0],因为 Oracle 返回了一个警告SQLERROR
- sqlcode为负,因为 Oracle 返回了错误NOT FOUND
- sqlcode为正,因为 Oracle 找不到满足WHERE条件的行,或者SELECT INTO或FETCH未返回任何

可以是以下任何一种:

print_warning_msg
含义CONTINUE
- 如果可能,程序将尝试继续运行下一条语句DO
- 程序将控制权转移到错误处理函数- 程序分支到带标签的语句
GOTO STOP
- 程序通过exit()调用退出,未提交的工作被回滚

WHENEVER语句 的一些示例:

EXEC SQL WHENEVER SQLWARNING DO ();sql_error
EXEC SQL WHENEVER SQLERROR DO ();;
EXEC SQL WHENEVER NOT FOUND GOTO handle_empty/* code to find student name given id */

这是一个更具体的例子:

/* ... */
for
( ;;)printf {
    ("Give student id number : ");scanf
    ("%d",& )id;;
    EXEC SQL WHENEVER NOT FOUND GOTO notfound:
    EXEC SQL SELECT studentname INTO =st_name
             FROM   student
             WHERE  studentid : ;idprintf
    ("Name of student is %s.\n",) st_name;continue
    ;:
notfoundprintf
    ("No record exists for id %d!\n",) id;}
/* ... */
break

请注意,WHENEVER 语句不遵循常规的 C 范围规则。


范围对整个程序有效。


例如,如果您在程序的某处(例如循环之前)有以下语句:

EXEC SQL WHENEVER NOT FOUND DO ;;

文件中此行之后出现的所有 SQL语句 都会受到影响。


确保在不再需要时(例如在循环之后)使用以下行来取消 WHENEVER 的效果:

EXEC SQL WHENEVER NOT FOUND CONTINUE/*先前设定的是NOT FOUND DO break;所以现在取消是NOT FOUND CONTINUE; SQLWARNING同理取消是SQLWARNING CONTINUE;*/
#将嵌入式 SQL 代码转换为相应的库调用并输出 sample1.c
编译
iname
proc =onamesample1.pc =#生成可执行sample1sample1.c
<
cc CODE=CPPa_number_of_flags_here> sample1.c
C++ 用户

要让预编译器生成适当的 C++ 代码,您需要注意以下问题:
预编译器的代码处理。


要获取 C++ 代码,您需要 在执行proc时设置选项;


C 用户不必担心这个选项;默认满足他们的需求。



解析能力。


proc的PARSE选项可以采用以下值:
PARSE=NONE。


C 预处理器指令只能在声明部分中理解,并且所有宿主变量都需要在声明部分中声明。



PARSE=PARTIAL。


理解 C 预处理器指令;但是,所有宿主变量都需要在声明部分中声明。



PARSE=FULL。


可以理解 C 预处理器指令,并且可以在任何地方声明宿主变量。


当CODE 不是CPP时,这是默认设置; 使用CODE=CPP指定PARSE=FULL是错误的。



因此,C++ 用户必须指定PARSE=NONE或PARSE=PARTIAL。


因此,他们失去了在代码中任意位置声明主变量的自由。


相反,宿主变量必须封装在声明部分 中,如下所示:

EXEC SQL BEGIN DECLARE SECTION// declarations...
    ;
EXEC SQL END DECLARE SECTIONSYS_INCLUDE选项来指定proc

您需要遵循此例程在您这样做的所有地方声明宿主和指示变量。



文件扩展名。


您需要指定选项CPP_SUFFIX=cc或 CPP_SUFFIX=C。



头文件的位置。


默认情况下,proc在标准位置搜索诸如stdio.h 之类的头文件。


但是,C++ 有自己的头文件,例如iostream.h,位于其他位置。


所以你需要使用声明性语法 应该搜索头文件的路径。


Pro*C 支持的嵌入式 SQL 语句列表
说明EXEC SQL ARRAYLEN
在 PL/SQL 中使用宿主数组EXEC SQL BEGIN DECLARE SECTION
开始声明宿主变量EXEC SQL END DECLARE SECTION
结束声明宿主变量EXEC SQL DECLARE
命名 Oracle 对象EXEC SQL INCLUDE
包含头文件(复制文件)EXEC SQL TYPE
指定用户自定义数据类型等价数据库外部数据类型EXEC SQL VAR
指定用户定义的变量(应该是变量所属的类型)等价数据库外部数据类型EXEC SQL WHENEVER
处理运行时错误可执行性语句
[+++]
说明EXEC SQL ALLOCATE
分配EXEC SQL ALTER
修改表EXEC SQL ANALYZE
定义和控制 Oracle 数据EXEC SQL AUDIT
定义和控制 Oracle 数据EXEC SQL COMMENT
注释EXEC SQL CONNECT
连接数据库EXEC SQL CREATE
创建表EXEC SQL DROP
删表EXEC SQL GRANT
授权EXEC SQL NOAUDIT
EXEC SQL RENAME
重命名EXEC SQL REVOKE
撤销EXEC SQL TRUNCATE
清空表或者说是截断表(与drop有点不同处)EXEC SQL CLOSE
关闭EXEC SQL DELETE
删除数据EXEC SQL EXPLAIN PLAN
解释计划EXEC SQL FETCH
提取EXEC SQL INSERT
插入数据EXEC SQL LOCK TABLE
锁定表EXEC SQL OPEN
打开EXEC SQL SELECT
查询数据EXEC SQL UPDATE
更新数据EXEC SQL COMMIT
提交事务EXEC SQL ROLLBACK
回滚EXEC SQL SAVEPOINT
保存点EXEC SQL SET TRANSACTION
设置事务EXEC SQL DESCRIBE
动态 SQL描述EXEC SQL EXECUTE
动态SQL的执行EXEC SQL PREPARE
动态SQL的准备EXEC SQL ALTER SESSION
更改会话EXEC SQL SET ROLE
设置角色EXEC SQL EXECUTE
嵌入式PL/SQL块执行END-EXEC
嵌入式PL/SQL块 结束

附上:Proc*C开发示例

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Pro*C入门手册+语法详解_C_内存溢出

Pro*C入门手册+语法详解

Pro*C入门手册+语法详解,第1张

Pro*C入门手册+语法详解 概述

嵌入式 SQL 是一种结合 C/C++ 等高级语言的计算能力和 SQL 的数据库 *** 作能力的方法。


它允许您从应用程序执行任何 SQL 语句。


Oracle 的嵌入式 SQL 环境称为 ProC。



Pro
C 程序分两步编译。


首先,Pro*C预编译器 识别程序中嵌入的 SQL 语句,并将它们替换为对 SQL 运行时库中函数的适当调用。


输出是纯 C/C++ 代码,所有纯 C/C++ 部分都完好无损。


然后,使用常规 C/C++ 编译器编译代码并生成可执行文件。


有关详细信息,请参阅演示程序部分。


Pro*C 语法 SQL

所有 SQL 语句都需要以EXEC SQL开头并以分号“ ; ”结尾。


您可以将 SQL 语句放置在 C/C++ 块中的任何位置,但限制是声明性语句不在可执行语句之后。


举个例子:

    {
        int a;
        /* ... */
        EXEC SQL SELECT salary INTO :a
                 FROM Employee
                 WHERE SSN=876543210;
        /* ... */
        printf("The salary is %d\n", a);
        /* ... */
    }
预处理器指令

与 ProC 一起使用的 C/C++ 预处理器指令是#include 和#if。


ProC 无法识别#define。


例如,以下代码无效:
应该仅仅是#define 定义的宏不能用于SQL语句。


#define THE_SSN 876543210
/* ... */
EXEC SQL SELECT salary INTO :a
         FROM Employee
         WHERE SSN = THE_SSN;    /* 无效的*/
声明标签

您可以将 C/C++ 标签与 SQL 连接起来,如下所示:

    EXEC SQL WHENEVER SQLERROR GOTO error_in_SQL;
    /* ... */
 error_in_SQL:
    /* 进行错误处理 */

我们将在稍后的错误处理部分讨论WHENEVER的含义。


宿主变量 基本

宿主变量是宿主程序与数据库之间通信的关键。


宿主变量表达式必须解析为左值 (即,它可以被赋值)。


您可以根据 C 语法声明宿主变量,就像声明常规 C 变量一样。


宿主变量声明可以放置在可以放置 C 变量声明的任何位置。


(C++ 用户需要使用声明部分;请参阅C++ 用户部分。


)可用于 Oracle 的 C 数据类型包括:

char
char[n]
int
short
long
float
double
VARCHAR[n] - 这是 Pro*C 预编译器识别的伪类型。


它用于表示空白填充的可变长度字符串。


Pro*C 预编译器会将其转换为具有 2 字节长度字段和n字节字符数组的结构。


您不能对宿主变量使用寄存器 存储类说明符。


宿主变量引用在 SQL 语句中必须以冒号“ : ”为前缀,但在 C 语句中不应以冒号为前缀。


通过宿主变量指定字符串文字时,必须省略单引号;Pro*C 理解您正在根据宿主变量的声明类型指定字符串。


C 函数调用和大多数指针算术表达式不能用作宿主变量引用,即使它们确实可以解析为左值。


以下代码说明了合法和非法的宿主变量引用:

int deptnos[3] = { 000, 111, 222 };
int get_deptno() { return deptnos[2]; }
int *get_deptnoptr() { return &(deptnos[2]); }
int main() {
    int x; char *y; int z;
    /* ... */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y, :z);         /* 合法的 */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x + 1,              /* 合法的: 引用 x */
               'Big Shot',          /* 合法的: 但不是真正的宿主变量 */
               :deptnos[2]);        /* 合法:数组元素很好 */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y,
               :(*(deptnos+2)));    /* 非法:尽管它有一个左值 */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y,
               :get_deptno());      /* 非法:不能函数调用 */
    EXEC SQL INSERT INTO emp(empno, ename, deptno)
        VALUES(:x, :y,
               :(*get_depnoptr())); /* 非法:尽管它有一个左值 */
    /* ... */
}
指针

您可以使用常规 C 语法定义指针,并在嵌入式 SQL 语句中使用它们。


像往常一样,在它们前面加上一个冒号:

int *x;
/* ... */
EXEC SQL SELECT xyz INTO :x FROM ...;

此SELECT语句的结果将写入*x,而不是x。


(x的值为地址,*x为x的值(地址)对应的值;写入x指针地址对应的值,而不是指针地址)
和上面注意区分:C 函数调用和大多数指针算术表达式不能用作宿主变量引用;意思是指针可以作为宿主变量,但是不能将指针进行算术表达式后作为宿主变量引用。


结构体

结构体可以用作宿主变量,如下例所示:

    typedef struct {
        char name[21];    /* one greater than column length; for 'int' */
        ; SSN}
    ; Emp/* ... */
    ;
    Emp bigshot/* ... */
    emp
    EXEC SQL INSERT INTO ( ,ename) eSSNVALUES
        ( :)bigshot;int emp_number[50];
char name[50][11];
/* ... */
EXEC SQL INSERT INTO emp(emp_number, name)
    VALUES (:emp_number, :emp_name);

数组

宿主数组可以通过以下方式使用:

char name[50][11]

这将一次性插入所有 50 个元组。



数组只能是一维的。


示例short 似乎与该规则相矛盾。


然而,Pro*C 实际上认为name 是一维字符串数组,而不是二维字符数组。


您还可以拥有结构体数组。


使用数组存储查询结果时,如果宿主数组的大小(例如n)小于查询返回的实际元组数,则只有前n 个结果元组将输入宿主数组。


指示变量

指示变量本质上是附加到主变量的“ NULL flags”。


您可以将每个宿主变量与可选的指示变量相关联。


指示变量必须定义为 2 字节整数(使用类型short),并且在 SQL 语句中,必须以冒号为前缀;并紧跟其宿主变量。


或者,您可以在宿主变量和指示变量之间使用关键字 INDICATOR 。


这是一个例子:

    ; indicator_var:
    EXEC SQL SELECT xyz INTO :host_var.indicator_var
        FROM ..;/* ... */
    VALUES
    EXEC SQL INSERT INTO R
        (::host_var INDICATOR ,indicator_var. ..);

您可以在SELECT语句的INTO子句中 使用指示变量 来检测输出宿主变量中的NULL或截断值。


Oracle 可以分配给指示变量的值具有以下含义:

含义-1
0列值为NULL,因此宿主变量的值是不确定的。


-2Oracle 将完整的列值分配给宿主变量。


>0Oracle 将截断的列值分配给宿主变量。


指示变量返回的整数是列值的原始长度。


Oracle 将截断的列变量分配给宿主变量,但无法确定原始列值。


您还可以在INSERT或UPDATE 语句 的VALUES和SET 子句中使用指示变量,将是否是NULL分配给输入宿主变量。


您的程序可以分配给指示变量的值具有以下含义:

<
含义-1
Oracle 将为该列分配NULL,而忽略宿主变量的值。


>=0Oracle 会将宿主变量的值分配给该列。


数据类型等效

Oracle 识别两种数据类型:内部和外部。


内部数据类型指定 Oracle 如何在数据库表中存储列值。


外部数据类型指定用于在输入和输出宿主变量中存储值的格式。


在预编译时,为每个宿主变量分配一个默认的 Oracle 外部数据类型。


数据类型等效允许您覆盖此默认等效,并允许您控制 Oracle 解释输入数据和格式化输出数据的方式。



可以使用VAR语句在逐个变量的基础上进行等效。


语法是:

    EXEC SQL VAR <host_var> IS [type_name> ( <)length>] ;char emp_name[21];
EXEC SQL VAR emp_name IS STRING(21);

例如,假设您想从emp 表中选择name,然后将它们传递给需要 C 风格’\0’终止字符串的例程。


您不需要自己明确地用’\0’ 来终止name。


只需将宿主变量等同于STRING外部数据类型,如下所示:

<

emp表中ename列 的长度为 20 个字符,因此您分配emp_name 21 个字符以容纳’\0’ -终止符。


STRING是一种 Oracle 外部数据类型,专门设计用于与 C 样式字符串交互。


当您从ename列中选择一个值到emp_name时,Oracle 将自动为您终止该值。


您还可以使用TYPE语句将用户定义的数据类型等同于 Oracle 外部数据类型。


语法是:

EXEC SQL TYPE <user_type> IS [type_name> ( <)length>] [ ]REFERENCE;typedef

您可以将用户定义的类型声明为指针,可以显式声明为指向标量或结构的指针,也可以隐式声明为数组,然后在TYPE语句中使用此类型。


在这些情况下,您需要在语句末尾使用REFERENCE子句,如下所示:

    unsigned char * ;my_rawVARRAW
    EXEC SQL TYPE my_raw IS (4000); REFERENCE;
    my_raw buffer/* ... */
    =
    buffer malloc (4004);char

作用:说明自定义类型my_raw这个类型等价于数据库的VARRAW(4000)这个外部类型
这里我们分配了比类型长度(4000)更多的内存,因为预编译器也会返回长度,并且可能会在长度之后添加填充以满足您系统上的对齐要求。


总结:EXEC SQL VAR 是将宿主变量等同于数据库的外部变量类型 (当等同于STRING时,会自动以\0结束,注意宿主变量长度要多1,且数据库外部变量的类型指定的长度也要多1)
EXEC SQL TYPE 是将用户自定义的类型等同于数据库的外部变量的类型。


(当定义一个字符指针类型char * 的变量时,可以等同于对应长度的VARRAW的数据库外部变量类型,注意宿主指针的空间要稍大于外部变量的长度)

动态 SQL

虽然嵌入式 SQL 适用于固定应用程序,但有时对于程序来说动态创建整个 SQL 语句很重要。


使用动态 SQL,可以发布存储在字符串变量中的语句。


PREPARE 将字符串转换为 SQL 语句,然后 EXECUTE执行该语句。


考虑以下示例。


    * =s "INSERT INTO emp VALUES(1234, 'jon', 3)" ;:
    EXEC SQL PREPARE q FROM ;s;
    EXEC SQL EXECUTE qchar
或者,PREPARE和EXECUTE可以组合成一个语句:
    * =s "INSERT INTO emp VALUES(1234, 'jon', 3)" ;:
    EXEC SQL EXECUTE IMMEDIATE ;s.
本来执行插入数据语句是:EXEC SQL INSERT INTO  emp ....
但是我们可以通过动态sql来将“insert into ..#”这些关键字存放在变量中,然后通过prepare和execute来完成sql的翻译和执行。


事务

Oracle PRO*C 支持 SQL 标准定义的事务。


事务是 Oracle 将其视为单个工作单元的 SQL 语句序列。


事务从您的第一个 SQL 语句开始。


当您发出“ EXEC SQL COMMIT ”(在当前事务期间永久更改任何数据库)或“ EXEC SQL ROLLBACK ”(撤消自当前事务开始以来的任何更改)时,事务结束。


在当前事务以您的 COMMIT或ROLLBACK语句结束后,下一个可执行 SQL 语句将自动开始一个新事务。



如果您的程序在没有调用EXEC SQL COMMIT的情况下退出,则所有数据库更改都将被丢弃。


EXEC SQL COMMIT; 和EXEC SQL COMMIT RELEASE;区别(ROLLBACK同理):

在Pro*C中 EXEC SQL COMMIT; 会提交事务并释放所有的锁定及其资源,而EXEC SQL COMMIT RELEASE会提交事务并释放所有的锁定及其资源
然后断开与数据库的连接,以后所有的与数据库 *** 作的命令都会报ORA-01012错误,除非重新连接数据库。


错误处理

错误处理在每个可执行的 SQL 语句之后,您的程序可以通过显式检查 SQLCA 或通过使用 WHENEVER 语句的隐式检查来找到执行状态。


下面将详细介绍这两种方式。


SQLCA

SQLCA (SQL Communications Area) 用于检测程序中的错误和状态变化。


此结构包含由 Oracle 在运行时在每个可执行 SQL 语句之后填充的组件。



要使用 SQLCA,您需要使用#include指令包含头文件sqlca.h 。


如果您需要在许多地方包含sqlca.h ,您需要首先使用 #undef SQLCA 取消定义宏SQLCA 。


(因为sqlca.h中有SQLCA宏的判断)sqlca.h的相关块如下:

ifndefSQLCA #
defineSQLCA 1 struct

sqlca /* ub1 */ {
    char [ sqlcaid8];/* b4 */
    long ; sqlabc/* b4 */
    long ; sqlcodestruct
    /* ub2 */ {
        unsigned short ; sqlerrml/* ub1 */
        char [ sqlerrmc70];}
    ; sqlerrm/* ub1 */
    char [ sqlerrp8];/* b4 */
    long [ sqlerrd6];/* ub1 */
    char [ sqlwarn8];/* ub1 */
    char [ sqlext8];}
;/* ... */
void

sqlca中 的字段含义如下:


SQLCA 在其sqlerrm组件中只能容纳最多 70 个字符的错误消息。



要获取较长(或嵌套)错误消息的全文,您需要sqlglm()函数:

sqlglm (char* ,msg_bufsize_t * ,buf_sizesize_t * )msg_length;<

其中msg_buf是您希望 Oracle 存储错误消息的字符缓冲区;buf_size 以字节为单位指定msg_buf的大小;Oracle 将错误消息的实际长度存储在*msg_length中。


Oracle 错误消息的最大长度为 512 字节。


WHENEVER 语句

WHENEVER语句允许您进行自动错误检查和处理。


语法是:

   EXEC SQL WHENEVER <condition> ;action>

Oracle 自动检查 SQLCA 的,如果检测到这样的条件,您的程序将自动执行。


可以是以下任何一种:

含义SQLWARNING
-设置sqlwarn[0],因为 Oracle 返回了一个警告SQLERROR
- sqlcode为负,因为 Oracle 返回了错误NOT FOUND
- sqlcode为正,因为 Oracle 找不到满足WHERE条件的行,或者SELECT INTO或FETCH未返回任何

可以是以下任何一种:

print_warning_msg
含义CONTINUE
- 如果可能,程序将尝试继续运行下一条语句DO
- 程序将控制权转移到错误处理函数- 程序分支到带标签的语句
GOTO STOP
- 程序通过exit()调用退出,未提交的工作被回滚

WHENEVER语句 的一些示例:

EXEC SQL WHENEVER SQLWARNING DO ();sql_error
EXEC SQL WHENEVER SQLERROR DO ();;
EXEC SQL WHENEVER NOT FOUND GOTO handle_empty/* code to find student name given id */

这是一个更具体的例子:

/* ... */
for
( ;;)printf {
    ("Give student id number : ");scanf
    ("%d",& )id;;
    EXEC SQL WHENEVER NOT FOUND GOTO notfound:
    EXEC SQL SELECT studentname INTO =st_name
             FROM   student
             WHERE  studentid : ;idprintf
    ("Name of student is %s.\n",) st_name;continue
    ;:
notfoundprintf
    ("No record exists for id %d!\n",) id;}
/* ... */
break

请注意,WHENEVER 语句不遵循常规的 C 范围规则。


范围对整个程序有效。


例如,如果您在程序的某处(例如循环之前)有以下语句:

EXEC SQL WHENEVER NOT FOUND DO ;;

文件中此行之后出现的所有 SQL语句 都会受到影响。


确保在不再需要时(例如在循环之后)使用以下行来取消 WHENEVER 的效果:

EXEC SQL WHENEVER NOT FOUND CONTINUE/*先前设定的是NOT FOUND DO break;所以现在取消是NOT FOUND CONTINUE; SQLWARNING同理取消是SQLWARNING CONTINUE;*/
#将嵌入式 SQL 代码转换为相应的库调用并输出 sample1.c
编译
iname
proc =onamesample1.pc =#生成可执行sample1sample1.c
<
cc CODE=CPPa_number_of_flags_here> sample1.c
C++ 用户

要让预编译器生成适当的 C++ 代码,您需要注意以下问题:
预编译器的代码处理。


要获取 C++ 代码,您需要 在执行proc时设置选项;


C 用户不必担心这个选项;默认满足他们的需求。



解析能力。


proc的PARSE选项可以采用以下值:
PARSE=NONE。


C 预处理器指令只能在声明部分中理解,并且所有宿主变量都需要在声明部分中声明。



PARSE=PARTIAL。


理解 C 预处理器指令;但是,所有宿主变量都需要在声明部分中声明。



PARSE=FULL。


可以理解 C 预处理器指令,并且可以在任何地方声明宿主变量。


当CODE 不是CPP时,这是默认设置; 使用CODE=CPP指定PARSE=FULL是错误的。



因此,C++ 用户必须指定PARSE=NONE或PARSE=PARTIAL。


因此,他们失去了在代码中任意位置声明主变量的自由。


相反,宿主变量必须封装在声明部分 中,如下所示:

EXEC SQL BEGIN DECLARE SECTION// declarations...
    ;
EXEC SQL END DECLARE SECTIONSYS_INCLUDE选项来指定proc

您需要遵循此例程在您这样做的所有地方声明宿主和指示变量。



文件扩展名。


您需要指定选项CPP_SUFFIX=cc或 CPP_SUFFIX=C。



头文件的位置。


默认情况下,proc在标准位置搜索诸如stdio.h 之类的头文件。


但是,C++ 有自己的头文件,例如iostream.h,位于其他位置。


所以你需要使用声明性语法 应该搜索头文件的路径。


Pro*C 支持的嵌入式 SQL 语句列表
说明EXEC SQL ARRAYLEN
在 PL/SQL 中使用宿主数组EXEC SQL BEGIN DECLARE SECTION
开始声明宿主变量EXEC SQL END DECLARE SECTION
结束声明宿主变量EXEC SQL DECLARE
命名 Oracle 对象EXEC SQL INCLUDE
包含头文件(复制文件)EXEC SQL TYPE
指定用户自定义数据类型等价数据库外部数据类型EXEC SQL VAR
指定用户定义的变量(应该是变量所属的类型)等价数据库外部数据类型EXEC SQL WHENEVER
处理运行时错误可执行性语句
说明EXEC SQL ALLOCATE
分配EXEC SQL ALTER
修改表EXEC SQL ANALYZE
定义和控制 Oracle 数据EXEC SQL AUDIT
定义和控制 Oracle 数据EXEC SQL COMMENT
注释EXEC SQL CONNECT
连接数据库EXEC SQL CREATE
创建表EXEC SQL DROP
删表EXEC SQL GRANT
授权EXEC SQL NOAUDIT
EXEC SQL RENAME
重命名EXEC SQL REVOKE
撤销EXEC SQL TRUNCATE
清空表或者说是截断表(与drop有点不同处)EXEC SQL CLOSE
关闭EXEC SQL DELETE
删除数据EXEC SQL EXPLAIN PLAN
解释计划EXEC SQL FETCH
提取EXEC SQL INSERT
插入数据EXEC SQL LOCK TABLE
锁定表EXEC SQL OPEN
打开EXEC SQL SELECT
查询数据EXEC SQL UPDATE
更新数据EXEC SQL COMMIT
提交事务EXEC SQL ROLLBACK
回滚EXEC SQL SAVEPOINT
保存点EXEC SQL SET TRANSACTION
设置事务EXEC SQL DESCRIBE
动态 SQL描述EXEC SQL EXECUTE
动态SQL的执行EXEC SQL PREPARE
动态SQL的准备EXEC SQL ALTER SESSION
更改会话EXEC SQL SET ROLE
设置角色EXEC SQL EXECUTE
嵌入式PL/SQL块执行END-EXEC
嵌入式PL/SQL块 结束

附上:Proc*C开发示例

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/564252.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-03
下一篇 2022-04-03

发表评论

登录后才能评论

评论列表(0条)

保存