`

ESQL/C资料(完全版)三

阅读更多

第四节 ORACLE数据库的嵌入SQL语言
   4.1 基本的SQL语句
   4.1.1宿主变量和指示符
   1)、声明方法
   同其他数据库管理器一样,ORACLE使用宿主变量传递数据库中的数据和状态信息到应用程序, 应用程序也通过宿主变量传递数据到ORACLE数据库。根据上面两种功能,宿主变量分为输出宿主变量和输入宿主变量。在SELECT INTO和FETCH语句之后的宿主变量称作“输出宿主变量”,这是因为从数据库传递列数据到应用程序。除了SELECT INTO和FETCH语句外的其他SQL语句中的宿主变量,称为“输入宿主变量”。这是因为从应用程序向数据库输入值。如:INSERT、UPDATE等 语句。请看下面这个例子:
   int emp_number;
   char temp[20];
   VARCHAR emp_name[20];
   /* get values for input host variables */
   printf("Employee number? ");
   gets(temp);
   emp_number = atoi(temp);
   printf("Employee name? ");
   gets(emp_name.arr);
   emp_name.len = strlen(emp_name.arr);
   EXEC SQL INSERT INTO EMP (EMPNO, ENAME)
   VALUES (:emp_number, :emp_name);
   在上面这个例子中,其中的emp_number和emp_name就是宿主变量。值得注意的是,它同其他数据库的区别是,定义宿主变量可以不需要BEGIN DECLARE SECTION和END DECLARE SECTION。
   2)、指示符变量
   大多数程序设计语言(如C)都不支持NULL。所以对NULL的处理,一定要在SQL中完成。我们可以使用主机指示符变量来解决这个问题。在嵌入式SQL语句中,主变量和指示符变量共同规定一个单独的SQL类型值。指示符变量是一个2字节的整数。
   针对输入宿主变量和输出宿主变量,指示变量共有下面几种情况:
   同输入宿主变量一起使用时:
   -1 Oracle将null赋值给列,即宿主变量应该假设为NULL。
   >=0 Oracle将宿主变量的实际值赋值给列。
   同输出宿主变量一起使用时:
   -1 表示该列的输出值为NULL。
   0 Oracle已经将列的值赋给了宿主变量。列值未做截断。
  >0 Oracle将列的值截断,并赋给了宿主变量。指示变量中存放了这个列的实际长度。
   -2 Oracle将列的值截断,并赋给了宿主变量。但是这个列的实际长度不能确定。
   从数据库中查询数据时,可以使用指示符变量来测试NULL:
   EXEC SQL SELECT ename, sal
   INTO :emp_name, :salary
   FROM emp
   WHERE :commission INDICATOR :ind_comm IS NULL ...
   注意,不能使用关系操作符来比较NULL,这是因为NULL和任何操作都为false。如:
   EXEC SQL SELECT ename, sal
   INTO :emp_name, :salary
   FROM emp
   WHERE comm = :commission
   如果comm列的某些行存在NULL,则该SELECT语句不能返回正确的结果。应该使用下面这个语句完成:
   EXEC SQL SELECT ename, sal
   INTO :emp_name, :salary
   FROM emp
   WHERE (comm = :commission) OR ((comm IS NULL) AND
   (:commission INDICATOR :ind_comm IS NULL));
   4.1.2 查询
   如果是单行查询,则应该使用SELECT INTO语句。如果是多行查询,应该使用游标或宿主变量数组。如:单行查询的一个例子:
   EXEC SQL SELECT ename, job, sal + 2000
   INTO :emp_name, :job_title, :salary
   FROM emp
   WHERE empno = :emp_number;
   在嵌入SQL语句中,也可以使用子查询。如:
   EXEC SQL INSERT INTO emp2 (empno, ename, sal, deptno)
   SELECT empno, ename, sal, deptno FROM emp
   WHERE job = :job_title;
   4.1.3 修改数据
   1)、插入数据
   使用INSERT语句插入数据。其语法同ANSI SQL语法类似。如:
   EXEC SQL INSERT INTO emp (empno, ename, sal, deptno)
   VALUES (:emp_number, :emp_name, :salary, :dept_number);
   2)、更新数据
   使用UPDATE语句更新数据。其语法同ANSI SQL语法类似。如:
   EXEC SQL UPDATE emp
   SET sal = :salary, comm = :commission
   WHERE empno = :emp_number;
   3)、删除数据
   使用DELETE语句删除数据。其语法同ANSI SQL语法类似。如:
   EXEC SQL DELETE FROM emp
   WHERE deptno = :dept_number;
   4.1.4 游标
   用嵌入式SQL语句查询数据分成两类情况。一类是单行结果,一类是多行结果。对于单行结果,可以使用SELECT INTO语句;对于多行结果,你必须使用游标来完成。游标是一个与SELECT语句相关联的符号名,它使用户可逐行访问由ORACLE返回的结果集。使用游标,应该包含以下四个步骤。
   1)、定义游标
   使用DECLARE语句完成。如:
   EXEC SQL DECLARE emp_cursor CURSOR FOR
   SELECT ename FROM emp WHERE deptno = :dept_number;
   值得注意的是,不能在同一个文件中定义两个相同名字的游标。游标的作用范围是全局的。
   2)、打开游标
   使用OPEN语句完成。如:
   EXEC SQL OPEN emp_cursor;
   3)、取一行值
   使用FETCH语句完成。如:
   EXEC SQL FETCH emp_cursor INTO :emp_name;
   4)、关闭游标
   使用CLOSE语句完成。它完成的功能是:释放资源,如占用内存,锁等。如:EXEC SQL CLOSE emp_cursor;
   5)、使用游标修改数据
   我们可以使用CURRENT OF子句来完成修改数据。如:
   EXEC SQL DECLARE emp_cursor CURSOR FOR
   SELECT ename, sal FROM emp WHERE job = 'CLERK'
   FOR UPDATE OF sal;
   ...
   EXEC SQL OPEN emp_cursor;
   EXEC SQL WHENEVER NOT FOUND GOTO ...
   for (;;) {
   EXEC SQL FETCH emp_cursor INTO :emp_name, :salary;
   ...
   EXEC SQL UPDATE emp SET sal = :new_salary
   WHERE CURRENT OF emp_cursor;
   }
   值得注意的是,在使用CURRENT OF子句来完成修改数据时,在OPEN时会对数据加上排它锁。这个锁直到有COMMIT或ROLLBACK语句时才释放。
   以下是使用游标修改数据的一个完整例子:
   ...
   /* 定义游标 */
   EXEC SQL DECLARE emp_cursor CURSOR FOR
   SELECT ename, job
   FROM emp
   WHERE empno = :emp_number
   FOR UPDATE OF job;
   /* 打开游标 */
   EXEC SQL OPEN emp_cursor;
   /* break if the last row was already fetched */
   EXEC SQL WHENEVER NOT FOUND DO break;
   /* 循环取值*/
   for (;;)
   {
   EXEC SQL FETCH emp_cursor INTO :emp_name, :job_title;
   /* 更新当前游标所在的行的数据*/
   EXEC SQL UPDATE emp
   SET job = :new_job_title
   WHERE CURRENT OF emp_cursor;
   }
   ...
   /* 关闭游标 */
   EXEC SQL CLOSE emp_cursor;
   EXEC SQL COMMIT WORK RELEASE;
   ... 下面这个例子完整演示了静态游标的使用方法。这个例子的作用是,获得部门编号,通过游标来显示这个部门中的所有雇员信息。 #include <stdio.h>
   /* 声明宿主变量 */
   char userid[12] = "SCOTT/TIGER";
   char emp_name[10];
   int emp_number;
   int dept_number;
   char temp[32];
   void sql_error();
   /*包含SQLCA */
   #include <sqlca.h>
   main()
   { emp_number = 7499;
   /* 处理错误*/
   EXEC SQL WHENEVER SQLERROR do sql_error("Oracle error");
   /* 连接到Oracle数据库*/
   EXEC SQL CONNECT :userid;
   printf("Connected.\n");
   /* 声明游标 */
   EXEC SQL DECLARE emp_cursor CURSOR FOR
   SELECT ename FROM emp WHERE deptno = :dept_number;
   printf("Department number? ");
   gets(temp);
   dept_number = atoi(temp);
   /* 打开游标*/
   EXEC SQL OPEN emp_cursor;
   printf("Employee Name\n");
   printf("-------------\n");
   /* 循环处理每一行数据,如果无数据,则退出*/
   EXEC SQL WHENEVER NOT FOUND DO break;
   while (1)
   {
   EXEC SQL FETCH emp_cursor INTO :emp_name;
   printf("%s\n", emp_name);
   }
   EXEC SQL CLOSE emp_cursor;
   EXEC SQL COMMIT WORK RELEASE;
   exit(0);
   }
   /错误处理程序*/
   void sql_error(msg)
   char *msg;
   {
   char buf[500];
   int buflen, msglen;
   EXEC SQL WHENEVER SQLERROR CONTINUE;
   EXEC SQL ROLLBACK WORK RELEASE;
   buflen = sizeof (buf);
   sqlglm(buf, &buflen, &msglen);
   printf("%s\n", msg);
   printf("%*.s\n", msglen, buf);
   exit(1);
   }
   4.2 嵌入PL/SQL
   嵌入PL/SQL和嵌入SQL不同。嵌入PL/SQL提供了很多嵌入SQL不具有的优点,如:更好的性能、更灵活的表达方式。能够自己定义过程和函数。如:
   PROCEDURE create_dept
   (new_dname IN CHAR(14),
   new_loc IN CHAR(13),
   new_deptno OUT NUMBER(2)) IS
   BEGIN
   SELECT deptno_seq.NEXTVAL INTO new_deptno FROM dual;
   INSERT INTO dept VALUES (new_deptno, new_dname, new_loc);
   END create_dept;
   其中的IN/OUT,表示参数模式。IN是传递参数值到过程,而OUT是从过程传递参数值到调用者。
   但是,如果使用这些扩展的功能,也会造成同其他数据库厂商的嵌入SQL的不兼容。
   4.3 动态SQL语句
   4.3.1 ORACLE动态SQL语句的一些特点
    ORACLE DBMS进入市场的时间早于DB2,其动态SQL支持是以IBM的system/R原型为基础的。因此,ORACLE支持的动态SQL与IBM的DB2标 准有不同。虽然ORACLE和DB2在很大程度上是兼容的,但是在使用参数标志、SQLDA格式及支持数据类型转换等方面都有差异。
   DB2中不允许在PREPARE的动态语句中引用宿主变量,而是用问号来标志语句中的参数,然后用EXECUTE或OPEN语句来规定参数值。ORACLE允许用户用宿主变量规定动态语句中的参数。
   而且,ORACLE支持的DESCRIBE语句同DB2有一些区别。如:
   从已经PREPARE后的动态查询语句中获得对查询结果列的信息的语句为:
   EXEC SQL DESCRIBE SELECT LIST FOR qrystmt INTO qry_sqlda;
   等价于DB2的:
   EXEC SQL DESCRIBE qrystmt INTO qry_sqlda;
   从已经PREPARE后的动态查询语句中获得对查询参数的说明的语句为:
   EXEC SQL DESCRIBE BIND LIST FOR qrystmt INTO qry_sqlda;
   该ORACLE语句没有对应的DB2语句。用户只能按照当前需要的参数和SQLDA的结构对SQLDA赋值。然后再在OPEN语句或EXECUTE语句中使用SQLDA结构。
   4.3.2 使用动态SQL的四种方法
   使用动态SQL,共分成四种方法: 方法 支持的SQL语句 1 该语句不包含宿主变量,该语句不是查询语句
   2 该语句包含输入宿主变量 ,该语句不是查询语句
   3 包含已知数目的输入宿主变量或列的查询
   4 包含未知数目的输入宿主变量或列的查询
   l方法1:使用EXECUTE IMMEDIATE命令实现,具体语法为:
   EXEC SQL EXECUTE IMMEDIATE { :host_string | string_literal };
   其中,host_variable和string是存放完整T-SQL语句。
   请看下面这个例子。这个例子的作用是执行用户随意输入的合法的SQL语句。
   char dyn_stmt[132];
   ...
   for (;;)
   {
   printf("Enter SQL statement: ");
   gets(dyn_stmt);
   if (*dyn_stmt == '\0')
   break;
   /* dyn_stmt now contains the text of a SQL statement */
   EXEC SQL EXECUTE IMMEDIATE :dyn_stmt;
   }
   ...
   EXECUTE IMMEDIATE命令的作用是:分析该语句的语法,然后执行该语句。方法1适合于仅仅执行一次的语句。
   l方法2:方法支持的语句可以包含输入宿主变量。这个语句首先做PREPARE操作,然后通过EXECUTE执行。PREPARE语句的语法为:
   EXEC SQL PREPARE statement_name FROM { :host_string | string_literal };
    该语句接收含有SQL语句串的宿主变量,并把该语句送到ORACLE。ORACLE编译语句并生成执行计划。在语句串中包含一个“?”表明参数,当执行语 句时,ORACLE需要参数来替代这些“?”。PREPRARE执行的结果是,DBMS用语句名标志准备后的语句。在执行SQL语句时,EXECUTE语 句后面是这个语句名。EXECUTE语句的语法为:
   EXECUTE 语句名 USING 宿主变量 | DESCRIPTOR 描述符名
   它的作用是,请求ORACLE执行PREPARE语句准备好的语句。当要执行的动态语句中包含一个或多个参数标志时,在EXECUTE语句必须为每一个参数提供值。这样的话,EXECUTE语句用宿主变量值逐一代替准备语句中的参数标志(“?”或其他占位符),从而,为动态执行语句提供了输入值。
    使用主变量提供值,USING子句中的主变量数必须同动态语句中的参数标志数一致,而且每一个主变量的数据类型必须同相应参数所需的数据类型相一致。各主 变量也可以有一个伴随主变量的指示符变量。当处理EXECUTE语句时,如果指示符变量包含一个负值,就把NULL值赋予相应的参数标志。除了使用主变量 为参数提供值,也可以通过SQLDA提供值。
   请看下面这个例子。这个例子的作用是删除用户指定的雇员信息。
   ...
   int emp_number INTEGER;
   char delete_stmt[120], search_cond[40];;
   ...
   strcpy(delete_stmt, "DELETE FROM EMP WHERE EMPNO = :n AND ");
   printf("Complete the following statement's search condition--\n");
   printf("%s\n", delete_stmt);
   gets(search_cond);
   strcat(delete_stmt, search_cond);
  
   EXEC SQL PREPARE sql_stmt FROM :delete_stmt;
   for (;;)
   { printf("Enter employee number: ");
   gets(temp);
   emp_number = atoi(temp);
   if (emp_number == 0)
   break;
   EXEC SQL EXECUTE sql_stmt USING :emp_number;
   }
   l方法三:是指查询的列数或输入宿主变量数在预编译时已经确定,但是数据库中的对象,如表、列名等信息未确定。这些对象名不能是宿主变量。这时,必须通过以下语句来完成:
   PREPARE statement_name FROM { :host_string | string_literal };
   DECLARE cursor_name CURSOR FOR statement_name;
   OPEN cursor_name [USING host_variable_list];
   FETCH cursor_name INTO host_variable_list;
   CLOSE cursor_name;
   如:下面这个例子演示用方法3完成动态查询:
   char select_stmt[132]

分享到:
评论

相关推荐

    ESQL/C资料(完全版)

    ESQL/C 嵌入式 SQL 资料(完全版) ESQL/C 嵌入式 SQL 是一种特殊的编程语言,它将 SQL 语句直接嵌入到程序的源代码中,用于访问数据库。ESQL/C 嵌入式 SQL 语言是基于 SQL 语言的扩展,它提供了一个可靠的解决方案...

    ESQL/C资料(完全版)二

    介绍了如何使用Microsoft SQL Server 2000和VC开发数据库(ESQL/C 嵌入式SQL)

    ESQLC资料 informax

    ESQL/C是特定于C语言的嵌入式SQL版本。 在ESQL/C中,有几个关键的概念和组成部分: 1. **嵌入SQL程序的组成元素**:一个嵌入式SQL程序由宿主语言代码和SQL语句组成。宿主语言负责程序的控制流,而SQL语句用于与...

    Informix ESQLC 中文完整版 pdf格式

    ### Informix ESQL/C 关键知识点详解 #### 第一章:Informix 产品介绍 ...综上所述,这份文档涵盖了 Informix 产品的详细介绍以及 INFORMIX-ESQL/C 的核心知识点,是学习和掌握 Informix 技术不可或缺的宝贵资料。

    ESQL编程

    #### 三、DB-Library与ESQL Sybase提供了一套名为DB-Library的API,它支持多种语言,包括C语言,用于实现与数据库的交互。DB-Library是Sybase为应用程序访问其数据库提供的核心接口之一。当使用C语言进行Sybase...

    ESQLC资料(完全版).doc

    在 ESQL/C 的上下文中,SQL 语句被预编译器处理,转换成宿主语言可识别的函数调用,然后由对应的编译器(如 C 编译器)编译为可执行程序。 在 ANSI/ISO 标准下,不同数据库厂商都支持嵌入式 SQL,但每个厂商可能会...

    ESQLC资料(完全版)

    ### ESQL/C资料(完全版) #### 第一节 什么是嵌入SQL语言? **1.1 嵌入SQL程序的组成元素** 嵌入式SQL(Embedded SQL, ESQL)是一种将SQL语句直接嵌入到高级编程语言(如C语言)中的方法,允许开发者直接在应用...

    informix数据库管理教程

    SQL是所有数据库操作的基础,而ESQL/C则是将SQL语句嵌入到C语言程序中的一种方法。这使得开发者可以在C语言中直接执行复杂的数据库操作。 - **提高系统效率的几点建议** 提高系统效率的方法包括优化查询语句、...

    informix入门和SQL优化

    伴随着数据库的发展,Informix还提供了一系列开发工具,如4GL和ESQL/C等,这些工具为开发者提供了强大的数据库应用开发能力,极大地提升了开发效率和应用程序的性能。 #### 二、数据库管理与系统维护 数据库管理...

    在LINUX下安装 Sybase ASE 11.0.3.3

    - `sybase-ase-11.0.3.3-1.i386.rpm`:包含了Sybase ASE 11.0.3.3的主要组件,包括SQL Server、Backup Server、Sybinit和Sybmon,以及OpenClient 10.0.4和OpenServer,还有ESQL/C接口。 - `sybase-doc-11.0.3.3-1....

    Informix Study Resource

    4. **4GL(第四代编程语言)**:Informix 自有的 4GL 语言,如 Informix-4GL 和 ESQL/C,提供了高效开发数据库应用的环境。 **四、Informix 高级特性** 1. **分布式数据库**:Informix 支持分布式数据库系统,允许...

    22.控制数据库服务.doc

    ### 控制数据库服务 在IT领域,特别是数据库管理与应用开发方面,掌握如何有效地控制数据库服务至关重要。...了解这些函数的工作原理对于任何从事Informix-ESQL/C应用开发的工程师来说都是非常有价值的。

    Informix维护基础

    对于应用开发工具,Informix提供了一系列基于4GL(第四代编程语言)的产品,包括I-SQL、4GLRDS、4GLCCOMPILER、4GLID和ESQL/C等。这些工具支持开发者创建基于字符界面的数据库应用程序。随着技术的发展,Informix还...

    000-315 真题, PDF版, IBM WebSphere Message Broker V6.1, Solution

    #### 完整问题与答案集合 Pass4sure提供的106个问题及答案集合覆盖了000-315考试的所有方面,帮助考生全面掌握所需知识。以下是几个具体的知识点: 1. **构建无WSDL访问的消息流**: - **问题**: 一个WMB V6.1...

    postgresql_简介

    - **丰富的客户端接口**:支持 ODBC、JDBC、Python、Perl、Tcl、C/C++、ESQL 等多种编程语言的客户端接口。 - **跨平台支持**:支持多种操作系统和硬件架构,包括 Windows、Linux、macOS 等。 ### PostgreSQL 的...

    Sybase IQ 15.4中文手册(命令与系统参数)

    Sybase IQ 15.4中文手册详细介绍了该版本的命令和系统参数,对于数据库管理员和开发者而言,这是极为重要的参考资料。手册涵盖了SQL语句的使用,包括数据定义语言(DDL)、数据操纵语言(DML)和事务控制语句等。...

Global site tag (gtag.js) - Google Analytics