OTL使用指南

                              

 

 

 

 

 

 

OTL使用指南

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

文档修改历史

日期

版本

作者

修改内容

评审号

变更控制号

发布日期

2007-9-14

0.1

佘彪

初稿

 

 

 

2007-9-18

0.2

佘彪

根据9月17日上午周例会上陈彰的要求,增加编程实践相关的内容,主要通过总结OCS租费开发中OTL的使用经验,整理出13章最佳实践。

 

 

 

2007-11-8

  0.3

佘彪

增加13.3小节与开源项目ORAPP的性能对比

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


目    录

1 OTL简介............................................................................................................................................................................... 5

2 编译OTL.............................................................................................................................................................................. 5

3 基本使用............................................................................................................................................................................... 5

4 OTL流的概念................................................................................................................................................................... 14

5 主要类及方法说明.......................................................................................................................................................... 15

4.1 otl_stream的主要方法......................................................................................................................................... 16

4.2 otl_connect的主要方法...................................................................................................................................... 19

6 SQL的变量绑定和常量SQL........................................................................................................................................ 22

6.1 SQL的变量绑定......................................................................................................................................................... 22

6.2 常量SQL..................................................................................................................................................................... 25

7迭代器.................................................................................................................................................................................. 25

7.1 OTL流的读迭代器.................................................................................................................................................... 25

7.2 STL兼容的迭代器..................................................................................................................................................... 29

8 资源池................................................................................................................................................................................. 33

8.1 连接缓冲池................................................................................................................................................................. 33

8.2 OTL流缓冲池............................................................................................................................................................. 37

9 操作大型对象................................................................................................................................................................... 44

9.1大型对象的存储......................................................................................................................................................... 44

9.1.1 otl_long_string.................................................................................................................................................. 44

9.1.2 otl_long_unicode_string................................................................................................................................. 45

9.2 大型对象的读写......................................................................................................................................................... 45

10国际化................................................................................................................................................................................ 50

10.1 使用UNICODE字符串.......................................................................................................................................... 50

10.2 使用UTF8字符串................................................................................................................................................... 54

11 Reference Cursor流........................................................................................................................................... 58

12 杂项................................................................................................................................................................................... 62

12.1 使用otl_nocommit_stream避免SQL执行成功后立刻提交事务........................................................ 62

12.2 SELECT中的数据类型映射覆写......................................................................................................................... 65

12.3 使用OTL tracing跟踪OTL的方法调用........................................................................................................ 69

12.4 获取已处理行数(Rows Processed Count).................................................................................................... 76

12.5 使用otl_connect的重载运算符<<,<<=, >>................................................................................................. 78

12.6 手工刷新otl_stream缓冲区............................................................................................................................ 82

12.7 忽略INSERT操作时的重复键异常.................................................................................................................... 87

12.8 使用模板otl_value<T>创建数据容器........................................................................................................... 91

12.9 使用OTL流的读迭代器遍历流返回的ReferenceCursor....................................................................... 94

12.10使用Reference Cursor流从存储过程中返回多个Referece Cursor............................................... 98

13 最佳实践........................................................................................................................................................................ 103

13.1流缓冲区大小的设置............................................................................................................................................ 103

13.2批量操作注意的问题............................................................................................................................................ 106

13.3与开源项目ORAPP的性能对比........................................................................................................................ 107

 

 


1 OTL简介

OTL 是 Oracle, Odbcand DB2-CLI Template Library 的缩写,是一个C++编译中操控关系数据库的模板库,它目前几乎支持当前所有的各种主流数据库,例如Oracle, MS SQL Server, Sybase, Informix, MySQL, DB2, Interbase /Firebird, PostgreSQL, SQLite, SAP/DB, TimesTen, MS ACCESS等等。

OTL中直接操作Oracle主要是通过Oracle提供的OCI接口进行,操作DB2数据库则是通过CLI接口进行,至于MS的数据库和其它一些数据库,OTL只提供了ODBC的操作方式。当然Oracle和DB2也可以由OTL间接使用ODBC的方式进行操纵。

在MS Windows and Unix 平台下,OTL目前支持的数据库版本主要有:Oracle 7 (直接使用 OCI7), Oracle 8 (直接使用 OCI8), Oracle 8i (直接使用OCI8i), Oracle 9i (直接使用OCI9i), Oracle 10g (直接使用OCI10g), DB2 (直接使用DB2 CLI), ODBC 3.x ,ODBC 2.5。目前OTL的最新版本为4.0,参见http://otl.sourceforge.net/,下载地址http://otl.sourceforge.net/otlv4_h.zip

2 编译OTL

OTL是一个集成库,它包含了一个模板流框架(template stream framework)以及适配OCI7, OCI8, OCI8i, OCI9i, OCI10g, ODBC 2.5, ODBC 3.x, DB2 CLI和Informix CLI的适配器(OTL-adapters)。编译时需要使用相应的宏定义向编译器指明底层数据库API的类型。例如,如果底层使用ORACLE10g的API,则需要使用宏定义”#defineOTL_ORA10G”。

另外,也可以使用相应的宏定义控制编译器对OTL的编译。 例如,如果需要和ACE库一起编译可以使用宏定义”#defineOTL_ACE”, 如果需要OTL为所分配并处理的字符串以空字符结尾成为C风格字符串则可以使用宏定义”#define OTL_ADD_NULL_TERMINATOR_TO_STRING_SIZE”等。

所有的相关宏请参见http://otl.sourceforge.net/otl3_compile.htm

3 基本使用

OTL的一般使用步骤包括:

(1)   使用宏指明底层数据库API类型和控制编译器对OTL的编译。例如:

    #define OTL_ORA9I      // Compile OTL 4.0/OCI9i

#define OTL_UNICODE    //Enable Unicode OTL for OCI9i

(2)   创建otl_connect对象,该对象一般为全局共享的。

(3)   调用otl_connect的静态方法otl_initialize()初始化OTL环境。

(4)   调用otl_connect的rlogon()方法连接数据库。

(5)   创建otl_stream()对象,该对象一般为局部的。

(6)   调用otl_stream的open()方法打开SQL进行解析。

(7)   使用otl_stream的<<操作符绑定SQL中的变量。

(8)   使用otl_stream的>>操作符读取返回结果。

(9)   调用otl_connect的logoff()方法从数据库断开。

下面将通过一个较为全面的示例说明使用OTL连接数据库、创建表和存储过程、调用存储过程、查询记录以及插入记录、从数据库断开的具体代码实现。

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <vector>

 

#define OTL_ORA9I       // Compile OTL 4.0/OCI9i

//#define OTL_UNICODE   // Enable Unicode OTL for OCI9i

#include "otlv4.h"          // include the OTL 4.0 header file

 

using namespace std;

 

/**

  *连接数据库

  */

int OTLConnect (const char* pszConnStr, otl_connect& db)

{

       try

       {

              otl_connect::otl_initialize(); // initialize OCI environment

              db.rlogon(pszConnStr);

              db.auto_commit_off ( );

              printf ( "CONNECT: OK!\n" );

       }

       catch(otl_exception& p)

       {   // intercept OTL exceptions

              printf ( "Connect Error: (%s) (%s) (%s)\n",p.msg, p.stm_text, p.var_info );

              return -1;

       }

       return 0;

}

 

/**

  *从数据库断开

  */

int OTLDisconnect (otl_connect& db)

{

       db.commit ( );

       db.logoff();

 

       printf ( "DISCONNECT: OK!\n" );

       return 0;

}

 

/**

  *创建数据库表和存储过程

  */

int OTLExec ( otl_connect& db)

{

       try

       {

              int nCnt = 0;

              char strSql[] = "SELECT count(0) FROM user_tables "

                                           " WHERE table_name = 'TEST_FTP' ";

 

              otl_stream otlCur (1, (const char*)strSql, db );

              otlCur >> nCnt;

 

              if ( nCnt == 0 )

              {

                     char strDDL[] =

                            "create table TEST_FTP                 "

                            "(                                                                          "

                            "  AREA_ID         VARCHAR2(100) not null,     "

                            "  FTP_FILE_NAME   VARCHAR2(100) not null,    "

                            "  FTP_TIME        VARCHAR2(14),               "

                            "  FTP_BEGIN_TIME  VARCHAR2(14),                   "

                            "  FTP_END_TIME    VARCHAR2(14),                   "

                            "  FTP_MOD_TIME    date,                                 "

                            "  FTP_SIZE        NUMBER(8),                      "

                            "  FTP_SOURCE_PATH VARCHAR2(100),                 "

                            "  FTP_LOCAL_PATH  VARCHAR2(100),                "

                            "  FTP_RESULT      VARCHAR2(4),                       "

                            "  FTP_REDO        VARCHAR2(1)                       )";

 

                     otl_cursor::direct_exec ( db, (const char*)strDDL );

              }

 

              char strSqlProc[] = "SELECT count(0) from user_objects "

                             " WHERE object_type = 'PROCEDURE' and object_name = 'PR_REMOVE_FTP' ";

              otl_stream otlCurProc (1, (const char*)strSqlProc, db );

              otlCurProc >> nCnt;

 

              if ( nCnt == 0 )

              {

                     char strProc[] =

                     "CREATE OR REPLACE procedure pr_remove_ftp             "

                     "      ( area in varchar2, out_flag out varchar )      "

                     "AS                                                                                    "

                     "strtmp varchar2(32);                                                  "

                     "BEGIN                                                                                    "

                     "  strtmp := area||'%';                                                        "

                     "  DELETE FROM TEST_FTP where area_id LIKE strtmp;       "

                     "  out_flag := 'OK';                                                   "

                     "END;                                                                                ";

 

                     otl_cursor::direct_exec ( db, (const char*)strProc );

              }

 

       }

       catch(otl_exception& p)

       {   // intercept OTL exceptions

              printf ( "EXECUTE Error: (%s) (%s) (%s)\n",p.msg, p.stm_text, p.var_info );

       }

       return 0;

}

 

/**

  *调用存储过程

  */

int OTLProcedure (otl_connect& db )

{

       try

       {

 

              char szData[64],  szData1[64],  szData2[64], szData3[64];

              int nSize = 0;

              char strSql[] = " BEGIN "

                                     "  pr_remove_ftp ( :area<char[100],in>, :out<char[100],out> ); "

                                     " END; ";

              otl_stream otlCur (1, (const char*)strSql, db );

              otlCur.set_commit ( 0 );

 

              strcpy ( szData, "AREA" );

              memset ( szData1, 0, sizeof(szData1) );

              memset ( szData2, 0, sizeof(szData2) );

              memset ( szData3, 0, sizeof(szData3) );

 

              otlCur << szData;

              otlCur >> szData1;

 

              printf ( "PROCEDURE: %s!\n", szData1 );

       }

       catch(otl_exception& p)

       { // intercept OTL exceptions

              printf ( "PROCEDURE Error: (%s) (%s) (%s)\n",p.msg, p.stm_text, p.var_info );

       }

       return 0;

}

 

/**

  *查询记录

  */

int OTLSelect (otl_connect& db)

{

       try

       {

              char szData[64],  szData1[64],  szData2[64], szData3[64], szRedo[2];

              int nSize;

              char strSql[] = " SELECT area_id, ftp_time, ftp_file_name, "

                                     " to_char(ftp_mod_time, 'YYYY-MM-DD HH24:MI:SS'), ftp_size "

                                     "  FROM TEST_FTP "

                                     " WHERE ftp_redo = :ftp_redo<char[2]>" ;

              otl_stream otlCur (1, (const char*)strSql, db );

 

              strcpy ( szRedo, "Y" );

              otlCur << szRedo;

              while ( !otlCur.eof() )

              {

                     memset ( szData, 0, sizeof(szData) );

                     otlCur >> szData;

                     otlCur >> szData1;

                     otlCur >> szData2;

                     otlCur >> szData3;

                     otlCur >> nSize;

                     printf ( "SELECT: (%s %s %s %s %d)\n",

                                    szData, szData1, szData2, szData3, nSize );

              }

       }

       catch(otl_exception& p)

       { // intercept OTL exceptions

              printf ( "Select Error: (%s) (%s) (%s)\n",p.msg, p.stm_text, p.var_info );

       }

       return 0;

}

 

/**

  *插入记录

  */

int OTLInsert (otl_connect& db)

{

       try

       {

              char szData[64],  szData1[64],  szData2[9], szData3[64], szRedo[2];

              int nSize;

              char strSql[] = " INSERT into TEST_FTP "

                                   " ( area_id, ftp_file_name, ftp_time, ftp_mod_time, ftp_size, ftp_redo )"

                                   " VALUES ( :area_id<char[100]>, "

                                   "      :ftp_file_name<char[100]>, "

                                   "      to_char(sysdate,'YYYYMMDDHH24MISS'), "

                                   "   to_date(:ftp_mod_time<char[20]>,'YYYYMMDD'), "

                                   "      :ftp_size<int>, "

                                   "   :ftp_redo<char[2]> ) ";

              otl_stream otlCur (1, (const char*)strSql, db );

 

              otlCur.set_commit ( 0 );

 

              for ( int i = 1; i < 10; i ++ )

              {

                     sprintf ( szData, "AREA_%d", i );

                     sprintf ( szData1, "FILE_NAME_%d", i );

                     if ( i < 5 )

                     {

                            sprintf ( szData2, "20070415" );

                            strcpy ( szRedo, "Y" );

                     }

                     else

                     {

                            sprintf ( szData2, "20070416" );

                            strcpy ( szRedo, "N" );

                     }

 

                     memset ( szData3, 0, sizeof(szData3) );

                     nSize = i * 100;

 

                     otlCur << szData << szData1 << szData2 << nSize << szRedo;

              }

 

              printf ( "INSERT: OK!\n" );

       }

       catch(otl_exception& p)

       { // intercept OTL exceptions

              printf ( "INSERT Error: (%s) (%s) (%s)\n",p.msg, p.stm_text, p.var_info );

       }

       return 0;

}

 

/**

  *主函数

  */

int main ( int argc, char *argv[] )

{

       otl_connect db;

       char szConn[64];

 

 

       if ( argc >= 2 )

              strcpy ( szConn, argv[1] );

       else

       {

              printf ( "otltest conn_str" );

              return -1;

       }

 

       if ( OTLConnect ( szConn, db ) < 0 )

              return 0;

       OTLExec ( db );

       OTLProcedure ( db );

       OTLInsert ( db );

       OTLSelect ( db );

       OTLDisconnect ( db );

 

       return 0;

}

4 OTL流的概念

OTL设计者认为,任何SQL语句、PL/SQL块或存储过程调用都被输入和输出变量特征化。例如:

l       一个SELECT语句在其WHERE子句中拥有标量的输入变量,而在其SELECT子句则定义了输出的列,如果SELECT语句返回的是多行记录则输出列是个向量参数。

l       一个INSERT和UPDATE语句需要将数据写入表中,它们拥有输入参数。另外,一个DELETE语句由于需要指明删除记录的类型,同样拥有输入。工业强度的数据库服务器通常也支持批量操作,例如批量的查询、更新、删除和插入,因此INSERT/UPDATE/DELETE语句的参数在批量操作的情况下也可能是向量。

l       一个存储过程可能含有输入和(或)输出参数。通常存储过程的参数是标量,但是也有特例,例如返回的是引用游标(Oracle)或者记录集(MS SQL SERVER或者Sybase)。

l       一个PL/SQL块可能含有输入和(或)输出参数,这些参数可能是标量也可能是向量。

图4-1 OTL的流

因此,任何的SQL或者其程序上的扩展在交互过程中都可以如图4-1所示看作拥有输入和输出的黑盒。OTL通过将数据流和SQL的概念联合起来,用otl_stream类表达这种抽象。

由于SQL语句可能以批量的方式执行,otl_stream是一个缓冲流。它拥有两个独立的缓冲区:输入和输出。输入缓冲区由所有集中到一起的输入参数组成,输出缓冲区则由所有集中到一起的输出变量组成。

OTL流和C++的缓冲流很相似。一个SQL语句或存储过程调用被当作一个普通的缓冲流被打开。OTL流的操作逻辑和C++流操作逻辑基本相同,但是OTL流的输出和输出缓冲区可能重叠。

OTL流拥有flush()方法在输入缓冲区写满的时候将其自动刷新,也含有一系列的<<和>>运算符来读和写不同数据类型的对象。它最重要的优点是为任何类型的SQL语句和存储过程调用提供了统一的接口。应用开发者能够通过熟悉少量的语法和函数名称像使用C++流一样来使用OTL流。

在OTL流的内部拥有一个小型的解析器来解析所声明的绑定变量以及绑定变量的数据类型。因此,免去了使用特殊的绑定函数来绑定已声明的C/C++主机变量(hostvariables)。由于所有必须的缓冲区在OTL流中会自动创建,因此OTL仅仅需要被打开来进行读和写相应的数值。

OTL流接口要求使用OTL异常。OTL流操作都能可能抛掷otl_exception异常。因此为了拦截异常并阻止程序异常终止,必须使用try/catch块来包裹OTL流的使用代码。

OTL流的实现otl_stream具有较高的自动化功能,当OTL流的所有的输入变量被定义好(也就是输入缓冲区被填满),它会触发OTL流中的黑盒来执行。在黑盒执行的过程中输出缓冲区被填充。在执行完成后,输出缓冲区中的值能够从OTL流中被读取。如果执行的是一个SELECT语句并且返回多于输出缓冲区大小的行,那么在输出缓冲区的内容被读取后,OTL会自动读取下一批行记录到输出缓冲区。

5 主要类及方法说明

5-1 OTL主要类说明

类名

说明

otl_connect

负责创建和处理连接对象以及事务管理。

otl_stream

OTL流概念(参见第4小节)的具体实现。任何具有输入输出的SQL语句,匿名的PL/SQL块或者存储过程能够使用otl_stream类进行C++编程。

一般传统的数据库API拥有绑定主机变量到SQL语句中占位符的函数。因此,开发者需要在程序中声明host array,解析SQL语句,调用绑定函数,填充输入变量,执行SQL语句,读输出变量等。这些操作结束后又继续填充输入变量,执行SQL语句,读输出变量。

以上的所有事情能够在otl_stream中全部自动完成。otl_stream在保证性能的情况下提供了完全自动的与数据库的交互。

otl_stream的性能主要被缓冲区大小arr_size一个参数控制。缓冲区大小定义了插入表的逻辑行以及与数据库一次往反交互(one round-trip to the database)过程中从表或视图中查询的逻辑行。

otl_exception

可能代表数据库错误也可能代表OTL自身的错误。OTL函数如果在使用底层的数据库API时返回非0的错误码,则会产生otl_exception类型的异常。

4.1otl_stream的主要方法

5-2 类otl_stream的主要方法说明

主要方法

说明

otl_stream(

const int arr_size,

     const char* sqlstm,
     otl_connect& db,

     const char* ref_cur_placeholder=0,
     const char* sqlstm_label=0

);

构造函数,负责创建otl_stream对象并调用open()方法。

参数arr_size为流的缓冲区大小,

参数db为otl_connect连接对象的引用,

参数ref_cur_placeholder为reference cursor的占位符名称,

参数sqlstm_label为SQL语句的标签,用于取代异常描述消息otl_exception::stm中默认填充的SQL语句。

void open(
const int arr_size,

     const char* sqlstm,
     otl_connect& db,

     const char* ref_cur_placeholder=0,
     const char* sqlstm_label=0

);

打开SQL语句对其进行解析,所有的输入和输出变量都在流内部别动态分配,并且自动绑定到占位符。

void close(void);

#ifdef OTL_STREAM_POOLING_ON
 void close(

constbool save_in_stream_pool=true

);
#endif

关闭流。如果使用了流缓冲池,则可以使用带save_in_stream_pool参数的close()函数。如果参数save_in_stream_pool为true则流并不会真正关闭,而是被缓冲池回收。

int good(void);

测试流是否打开。

int eof(void);

测试是否所有的数据都已经从流中读取。

void rewind(void);

重绕流。如果流不含有任何输入变量,该方法将强制流执行SQL语句。

operator int(void);

流到int的转换操作符,返回从!eof()获得的流状态。它允许运算符>>返回!EOF的流状态并且能够在while()循环中像下面的代码那样使用:

while(s>>f1>>f2) {
  cout<<”f1=”<<f1<<”, f2=”<<f2<<endl;

}

 int is_null(void);

判断是否从流中获得NULL

void flush(void);
void flush // OTL/OCI8,8i,9i,10g only 
(

const int row_offset=0,                             

const bool force_flush=false

);

刷新流的输出缓冲区。这实际上意味着批量执行SQL语句,其执行的批量和流输出缓冲区中已经填充的SQL数相等。当输出缓冲区被填满时,缓冲区将被自动刷新。如果流的auto_commit标志被置上,则在刷新完毕后当前事务被提交。

OTL/OCI8,8i,9i,10g拥有另外一个版本的flush()方法。能够通过参数row_offset指定缓冲区刷新的开始位置,通过参数force_flush则能够指定是否在出现错误抛出otl_exception的情况下仍然强制继续刷新,忽略之前的错误。

long get_rpc(void);

获得处理的行数(Rows Processed Count, RPC)。

void set_column_type(

const int column_ndx,
const int col_type,

const int col_size=0

);

设置SELECT输出列的数据类型。

参数column_ndx为列的索引,如1,2,3…

参数col_type为OTL定义的数据类型常量(参见11.2小节)

参数col_size为新数据类型的大小,只被otl_var_char类型使用。

void set_commit(int auto_commit=0);

设置流的auto_commit标志。默认情况下,该标志被置上,即当输出缓冲区刷新时,当前的事务被自动提交。

注意流的auto_commit标志和数据库库的自动提交模型没有任何关系。

如果需要默认方式为不自动提交的流,则可以使用otl_stream的子类otl_nocommit_stream。

void set_flush(const bool auto_flush=true);

设置auto_flush标志。默认情况下auto_flush的值为true, 即如果缓冲区出现脏数据则在流的析构函数中刷新缓冲区。如果自动刷新标志被关闭,则需要使用close()方法或者flush()方法对流进行刷新。

注意该函数仅仅能够设置流的析构函数中是否自动刷新,并不是通常意义上的缓冲区刷新。

int setBufSize(const int buf_size);     

设置流缓冲区的大小。

4.2 otl_connect的主要方法

4-3 类otl_connect的主要方法说明

主要方法

说明

static int otl_initialize(

const int threaded_mode=0

);

初始化OTL环境。需要在程序最开始连接数据库之前调用一次。

参数threaded_mode指明程序是否运行在多线程环境,注意由于OTL并没有使用同步锁或者临界段,线程安全并不能够自动得到保证。

otl_connect(

const char* connect_str,

const int auto_commit=0

);

构造函数。

参数connect_str为连接字符串,OTL/OCIx风格的连接字符串为:

“USER/PASSWORD”(本地Oracle连接)

“USER/PASSWORD@TNS_ALLAS”(通过SQL*Net进行的远程连接)

参数auto_commit指明是否每一个在连接中执行的SQL语句都会自动提交。如果需要自动提交则为1,默认情况下为0表示不需要自动提交。注意该auto_commit参数和otl_stream的自动提交没有任何关系。

void rlogon(

const char* connect_str,

const int auto_commit=0

);

连接数据库。参数同构造函数。

void logoff(void);

断开数据库连接。

static int otl_terminate(void);

终止Oracle 8i/9i的OCI环境。需要在程序最后的数据库连接进行关闭后调用一次。该方法仅仅是OCI Terminate()调用的包装。通常在多线程环境中,为了终止主线程的控制,该方法需要被调用使得进程能够从OCI客户端的共享内存中脱离以及做其他事情。

void cancel(void);// OTL/OCI8/8i/9i only

取消连接对象或者数据库会话中的正在执行或者活动的操作或数据库调用。

void commit(void);

#if defined(OTL_ORA10G_R2)
   void commit_nowait(void);
#endif

同步或异步的方式提交事务。

void rollback(void);

回滚事务。

void auto_commit_off(void);

void auto_commit_on(void);

设置otl_connect对象的auto_commit标志。

void set_stream_pool_size(

const int max_size

=otl_max_default_pool_size

);

如果使用了流缓冲池,则该方法重新分配被默认的流缓冲池和之前的set_stream_pool_size()调用分配的所有资源。

void set_character_set(

const int char_set=SQLCS_IMPLICIT

);

如果使用了UNICODE,则该方法设置默认或国家的字符集:

SQLCS_IMPLICIT为数据库默认字符集。

SQLCS_NCHAR为数据库国家的字符集。

otl_connect& operator<<(const char* str);

发送字符串到otl_connect对象。如果该otl_connect对象还没有连接到数据库则字符串为"userid/passwd@db"格式的连接字符串,它使得otl_connect对象能够连接数据库。如果该otl_connect对象已经连接到数据库则字符串为静态SQL语句,该语句被马上执行。

otl_connect& operator<<=(const char* str);

发送字符串到otl_connect对象。otl_connect对象将保存该字符串并被下一个>>操作符使用。该字符串是一个拥有占位符并且能够发送到otl_stream对象的SQL语句。

otl_connect& operator>>(otl_stream& s);

发送之前使用操作符<<=保存的SQL语句到otl_stream对象。它使得该SQL语句被otl_stream打开。

注意如果并没有被>>=操作符保存的字符串,则字符串"*** INVALID COMMAND ***"被发送到otl_stream,最终会将导致解析错误,抛掷otl_exception异常。

long direct_exec(

const char *sqlstm,

int ignore_error

= otl_exception::enabled 

);

直接执行静态的SQL语句,返回处理的行数。

void syntax_check(

const char *sqlstm 

);

解析静态的SQL语句,如果出现SQL错误将抛掷otl_exception异常。

void server_attach(const char* tnsname=0, 
 const char* xa_server_external_name=0,
 const char* xa_server_internal_name=0,
#if defined(OTL_ORA_OCI_ENV_CREATE)
 bool threaded_mode=false
#endif);

附加到Oralcle。

void server_detach(void);

从Oracle分离。

void session_begin (

const char* username,

const char* password,

const int auto_commit=0,      

const int session_mode=OCI_DEFAULT

);

开始Oracle8会话。

void session_end(void);

结束Oracle8会话。

6 SQL的变量绑定和常量SQL

6.1 SQL的变量绑定

OTL拥有一个小型的解析器,负责在流的内部动态的为SQL语句、PL/SQL 块或存储过程调用中声明的绑定变量分配空间。OTL将Oracle传统的使用命名符号作为占位符的变量绑定机制进行了扩展,增加了数据类型说明,例如:

INSERT INTO my_table2values(:employee_id<int>,:supervisor_name<char[32]>)

OTL占位符中的支持的数据类型如表6-1所示。

表6-1 OTL占位符中支持的数据类型

bigint

64-bit signed integer, for binding with BIGINT table columns (or stored procedure parameters) in MS SQL Server, DB2, MySQL, PostrgeSQL, etc. ODBC, and DB2 CLI support this kind bind variables natively, so does OTL.

OCIs do not have native support for 64-bit integers, so OTL has to emulate it via string (<char[XXX]>) bind variables internally and does string-to-bigint and bigint-to-string conversion.

blob

for Oracle 8/9; BLOB

char[length]

OTL 4.0.118 and higher: char(length)

null terminated string; length is database dependent; for Oracle in [3,32545]; for ODBC it depends on the database backend and the ODBC driver; for DB2-CLI >2.

In Unicode OTL, this type of bind variable declaration means a null terminated Unicode character string (two bytes per character). Thelength field of this declarator needs to include an extra byte / Unicode character, in order to accomodate the null  terminator itself (for example char[11] can be used in binding with a VARCHAR(9) column), unless #define OTL_ADD_NULL_TERMINATOR_TO_STRING_SIZE is enabled.

charz

Same as char[] for OTL_ORA7, OTL_ORA8, OTL_ORA8I, OTL_ORA9I, OTL_ORA10G. Should be used only when PL/SQL tables of type CHAR(XXX) are used.

charz is actually a workaround for the following Oracle error: PLS-00418: array bind type must match PL/SQL table row type.Normally, the internal OCI datatype that is used to bind VARCHAR2/CHAR table columns / scalar PL/SQL procedure parameters works fine, except for PL/SQL tables of CHAR(XXX). PL/SQL engine does not like what OTL tries to bind with a PL/SQL table of CHAR(XXX).charz[] should be used instead of char[] in cases like that.

clob

for Oracle 8/9: CLOB, NCLOB

db2date

for DB2 DATEs; should be used in the binding of a placeholder with a DB2 DATE column in case of both

db2time

for DB2 TIMEs; should be used in the binding of a placeholder with a DB2 TIME column in case of both OTL/DB2-CLI and OTL/ODBC for DB2; requiresotl_datetime as a data container. See example91 for more detail.

double

8-byte floating point number

float 

4-byte floating point number

int 

32-bit signed int

ltz_timestamp

Oracle 9i TIMESTAMP WITH LOCAL TIME ZONE, in a combination with #define OTL_ORA_TIMESTAMP, and otl_datetime

nchar[length]

Same as char[] + otl_connect::set_character_set(SQLCS_NCHAR) for Oracle 8i/9i/10g only, under #define OTL_UNICODE., or #define OTL_ORA_UTF8. nchar[] is required only when both VARCHAR2/CHAR and NVARCHAR2/NCHAR need to be declared  in the same SQL statement, or PL/SQL block.

nclob

Same as clob + otl_connect::set_character_set(SQLCS_NCHAR) for Oracle 8i/9i/10g only, under #define

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OCL电路和OTL电路都是指功率放大器电路的两种不同设计架构。 首先,OCL(Output Capacitor-Less)电路是指在输出端不需要使用输出电容器的放大器电路。传统的功率放大器设计通常需要在输出端加入电容器以保护后级负载和直流偏置。然而,输出电容器会引入额外的损失和非线性因素。为了解决这个问题,OCL电路应运而生。OCL电路通过在电路设计引入补偿网络,使得放大器能够直接连接到负载,从而消除了输出电容器的需求。这种设计架构可以提高放大器的频率响应和线性度。 相比之下,OTL(Output Transformer-Less)电路是指在输出端不需要使用输出变压器的放大器电路。传统的电子管功率放大器通常使用输出变压器来提高电压增益和驱动负载。输出变压器虽然可以提供较高的电压放大倍数,但也会引入较大的重量、尺寸和成本。而OTL电路通过使用特殊的电路构造和驱动方式,使得放大器能够直接驱动低阻抗负载,从而避免了输出变压器的需求。OTL电路通常使用大功率晶体管或功率电子管来实现高功率输出。 总的来说,OCL和OTL电路都是为了解决传统功率放大器的限制而设计的创新架构。它们通过消除输出电容器和输出变压器的需求,提高了放大器的线性度、频率响应和稳定性。这些设计在无线电、音频和音响应用得到广泛应用,以提供更高质量的音频放大和放大器性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值