第四章 动态SQL语句
    嵌入式的SQL有两种主要的形式:静态的SQL动态的SQL静态的SQL语句是在编写程序时要定义所有的SQL语句,如INSERTSELECT等普通的SQL语句。对于动态的SQL的情形,SQL语句可以被应用程序在运行时构造
    ESQL/C提供了处理在编译时未知的SQL语句的手段,通常的ESQL/C程序,只要显式地嵌入SQL语句就能实现所要求的功能了,但在有些特定的应用中,程序在编译时并不知道语句的内容,需要在程序运行中捕获并完成正确的操作,这样的程序有:
    1.运行时用户才从键盘打入检索要求的交互式程序。
    2.编写支持变化的数据库结构的程序,这些变化在编程时是未知的
    这两种情况都需要对动态定义的语句进行处理,也就是说,当应用程序不知道那些需要提前在数据库上执行的所有操作时,或操作的组合数目很大,以至于与其在静态SQL中把所有可能的组合都编码,倒不如动态地在程序中建立SQL串来得容易些。动态SQL中使用参数代替了宿主变量,这些参数可以嵌入在SQL语句中,并且在以后被值替换。动态SQL语句在提
高性能方面还有不小的影响。
4.1 动态SQL的相关语句
    动态SQL的特性为:语句的说明与执行分为两步。第一步,PREPARE语句用于分析SQL语句,并且在必要时建立一个程序计划;第二步,EXECUTE或定义游标来执行被预备好的SQL语句。这样一旦一条SQLsql语句替换表中内容语句经过预备处理后,就可重复执行它多次。假如仅执行一次的SQL语句那就不必做预备处理。与之相关的动态定义语句简要介绍如下:
  1.PREPARE语句:将一字符串解释成一组SQL语句,并赋给它一个语句标识符,以后的
    动态管理语句通过语句标识来引用这组SQL语句
    PREPARE语句的一般形式为:
    PREPARE语句标识名fromSQL语句”;
    PREPARE语句标识名from :宿主变量;
 
  2.EXECUTE语句:运行与其语句标识符对应的事先准备好的语句,对非select语句,用
    EXECUTE来运行。
    EXECUTE语句的一般形式为:
    EXECUTE被预备的语句标识名[using宿主变量列]
  3.DESCRIBE语句:确定已准备好的语句是否为select语句,如果是,则得到单一查
    行的存贮要求,否则只返回语句类型。
 
  4.DECLARE语句:为已准备好的select语句说明游标。
 
  5.FREE语句:释放已准备好的语句或已打开的游标所占用的资源。
  6.EXECUTE IMMEDIATE语句:立即执行语句,它接收一字符串,将其解释成SQL语句
    并立即执行它,然后释放准备SQL语句所占用的资源。
4.2 select语句的用法举例
    例:
    $ char state[128];
    $ long p_num;
      char num[12];
      long atol();
      ...
      sprintf(state,"delete from customer where customer_num=?");
    $ prepare stateid from $ state;  /*准备state中的语句*/
      for(;;){
      prinft{"Enter customer number:");
      getline(num,12);
      p_num=atol(num);
      if(p_num==0)break;
    $ execute stateid using $ p_num;
              /*执行语句,用p_num的值替语句中的问号“?*/
      }
    例:
    int cust_update(cnum,lname)
      exec sql begin declare section;
      parameter long cnum;
      parameter char *lname;
      exec sql end declare section;
    {
      static int first = 1;
      if (first){
        first =0;
        exec sql prepare pl from
              "update customer set lname =? where cus_num =?";
        sqlerr();
      }
      esql sql execute pl using :lname, :cnum;
      sqlerr();
    }
4.3 select语句的用法举例
    ESQL/C中直接嵌入的select语句,查询结果放入INTO子句的宿主变量中,然而在程序已被编译后交互地建立的select语句中,不能使用INTO子句,因为这时不能直接使用宿主变量。/*?????*/为此,ESQL/C提供了sqlda结构,该结构中包含了动态定义语句的所有信息。执行动态定义的select语句,需要以下几个步骤:
    (1)说明一个指向sqlda结构的指针
    (2)准备select语句,并赋给语句标识符
(3)执行语句describe为指针赋值,使其指向一结构链,链中每个结点含有查项的
      描述,包括数据类型、长度、名字等
    (4)为结构链中存放查询数据的指针分配空间
    (5)为已准备好的语句说明游标
    (6)打开游标
    (7)执行语句来获取数据,并重复执行
    (8)关闭游标
    例:
    $ include sqlca;
    $ include sqlda;
        .
        .
        .
    /*declare pointer to structure that
            apportions the data from each row*/
    struct sqlda  *q_desc;
    /*declare host variable to hold
            statement string*/
    $        char q_string[128];
    /*make stores the current database*/
    $        database stores;
            .
            .
            .
    /*At this point the SELECT statement
            is assigned to q_string*/
    /*prepare the SELECT statement*/
    $        prepare q_id from $q_string;
    /*identify the select_list*/
    $        describe q_id into q_desc;
            /*this section of the code must
                      allocate variables to receive
                      the data from the rows and
                      set the pointers in q_desc.
                      See the followng discussion*/
    /*associate q_cursor with SELECT
            statement*/
    $      declare q_cursor cursor for q_id;
    /*open q_cursor;create active set*/
    $      open q_cursor;
    /*loop through rows in active set*/
            for(;;)
                      {
    /*fetch next row from the active set*/
    $                fetch q_cursor
                              using descriptor q_desc;
    /*process data if fetch returned a row*/
                      if (sqlca.sqlcode==0)
                                  {
                                  /*process data*/
                                  .
                                  .
                                  .
                                  }
                      else
                                  {

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。