Rapidize the Sybase C program to Oracle Pro * C program

xiaoxiao2021-03-06  38

Originally published in vckbase, take everyone to throw bricks to quickly transplant the Sybase C program to Oracle Pro * C procedures

Download source code [no space, download connection still use vckBase] 1. Introduction, many of the present fewer units in the system transformation upgrade, facing the database used by the applications developed by each independent department in order to adapt to the data concentration Demand is convenient for future data mining and other higher level applications. In the process of unified database, how to quickly and efficiently convert the existing database-based programs, especially those developed by C / C , especially using C / C , and become a lot of units. The problem. Of course, the RAD-developed procedures can basically do not need to make changes, can achieve the purpose. For how to quickly transplant the Sybase C program to Oracle Pro * C, this article will indicate a direction and give a rough framework. In this paper, you will be thrown into jade, I hope you guidance. (Plan a conversion series, look at how to react) Second, the principle Sybase's C program is converted to Oracle's Pro * C program, there is a lot of advantages compared to other types of conversions (forgive me, I may be the simplest one. Conversion):

The Sybase program uses a C function call, which brings a big convenience to convert the Sybase program to any of the database programs! Just use the syntax of the destination database, you can realize the Sybase function used by the old program! And do not need to modify any logical aspects of the original C program! Oracle's Pro * c provides a dynamic SQL development method, which brings great convenience to transplant. Oracle Pro * C is also providing process multi-connection. When Oracle 9 uses Parse = FULL compilation option, C's defined variables can be used directly in Exec SQL, which is a lot of writing to the program.

There are other advantages, no longer listed. Third, achieve nonsense, turn into the topic: Several major functions for Sybase, the following summary, specific implementation reference source code:

Dbinit (): This function initializes some variables for database operations. Some usernames, password settings, not too much. easier. DBOPEN (): This function actually performs a database connection, in the connection process, I set the global variable allopenProcess to save all connection pointers and generate a connection string to identify the connection. Saved in global variables because Sybase functions Dbexit have no input parameters. DBCMD (): This function performs an analysis of SQL statements for further judgment. DBEXEC (): This function performs command execution (not clear why Sybase is separated from DBCMD). Command (INSERT, UPDATE, DELETE) without return result sets is performed directly through the syntax of Exec SQL At Execute Immediate. The method of using Oracle dynamic SQL4 is processed with the SELECT that has the result set. Because the relationship between time and the old program, the implementation of this function is only for the string of the incoming full SQL statement. DBRESULTS (): Judging the return result. Dbbind (): Binds the address of the stored value and determines if the incoming type is correct. Since the old procedure only uses the ntbstringbind type, this type is also processed in the example. DBNUMCOLS (): Returns the number of data columns, which is valid when the statement type is SELECT. DBNEXTROW (): Get the next data value and fill in the address space bound by DBBIND. The relevant data conversion is required based on the source type select_dp-> t [], and the target type. DBDEAD (): Judging whether the database connection is normal. Tested in a manner that is taken from the Dual table. Dbexit (): Exit the database connection.

There are still many other functions, but because I don't use it, I don't do it. four. The way the transplantation is very simple, and the original C / C file is removed from the C / C "#include" sybdb.h ", etc., is removed from the Sybase header file, replaced with #include" database_op.h "in the attachment, At the same time, add Database_OP.cxx in the attachment to the project, plus the appropriate Compilation Statement (Proc), then remove the LIB of Sybase, add Oracle's lib: ORASQL9.LIB. The program can be completed in the case where the source program is basically not modified! Of course, if your Sybase program uses non-ntbstringbind type, add relevant processing methods to the CXX file! good luck! Welcome. 5. Let's sum up some small skills used in the development process, and laugh. How to make full use of the Visual C development environment for Pro * C program development: I believe that all the integrated development environments for Visual C are more familiar, don't tell me that the C / C program under UNIX is still using VI, UltraEdit, Editplus. ! Of course, if you insist that I don't object, but you will not have to turn the time to turn the page. Oracle's Pro * C procedures typically end with PC. The procedure ended with the PC, can't be displayed in the integrated development environment of the Visual C in the syntax of C / C ! It's just a white paper black word. Unlike UltraEdit, you can customize the PC file according to C / C syntax display (in the WordFile.txt file in the UltraEdit installation directory, "PC" can be added to the back plus "PC") (Maybe VC has this function, but I didn't find). How to do it? Simple, modify the PC file suffix is ​​CXX, at this time, the file is displayed according to the C / C syntax! At this time, set the file attribute page (selected in the Workspace in the VC development environment, pressing the always use customer in General in Alt F7) to select the status, CURSTOM builds under Commands / Outputs under the CURSTOM Builds / Outputs under Oracle EXAMPLE Enter the corresponding compilation option. Remember to modify the corresponding PC suffix to the CXX suffix.

Below is some source code: database_op.cxx / * database_op.cxx is responsible for compatible with Sybase and Oracle to the database * / # include "stdio.h" #include "stdlib.h" #include "string.h" #include "Database_oP .h "#ifdef SYBASE_PLATFORM / ** no action * / # endif # ifdef MSSQL_PLATFORM # endif # ifdef ORACLE_PLATFORMEXEC SQL INCLUDE sqlca; EXEC SQL INCLUDE sqlda; EXEC SQL WHENEVER NOT FOUND CONTINUE; EXEC SQL WHENEVER SQLWARNING CONTINUE; EXEC SQL WHENEVER SQLERROR CONTINUE; char dyn_statement [1024]; SQLDA * select_dp = NULL; #define MAXCOLNUM 126 # define MAXCOLVALUE 1024char chValueBuff [MAXCOLNUM] [MAXCOLVALUE] = {0}; / * Maximum lengths of the _names_ of theselect-list items or indicator variables . * / # define MAX_VNAME_LEN 80 # define MAX_INAME_LEN 80typedef struct Securepair {struct Securepair * next; char * labelname; char * labelvalue;} SECLABELS; typedef struct loginrec {char chLogName [256]; char chLogPass [256];} LOGINREC_STR; enum SQLTYPE_ENUM {SQL_NULL = 0, SQL_SELECT, SQL_INSERT, SQL_UPDATE, SQL_DELETE}; struct dbprocess {SQL_Context CTX; char conname [20]; / * The first SQL statement type, including the query select insert update delete, * / / * to find * / enum sqltype_enum sqltype; long rowindex; / * after performing this SQL, the number of rows that are taken out after this SQL is found in SQLDATA The index that needs to be taken out * / long rownum; / * Number of rows obtained in this SQL * / long colnum; / * Current column number * / long sqlerror; / * SQL statement error number * / void * ppbuff [maxpointnum]; / * The memory address of the field is currently bound * / long pBuffType [maxpointnum]; / * The current SQL statement value, change the above RowIndex, Rownum, Colnum * / char SqlData [SqlDatalen] after execution, change, TypeDef struct dbprocess dbproc_str; Dbproc_str * allopenprocess [20] = {0}; ehandlefunc ehandfunc = 0; MHANDLEFUNC MHANDFUNC = 0; retcode dbinit (void) {INT i; if (select_dp) Return succeed; if ((SELECT_DP =

sqlald (MAXPOINTNUM, MAX_VNAME_LEN, MAX_INAME_LEN)) == (SQLDA *) 0) {fprintf (stderr, "Can not allocate memory for select descriptor."); return FAIL;} select_dp-> N = MAXPOINTNUM; / * Allocate the pointers to The indeicator var. * / for (i = 0; i i [i] = (short *) malloc (SIZEOF (Short)); select_dp-> v [i ] = (char *) Malloc (1);} Return succeed;} void errhandlefunc () {if (ehandfunc) (0, 0, 0, 0, "," ");} void Mhandlefunc () {IF (* MHANDFUNC) (0, 0, 0, 0, "," ",", 0); Ehandlefunc DBERRHANDLE (Ehandlfunc = handler; / * EXEC SQL WHENEVER SQLERROR DO ERRHANDLEFUNC (); * / return 0;} mHANDLEFUNC dbmsghandle (mHANDLEFUNC handler) {mhandfunc = handler; / * EXEC SQL WHENEVER SQLWARNING DO mhandlefunc (); *** / return 0;} void * dblogin (void) {LOGINREC_STR * rec; REC = (LoginRec_str *) Malloc (sizeof (loginRec_str)); if (null == REC) RETURN Rec; Memset (REC, 0, Si ZEOF (LoginRec_Str)); RETURN Rec;} RETCODE DBSETLNAME (loginRec_str * lptr, char * values, int type) {if (null == lptr || null == values) Return Fail; if ((DBSETUSER! = Type) && (DBSETPWD! = TYPE)) Return Fail; if (dbsetuser == type) {if (strlen> = sizeof (lptr-> chlogname)) Return Fail; Strcpy (lptr-> chlogname, values);} IF DBSETPWD == TYPE) {IF (Strlen)> = sizeof (lptr-> chlogpass) Return Fail; Strcpy (lptr-> chlogpass, value);} Return succeed;

} / * Database connection attempt within the function * / DBPROCESS * dbopen (LOGINREC_STR * logon_ptr, char * servername) {int iLen, iIndex; DBPROC_STR * dbprocess; EXEC SQL BEGIN DECLARE SECTION; VARCHAR username [256]; VARCHAR password [256 ]; VARCHAR dbstring [256]; EXEC SQL END DECLARE SECTION; if (NULL == logon_ptr) return NULL; dbprocess = (DBPROC_STR *) malloc (sizeof (DBPROC_STR)); if (NULL == dbprocess) return NULL; memset ( dbprocess, 0, sizeof (DBPROC_STR)); iLen = sizeof (AllOpenProcess) / sizeof (DBPROC_STR *); for (iIndex = 0; iIndex conname, "conn% D", IIndex; break;}} = {free (dbprocess); dbprocess = null;} / * Try !!!!!!!!! * / STRNCPY ((char *) Username.arr, logon_ptr-> chlogname, sizeof (username.arr)); username.len = strlen ((char *) Username.arr); STRNCPY ((char *) Password.arr, logon_ptr-> chlogpass, sizeof (password.arr)); password.len = strlen ((char *) password.arr); EXEC SQL CONTEXT ALLOCATE: dbprocess-> ctx; EXEC SQL CONTEXT USE: dbprocess-> ctx; if (NULL == servername) {EXEC SQL CONNECT: username IDENTIFIED BY: password AT: dbprocess-> connName;} else {strncpy (( char *) dbstring.arr, servername, sizeof (dbstring.arr)); dbstring.len = strlen ((char *) dbstring.arr); EXEC SQL CONNECT: username IDENTIFIED BY: password AT: dbprocess-> connName USING: dbstring }} {Printf ("/ n% D% s / n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); Printf ("Connect Error!"); Return Fail;} return DBPROCESS *) DBPROCESS;

} void dbloginfree (loginRec_str * loginptr) {if (null! = loginptr) {MEMSET (loginptr, 0, sizeof (loginRec_str)); free (loginptr);}} / * This function is only copied, make a simple command check * / RETCODE DBCMD (dbproc_str * dbproc, const char * cmdstring) {long l_len; char * pselect, * pinsert, * pupdate, * pdlete, * pmin; if (null == dbproc || null == cmdstring) Return Fail; / * Only copy commands, make simple commands! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! * / l_len = Strlen (cmdstring); if (l_len> = sizeof (dbproc-> sqldata)) Return Fail; Memcpy (dbproc-> sqldata, cmdstring, l_len 1); strupr (dbproc-> sqldata); dbproc-> COLNUM = 0; dbproc-> rowindex = 0; dbproc-> rownum = 0; MEMSET (dbproc-> ppbuff, 0, sizeof (dbproc-> ppbuff); Memset (dbproc-> pbufftype, 0, sizeof (dbproc-> PBUFFTYPE)); / * Analyze command type * / pselect = strstr (dbproc-> sqldata, "select"); pinsert = strstr (dbproc-> sqldata, "insert"); pupdate = strstr (dbproc-> sqldata, "Update "); pdlete = strstr (dbproc-> sqldata," delete "); Pmin = dbproc-> SQLData strln (dbproc-> sqldata); dbproc-> sqltype = SQL_NULL; IF ((pselect) && (pselect sqltype = sql_select;} if (pinsert sqltype = SQL_INSERT;}} && (Pupdate SQLTYPE = SQL_UPDATE;} IF (PDELETE) && (PDELETE SQLTYPE = SQL_DELETE;} IF (SQL_NULL ==

dbproc-> sqltype) {dbproc-> sqlerror = -1; return FAIL;} return SUCCEED;} / * This function execution command * / RETCODE dbsqlexec (DBPROC_STR * dbproc) {int i, null_ok, precision, scale; EXEC SQL BEGIN DECLARE SECTION; VARCHAR chSqlStr [SQLDATALEN]; EXEC SQL END DECLARE SECTION; if (NULL == dbproc) return FAIL; if (SQL_NULL == dbproc-> sqltype) return FAIL; dbproc-> colnum = 0; dbproc-> rowindex = 0; dbproc-> rownum = 0; dbproc-> sqlerror = 0; MEMSET (dbproc-> ppbuff, 0, sizeof (dbproc-> ppbuff); Memset (dbproc-> pbufftype, 0, sizeof (dbproc-> pBuffType) ); strcpy (chsqlstr.arr, dbproc-> sqldata); chsqlstr.len = strlen (chsqlstr.arr); if (sql_insert == dbproc-> sqltype || SQL_UPDATE == dbproc-> sqltype || SQL_DELETE == dbproc > sqltype) {EXEC SQL CONTEXT USE: dbproc-> ctx; EXEC SQL AT: dbproc-> connName execute immediate: chSqlStr; dbproc-> sqlerror = sqlca.sqlcode; if (dbproc-> sqlerror <0) {printf ( "/ N% s / n ", sqlca.sqlerrm.sqlerrmc); Exec SQL ROLLBACK; RETURN FAIL;} dbproc-> rownum = SQLCA.SQLERRD [2]; EXEC SQ L Context use: dbproc-> ctx; exec SQL At: dbproc-> conname commit; return succeed;} / * adoption of Cursor cursor mode * / / * adopts dynamic SQL 4 method * / if (SQL_SELECT == dbproc-> sqltype) {SQLCA.SQLCODE = 0; if (Sqlca.sqlcode! = 0) {Printf ("/ NDECLARE ERR =% D / N% S / N", Sqlca.sqlcode, Sqlca.sqlerrm.sqlerrmc); Return Fail;} EXEC SQL Context Use: dbproc-> CTX; Exec SQL At: dbproc-> conname prepare sss from: chsqlstr; if (Sqlca.sqlcode! = 0) {Printf ("/ nprepare err =% d / n% s / n", Sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); RETURN FAIL;

} EXEC SQL Context Use: dbproc-> CTX; Exec SQL At: dbproc-> CONNNAME DECLARE CCC CURSOR for SSS; IF (Sqlca.sqlcode! = 0) {Printf ("/ NDECLARE CCC Err =% D / N% S / n ", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return fail;} Exec SQL Context Use: dbproc-> ctx; Exec SQL At: dbproc-> conname open ccc; if (sqlca.sqlcode! = 0) {Printf ("/ Nopen CCC Err =% D / N% S / N", Sqlca.sqlcode, Sqlca.sqlerrm.sqlerrmc); Return Fail;} SELECT_DP-> n = maxpointnum; Exec SQL Context Use: dbproc-> CTX; Exec SQL AT: DBPROC-> CONNNAME DESCRIBE SELECT LIST for SSS INTO SELECT_DP; DBPROC-> SQLERROR = Sqlca.sqlcode; if (dbproc-> sqlerror <0) {printf ("/ Nerr =% D / N% S / N", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CONTEXT USE: dbproc-> ctx; EXEC SQL AT: dbproc-> connName CLOSE CCC; EXEC SQL CONTEXT USE: dbproc-> ctx; EXEC SQL AT: dbproc-> connName Rollback; Return Fail;} IF (select_dp-> f <0) {Printf ("/ Nerr =% D / N% S / N", Sqlca.sqlcode, Sqlca.sqlerrm.sqlerrmc); Exec SQL Context Use: dbproc- > CTX; EXEC SQL AT: DBPROC-> CONNNAME CLOSE CCC; Exec SQL Context Use: dbproc-> CTX; EXEC SQL At: dbproc-> conname rollback; returnif;} if (select_dp-> f> maxpointnum) {printf ("/ Nerr = % D / N% S / N ", Sqlca.sqlcode, Sqlca.sqlerrm.sqlerrmc); Exec SQL Context Use: dbproc-> CTX; Exec SQL At: dbproc-> conname close ccc; exec SQL Context use: dbproc-> CTX; EXEC SQL At: dbproc-> conname rollback; returnif;} select_dp-> n = select_dp-> f; dbproc-> colnum = select_dp-> n; / * cannot be directly taken to all rows, so it is directly adopted Current way to add 1 method * / dbproc-> rowNum = dbproc-> rowindex 1;

For (i = 0; i f; i ) {/ * char Title [max_vname_len]; * / / * Turn Off High-Order Bit Of Dattype (in this Example, IT Does Not * / / * Matter IF The column is not null). * / SQLNUL (SQLNUL (SQLNUL (SELECT_DP-> T [I]), (unsigned short *) & (select_dp-> t [i]), & null_ok); / * varchar2 1 Char [n] Number 2 Char [N] (n <= 22) Integer 3 int float 4 float string 5 char [n 1] varnum 6 char [n] (n <= 22) Decimal 7 Float Long 8 char [n ] VARCHAR 9 Char [N 2] Rowid 11 Char [N] Date 12 Char [N] Varraw 15 Char [N] RAW 23 Unsigned Char [N] Long Raw 24 Unsigned Char [N] Unsigned 68 Unsigned Int Display 91 CHAR [ N] long varchar 94 char [n 4] long varraw 95 unsigned char [n 4] char 96 char [n] charf 96 char [n] charz 97 char [n 1] * / switch (select_dp-> t [select_dp-> t [SELECT_DP-> T I]) {/ * char datatype: No change, innene, except * / / * possibly for to_char conversions. * / case 1: break; / * number datatype: use sqlprc () to extract precision and Scale. * / Case 2: SQLPRC ((unsigned Long *) & (select_dp-> l [i]), & precision, & scale); / * allow for maximum size of number. * / if (precision == 0) precision = 40; / * Also Allow for Decimal Point and Possible Sign. * / / * Convert Number Dattype to float if scale> 0, * / / * int terwise. * / if (scale> 0) SELECT_DP-> L [i] = sizeof (float); else select_dp-> l [ I] = sizeof (int); break; case 8: / * long datatype * / select_dp-> l [i] = 240; break; case 11: / * rowid DataType * / case 104: / * universal Rowid DataType * / SELECT_DP-> L [I] = 18; Break;

Case 12: / * Date DataType * / SELECT_DP-> L [I] = 9; Break; Case 23: / * Raw DataType * / Break; Case 24: / * long Raw DataTyPE * / SELECT_DP-> L [i] = 240; Break;} / * allocate space for the select-list data value.sqlald () * / / / * RESERVES A POINTER LOCATION for V [i] But does not allocate * / / * the full space for the pointer. * / IF (select_dp-> t [i]! = 2) {SELECT_DP-> V [I] = (char *) realloc (select_dp-> v [i], select_dp-> l [i] 1);} else SELECT_DP -> v [i] = (char *) Realloc (select_dp-> v [i], select_dp-> l [i]); / * Print Column Headings, Right-Justify Number Column Headings. * / / * Copy Temporary Buffer In Case Name Is Null-Terminated * / / / / / / * STRNCPY (Title, SELECT_DP-> S [i], select_dp-> c [i]); if (select_dp-> t [i] == 2) IF (Scale> 0) Printf ("%. * S", select_dp-> L [i] 3, title); Else Printf ("%. * S", select_dp-> l [i], title); else printf ("% -. * s ", select_dp-> l [i], title); * / / * COERCE All DataTypes Except for long raw and number to character. * / if (select_dp-> t [i]! = 24 && select_dp- > T [I]! = 2) SELECT_DP-> T [I] = 1; / * COERCE The DataTypes of NumBers to float or int * / / / * depending on the scale. * / if (select_dp-> t [i] == 2) {IF (scale> 0) SELECT_DP-> T [i] = 4; / * float * / else select_dp-> t [i] = 3; / * int * /}}} Return succeed;} / * This function determines the database return result, operation SUCCEED NO_MORE_RESULTS DBPROC_STR the specific field * / RETCODE dbresults (DBPROC_STR * dbproc) {if (NULL == dbproc) return NO_MORE_RESULTS; if (dbproc-> sqlerror <0) return NO_MORE_RESULTS;! if (dbproc-> rowindex = dbproc-> rownum Return succeed; Return No_More_Results;} / * binding value,

Binding the stored value bit * / retcode dbbind (dbproc_str * dbproc, int colnum, int number, dbint varlen, byte * destvar) {if (colnum <= 0) Return Fail; if (colnum> dbproc-> colnum) Return Fail ; if (colnum> = maxpointnum) Return Fail; / * currently only support this type * / if (ntbstringbind! = varType) {printf ("/ N !!!!!!!!!!!!!!!!!!! !!!!!!!! / n / n ", vartype); exit (0); / * !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * /} dbproc-> ppbuff [colnum - 1] = destvar; dbproc-> PBuffType Colnum - 1] = VARTYPE; RETURN FAIL;} / * Get this execution Return how many columns * / int dbnumcols (dbproc_str * dbproc) {return dbproc-> colnum;} / * assigns the next value to the bound variable * / STATUS dbnextrow (DBPROC_STR * dbprocess) {int i; if (NULL == dbprocess) return NO_MORE_ROWS; / * FETCH each row selected and print the column values ​​* / EXEC SQL CONTEXT USE: dbprocess-> ctx; EXEC SQL WHENEVER. NOT Found Goto End_Select_Loop; Exec SQL Context Use: DBProcess-> CTX; Exec SQL At: dbProcess-> CONNNAME FETCH CCC Using Descriptor SELECT_DP; / * Since Each Variable Returned Has Been COERCED TO a character string, * / / * int, or float us routine * / / * Just Prints out the value on the terminal. * / for (i = 0; i f; i ) ) {if (null == dbprocess-> ppbuff [i]) Continue; if (* select_dp-> i [i] <0) {switch (dbProcess-> PBuffType [i]) {case ntbstringbind: / * if (SELECT_DP -> t [i] == 4) Sprintf ("% - * c", (int) SELECT_DP-> L [i] 3, '' '); Else Printf ("% - * c", (int) (INT) SELECT_DP-> L [I], '' '); * / strcpy (dbProcess-> PPBuff [I], ""; Break; Case Charbind: * ((char *) dbprocess-> PPBuff [i]) = 0; BREAK;

Case INTBIND: * (INT *) DBPROCESS-> PPBuff [I]) = 0; Break; default: / * * Error! Not support type! * / dbprocess-> sqlerror = -50001; Return NO_MORE_ROWS;}} else { Switch (dbProcess-> PBuffType [i]) {copy ntbstringbind: if (select_dp-> t [i] == 3) / * int Dattype * / sprintf (dbProcess-> PPBuff [i], "% * D", INT) SELECT_DP-> L [I], * (int *) SELECT_DP-> V [I]); Else IF (SELECT_DP-> T [I] == 4) / * float datatype * / sprintf (dbProcess-> PPBuff [i], "% *. 2f", (int) SELECT_DP-> L [I], * (float *) SELECT_DP-> V [I]); else / * character string * / sprintf (dbProcess-> PPBuff [ I], "% - *. * s", (int) SELECT_DP-> L [i], (int) SELECT_DP-> L [I], select_dp-> v [i]); break; case charbind: * ( (char *) DBPROCESS-> PPBuff [i]) = * (char *) SELECT_DP-> V [I]; Break; Case INTBIND: * ((int *) dbprocess-> ppbuff [i]) = * (int *) ) select_dp-> V [i]; break; default:!! / * * ERROR not support type * / dbprocess-> sqlerror = -50001; return NO_MORE_ROWS;}}} return SUCCEED; end_select_loop: dbprocess-> rownum = dbprocess- > RO WINDEX; RETURN NO_MORE_ROWS;} / * Judging whether the connection is normal * / dbool dbdead (dbproc_str * a) {char chbuff [8]; chbuff [0] = '' / 0 '; EXEC SQL WHENEVER NOT FOT GOTO END_SELECT_LOOP; EXEC SQL Context Use: A-> CTX; EXEC SQL AT: A-> CONNNAME SELECT '' A '' INTO: ChBuff from Dual; IF ('' A '! = ChBuff [0]) {Return Fail;} Return Succeed END_SELECT_LOOP: RETURN FAIL;} / * This function releases the memory generated by DBOPEN, while disconnecting the database connection requires further consideration! * / void dbexit (void) {INT I, ILEN, IINDEX; EXEC SQL WHENEVER SQLERROR Continue; Ilen = SizeOf (AllopenProcess) / sizeof (dbproc_str *); for (IIndex =

转载请注明原文地址:https://www.9cbs.com/read-66608.html

New Post(0)