51CTO技术论坛_中国领先的IT技术社区's Archiver

ribut9225 发表于 2008-6-18 08:57

PB中使用动态SQL语句

PB中使用动态SQL语句
我们经常使用的SQL语句大多都是静态的,也就是说,SQL语句的结构是固定的,当编译Script时,整个SQL语句都是已知的,它们不能在运行时动态的改变。但是,在很多情况下,SQL语句或SQL所带的参数在编译时并不知道,应用必须在运行时才能生成SQL语句。这种在运行时才能生成的SQL语句叫动态SQL语句。动态SQL允许应用程序向数据库发送任何查询。此外,某些类型的操作,尤其是数据定义语言(DDL)的语句如CREATE和 DROP等,对嵌入式SQL根本就不可能。动态SQL使得可以象发送查询一样向数据库发送DDL和数据存取语言(Date Access Language)的语句。
为了支持动态SQL,PowerBuilder提供了两种数据类型:DynamicStagingArea 和DynamicDescriptionArea。Powerbuilder使用DynamicStagingArea类型的变量为后续语句保存信息,用作语句的运行和事物对象之间的连接。DynamicStagingArea类型的变量是PowerBuilder内部使用的,用户无法访问DynamicStagingArea中的信息。PowerBuilder提供了一个全局的DynamicStagingArea变量,变量名为SQLSA,当需要一个DynamicStagingArea变量时可以使用它。用户也可以根据需要定义并创建另外的DynamicStagingArea类型的变量。下面的例子定义并创建了一个DynamicStagingArea类型的变量,变量名是Dsa_Stage1
DynamicStagingArea Dsa_Stage1
Dsa_Stage1=CREATE DynamicStagingArea
PowerBuilder使用DynamicDescriptionArea类型的变量保存动态SQL语句中的输入和输出参数的信息。PowerBuilder也提供了一个全局的DynamicDescriptionArea变量,变量名为SQLDA,当需要一个DynamicDescriptionArea变量时可以使用它。用户也可以根据需要定义并创建另外的DynamicDescriptionArea类型的变量。下面的例子定义并创建了一个DynamicDescriptionArea类型的变量,变量名是Dda_Desc1。
DynamicDescriptionArea Dda_Desc1
Dda_Desc1=CREATE DynamicDescriptionArea
为适应所有的SQL语句,PowerBuilder根据语句的类型和未知数的个数把动态SQL分为四种不同的格式。下面将详细介绍动态SQL的这四种格式。
二、动态SQL格式一
    使用这种格式执行的SQL语句不会产生结果集,并且不需要输入参数。可以使用这种格式执行所有的数据定义语言(DDL)。语法如下:
    EXECUTE IMMEDIATE SQLStatement  { USING TransactionObject }
    其中,SQLStatement是包括合法SQL语句的字符串,该字符串必须放在一行上,并且不能包含表达式。它可以是字符串常量或前面带有冒号的PowerBuilder字符串变量。TransactionObject是指向数据库的事物对象名。此方法成立的前提是:1、用于除SELECT之外的SQL语句。2、在SQL语句中不能包含变量。
例如,下面语句创建一个名为 auths的表,它用串ls_sql存放SQL语句。
String ls_sql
//若与SQL SERVER、Sybase 11、ODBC数据库相连,在运行CREATE前,
//必须置系统对象属性AUTOCOMMIT为TRUE
SQLCA.AUTOCOMMIT=TRUE
ls_sql="CREATE TABLE auths(auths_id char(6) NOT NULL,"+&
      "auths_name char(10) NOT NULL,auths_phone char(12),"+&
      "auths_address char(50),PRIMARY KEY(auths_id))"
EXECUTE IMMEDIATE  :ls_sql  USING SQLCA;
SQLCA.AUTOCOMMIT=FALSE
注意:在给出的SQL语句串的结束位置不能加“;”号。
使用格式一的动态SQL语句适合于在程序运行期间,创建一些简单的临时的数据库对象(如临时表)来保存数据等,做一些程序运行的辅助性工作。
三、动态SQL格式二
使用这种格式执行的SQL语句不产生结果集,但是需要输入参数。使用这种格式可以执行所有形式的数据定义语言(DDL)。语法如下:  
    PREPARE DynamicStagingArea FROM SQLStatement { USING TransactionObject }
    EXECUTE  DynamicStagingArea  USING {ParameterList }
    其中,DynamicStagingArea是DynamicStagingArea变量名(一般为系统变量SQLSA)。SQLStatement和TransactionObject的意义同格式一。ParameterList是逗号分隔的一组PowerScript变量表,在它们的前面要有冒号。此方法成立的前提是:1、用于除SELECT之外的SQL语句。2、在SQL语句中可用变量,但必须预先说明。
例如,下面语句在SQLSA中准备了一个带有一个参数的DELETE语句,然后把变量author_code的值带入并运行它:
String  sl_sql,author_code
sl.sql="delete from auths where auths_id=?"
PREPARE SQLSA FROM :ls_sql USING SQLCA;
author_code='A00001'
EXECUTE SQLSA USING :author_code;
    格式二可用于执行除SELECT语句之外的其它任意SQL语句,由于可以输入参数,因此,它可以灵活地控制SQL语句的执行条件。
四、动态SQL格式三
使用这种格式执行的SQL语句产生结果集,也需要输入参数,但结果集中列的数目必须固定。使用这种格式的语法如下:
DECLARE Cursor | Procedure
          DYNAMIC CURSOR | PROCEDURE FOR DynamicStagingArea;
PREPARE  DynamicStagingArea  FROM SQLStatement
          { USING TransactionObject };
OPEN  DYNAMIC  Cursor { USING ParameterList };
EXECUTE  DYNAMIC  Procedure  { USING ParameterList };
FETCH  Cursor | Procedure  INTO HostVaribleList ;
CLOSE Cursor | Procedure ;
其中,Cursor或Procedure 是要使用的游标或过程名;DynamicStagingArea、SQLStatement、TransactionObject和ParameterList的意义同格式二。HostVaribleList是存放查询结果的PowerBuilder变量。此方法成立的前提是:1、用于动态的SELECT语句,但SELECT语句中列的数目必须固定,WHERE、ORDER BY等子句可任意合成。2、在SQL语句中可用变量,但必须预先说明。
例如,下面语句在ls_sql中准备一个查询auths表的SELECT语句,把查询结果返回给PowerBuilder变量(用游标处理结果集):
string name,ls_sql,code  
code="A%"              
ls_sql="SELECT auths_name FROM auths WHERE auths_id like ?"
DECLARE c1 DYNAMIC CURSOR FOR SQLSA;
PREPARE SQLSA FROM :ls_sql;
OPEN DYNAMIC c1 USING :code;
Lable:
FETCH c1 INTO :name;
If SQLCA.SQLCode=0 then   //如果成功取出记录
   //进行相应处理
   goto lable               //取下一条
end if
CLOSE c1;                 //关闭游标
格式三可用于执行WHERE、ORDER BY 等子句任意组合的SELECT语句。
2007-11-14 15:15 hyshi
五、动态SQL 格式四
这是一种全动态的SQL 语句。全动态的SQL 语句是指这样的语句:在写程序时并不知道SELECT语句的选择项是什么或有多少个,也不知道SQL语句中包含了多少个变量,它们是变化的。全动态SQL支持临时生成的SQL。全动态SQL实现起来很复杂,也很有用,下面我们将详细讲述。语法如下:
DECLARE Cursor | Procedure
           DYNAMIC CURSOR | PROCEDURE FOR DynamicStagingArea;
PREPARE  DynamicStagingArea  FROM SQLStatement
           { USING TransactionObject };
DESCRIBE DynamicStagingArea INTO DynamicDescriptionArea;
OPEN DYNAMIC Cursor | Procedure
           USING DESCRIPTION DynamicDescriptionArea;
EXECUTE  DYNAMIC  Cursor | Procedure
           USING DESCRIPTION DynamicDescriptionArea;
FETCH  Cursor | Procedure  USING DESCRIPTION DynamicDescriptionArea;
CLOSE  Cursor | Procedure ;
其中,Cursor或Procedure 是要使用的游标或过程名;DynamicStagingArea是DynamicStagingArea变量名(一般为SQLSA);SQLStatement 是包含合法SQL语句的字符串,它可以是字符串常量或前面带有冒号的PowerBuilder字符串变量,它必须包含在一行且不能包括表达式;TransactionObject是指向数据库的事物对象名。DynamicDescriptionArea 是DynamicDescriptionArea 变量名(一般为SQLDA)。  
     可以用以下方法设置在PREPARE语句中出现的每个输入参数的类型和值。PowerBuilder在 DESCRIBE运行时可取得SQLDA的属性NumInputs(可得到输入参数个数)和InParmType(可得到输入参数类型),可用这些值和函数SetDynamicParm给输入参数的类型和值赋值。输入参数是任选的,若要使用它们,应在运行OPEN或EXECUTE语句之前给它们赋值。
     可以用以下方法取得PREPARE语句中的每个输出参数的类型和值。如果使用的数据库支持输出参数描述,PowerBuilder应用可在DESCRIBE语句执行时取得SQLDA的NumOutputs值;若数据库不支持输出参数描述,PowerBuilder应用可在FETCH语句执行时取得SQLDA的NumOutputs值。可用输出参数的号码(NumOutputs)从输出参数类型(OutParmType)数组中获得特定参数的类型。得到类型后,在FETCH语句后可调用恰当的函数取出输出值。
    下面是一个使用动态SQL格式四的例子,此例有一个字符串输入参数,但输出参数的类型和个数不定。
    string ls_sql,ls_val
integer i,li_boolean
ls_sql="SELECT * FROM auths WHERE auths_id=?"
    DECLARE c1 DYNAMIC CURSOR FOR SQLSA;
    PREPARE SQLSA FROM :ls_sql;
    DESCRIBE SQLSA INTO SQLDA;
    //若DESCRIBE成功,则输入描述符数组将包含一个输入描述符,
    //在打开游标前必须先给输入描述符赋值。
    SetDynamicParm(SQLDA,1,'A00001')     //这里的“1”表示第一个参数
    OPEN DYNAMIC c1 USING DESCRIPTOR SQLDA;
    lable:
    FETCH c1 USING DESCRIPTOR SQLDA;
    IF SQLCA.SQLCODE=0 THEN //若FETCH成功
     FOR i=1 to SQLDA.NumOutputs  
        //SQLDA.NumOutputs含有输出参数的个数
        CHOOSE CASE SQLDA.OutParmType[i]
        CASE TypeString!
             ls_val=GetDynamicString(SQLDA,i)
        CASE TypeDate!
             ls_val=string(GetDynamicDate(SQLDA,i),'dd mm yyyy')
        CASE TypeTime!
             ls_val=string(GetDynamicTime(SQLDA,i),'hh:mm:ss')
        CASE TypeDataTime!
             ls_val=string(GetDynamicDateTime(SQLDA,i),&
                            'dd mm yyyy hh:mm:ss')
        CASE TypeInteger!,TypeLong!,TypeDecimal!,TypeDouble!,TypeReal!
             ls_val=string(GetDynamicNumber(SQLDA,i))
        CASE TypeBoolean!
             li_boolean=GetDynamicNumber(SQLDA,i)
             IF li_boolean=1 THEN
                ls_val="TRUE"
             ELSE
                ls_val="FALSE"
             END IF
END CHOOSE
        …… //进行相应处理
NEXT
     GOTO lable  //取下一条记录
     ENF IF
     CLOSE c1;
     格式四适合于所有子句都不确定的SELECT语句,这是最有用的一种动态SQL。

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.