亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Pro*C介紹-內(nèi)嵌SQL

系統(tǒng) 2004 0

概要

內(nèi)嵌SQL是結(jié)合高級(jí)語言如C/C++的計(jì)算能力和SQL數(shù)據(jù)庫處理能力的一種方法。它允許你在程序中執(zhí)行任意的SQL語句。Oracle的嵌入SQL環(huán)境稱為Pro*C。

Pro*C程序分兩步編譯。首先,Pro*C的預(yù)編譯器識(shí)別出嵌入在程序中的SQL語句,并將這些語句轉(zhuǎn)換為對(duì)SQL運(yùn)行時(shí)庫(SQL runtime library)中功能(functions)的適當(dāng)調(diào)用。輸出是純C/C++代碼和未被處理的純C/C++代碼。然后,用常規(guī)C/C++編譯器編譯代碼并生成可執(zhí)行程序。更詳細(xì)的內(nèi)容請(qǐng)參考 Demo程序

Demo程序

Pro*C語法


SQL

所有SQL語句都要以 EXEC SQL 開始,并用分號(hào)" ; "結(jié)束。SQL語句可以放置在C/C++塊中的任何地方,但可執(zhí)行的(SQL)語句應(yīng)該在聲明語句后面。例:

      {

    int a;

    /* ... */

    EXEC SQL SELECT salary INTO :a

             FROM Employee

             WHERE SSN=876543210;

    /* ... */

    printf("The salary is %d\n", a);

    /* ... */

}
    


預(yù)處理指令

能夠在Pro*C中正常工作的C/C++預(yù)處理指令是 #include #if 。Pro*C不能識(shí)別 #define 。下面的代碼是錯(cuò)誤的:

      #define THE_SSN 876543210

/* ... */

EXEC SQL SELECT salary INTO :a

         FROM Employee

         WHERE SSN = THE_SSN;/* INVALID */
    

語句標(biāo)號(hào)

可以在SQL中跳轉(zhuǎn)到C/C++標(biāo)記

          EXEC SQL WHENEVER SQLERROR GOTO error_in_SQL;

    /* ... */

error_in_SQL:

    /* do error handling */
    

我們會(huì)在后面的 錯(cuò)誤處理 一節(jié)中講到有關(guān) WHENEVER 的含意。

錯(cuò)誤處理 一節(jié)中講到有關(guān) WHENEVER 的含意。

宿主變量


基礎(chǔ)

宿主變量是連接宿主程序與數(shù)據(jù)庫的關(guān)鍵。宿主變量表達(dá)式必須視為(resolve to)左值(能被賦值)。你可以像聲明普通C變量一樣,按著C的語法規(guī)則聲明宿主變量。宿主變量的聲明可以放置在任何C變量聲明可以放置的地方。(C++用戶需要使用" DECLARE SECTION ";參考 C++ Users ) Oracle可以使用的C數(shù)據(jù)類型包括:

C++ Users ) Oracle可以使用的C數(shù)據(jù)類型包括:
  • char
  • char[ n ]
  • int
  • short
  • long
  • float
  • double
  • VARCHAR[ n ] - 它是能被Pro*C的預(yù)編譯器識(shí)別的預(yù)處理類型(psuedo-type)。它用來 表示由空白填充(blank-padded,譯注:' \0 ')的變長字符串。Pro*C預(yù)編譯器會(huì)把它轉(zhuǎn)換為有一個(gè)2字節(jié)(byte)長的域和一個(gè)n字(byte)長的字符數(shù)組的結(jié)構(gòu)體。

你不能指定寄存器存儲(chǔ)類型(譯注:指針)為宿主變量。

可以在SQL表達(dá)式中使用冒號(hào)" : "做前綴來引用一個(gè)宿主變量,但不能在C表達(dá)式中用分號(hào)做前綴。當(dāng)使用字符串作為宿主變量時(shí),必須省略引用;Pro*C明白你正指定一個(gè)基于宿主變量聲明類型的字符串(譯注:這句的意思是,當(dāng)定義一個(gè)字符串做為宿主變量時(shí) char *str="string" ,在嵌入SQL中使用時(shí),要省略" * "而不是 *str )。不能將C函數(shù)調(diào)用和多數(shù)的指針計(jì)算表達(dá)式作為宿主變量使用,即使它們確實(shí)被解釋為左值。下面的代碼同時(shí)說明了合法和不合法的宿主變量的引用:

    int deptnos[3] = { 000, 111, 222 };

int get_deptno() { return deptnos[2]; }

int *get_deptnoptr() { return &(deptnos[2]); }

int main() 

{

    int x; char *y; int z;

    /* ... */

    EXEC SQL INSERT INTO emp(empno, ename, deptno)

        VALUES(:x, :y, :z); /* LEGAL */

    EXEC SQL INSERT INTO emp(empno, ename, deptno)

        VALUES(:x + 1,  /* LEGAL: the reference is to x */

               'Big Shot',  /* LEGAL: but not really a host var */

               :deptnos[2]);/* LEGAL: array element is fine */

    EXEC SQL INSERT INTO emp(empno, ename, deptno)

        VALUES(:x, :y,

               :(*(deptnos+2)));/* ILLEGAL: although it has anlvalue */

    EXEC SQL INSERT INTO emp(empno, ename, deptno)

        VALUES(:x, :y,

               :get_deptno());  /* ILLEGAL: no function calls */

    EXEC SQL INSERT INTO emp(empno, ename, deptno)

        VALUES(:x, :y,

               :(*get_depnoptr())); /* ILLEGAL: although it has an lvalue */

    /* ... */

}
  


指針

可以在SQL表達(dá)式中使用普通C語法聲明的指針。通常使用一個(gè)冒號(hào)做前綴:

      int*x;

/*...*/

EXEC SQL SELECT xyz INTO :x FROM ...;
    

這個(gè) SELECT 語句的結(jié)果會(huì)寫入 *x ,而不是 x


結(jié)構(gòu)

結(jié)構(gòu)同樣可以作為宿主變量使用,如下面例子:

      typedef struct {

    char name[21];/* one greater than column length; for '\0' */

    int SSN;

} Emp;

/* ... */

Emp bigshot;

/* ... */

EXEC SQL INSERT INTO emp (ename, eSSN)

    VALUES (:bigshot);
    


數(shù)組

像下面這樣使用宿主數(shù)組:

      int emp_number[50];

char name[50][11];

/* ... */

EXEC SQL INSERT INTO emp(emp_number, name)

    VALUES (:emp_number, :emp_name);
    

這樣會(huì)一次插入所有的50個(gè)元素(tuples)。

數(shù)組只能是一維數(shù)組。例子中的 char name[50][11] 可能看起來與這個(gè)規(guī)則矛盾,然而,Pro*C實(shí)際上把 name 視為一維字符串?dāng)?shù)組而不是二維字符數(shù)組。也可以使用結(jié)構(gòu)數(shù)組。

當(dāng)使用數(shù)組存放查詢結(jié)果時(shí),如果宿主數(shù)組的大小( n )小于實(shí)際查詢后返回的結(jié)果數(shù)量時(shí),那么只有(查詢出來的)前 n 個(gè)結(jié)果被填入宿主數(shù)組。


指示器變量

指示器實(shí)際上是附在宿主變量后的" NULL 標(biāo)記"。每一個(gè)宿主變量都可以選擇性的關(guān)聯(lián)到一個(gè)指示器變量上。指示器變量的類型必須為2字節(jié)整形值( short 類型),而且必須緊隨在宿主變量后且用冒號(hào)做為前綴。你也可以使用關(guān)鍵字 INDICATOR 放在宿主變量和指示器變量之間。例如:

      short indicator_var;

EXEC SQL SELECT xyz INTO :host_var:indicator_var

    FROM ...;

/* ... */

EXEC SQL INSERT INTO R

    VALUES(:host_var INDICATOR :indicator_var, ...);
    

SELECT INTO 子句中使用的指示器變量可以用來檢查返回給宿主變量的值為空(NULL)或被截?cái)嗟牡那闆r。Oracle能夠賦給指示器變量的值具有下面各項(xiàng)意義:

-1 字段(譯注:原文為column,意為該字段的列)值為 NULL ,宿主變量的值不確定。
0 Oracle把完整的字值賦給了宿主變量。
>0 Oracle把被截?cái)嗟淖侄沃蒂x給了宿主變量。指示器變量返回的整形值是字段的原始長度。
-2 Oracle把被截?cái)嗟淖侄沃蒂x給了宿主變量,但原字段值是不確定的。(譯注:這種情況可能是數(shù)值型的值被切斷后不能確定原始值)

你也可以在 INSERT UPDATE VALUES SET 子句中使用指示器變量指明用于輸入的宿主變量為 NULL 值。你的程序可以賦給指示器變量的值具有如下各項(xiàng)意義:

-1 Oracle會(huì)忽略宿主變量的值并給字段賦一個(gè) NULL 值。
>=0 Oracle會(huì)將宿主變量的值賦給字段。


數(shù)據(jù)類型同等化

Oracle認(rèn)識(shí)兩種數(shù)據(jù)類型:內(nèi)部類型和外部類型。內(nèi)部數(shù)據(jù)類型指示Oracle在數(shù)據(jù)庫表中如何存儲(chǔ)字段。外部數(shù)據(jù)類型指示如何格式化存儲(chǔ)在宿主變量中用于輸入或輸出的值。在預(yù)編譯期,每一個(gè)宿主變量會(huì)被賦予一個(gè)默認(rèn)的Oracle外部數(shù)據(jù)類型。數(shù)據(jù)類型同等化允許你重載默認(rèn)的同等化,并允許你控制Oracle輸入數(shù)據(jù)的解釋和輸出數(shù)據(jù)的格式化。

同等化通過使用 VAR 表達(dá)式實(shí)現(xiàn)基于從變量到變量的轉(zhuǎn)換。語法是:

      EXEC SQL VAR <host_var> IS <type_name> [ (<length>) ];
    

舉例來說, 假設(shè)你想從 emp 表中查詢雇員名子,然后傳給一個(gè)需要C類型(以' \0 '結(jié)尾的)字符串的程序,你不需要顯式的用' \0 '來結(jié)束這個(gè)名子。如下面所示,簡單地將宿主變量同等化為外部數(shù)據(jù)類型 STRING

      char emp_name[21];

EXEC SQL VAR emp_name IS STRING(21);
    

emp 表中 ename 字段的長是20字符(character),因此,需要分配21字符(character)以適應(yīng)' \0 '結(jié)束符。Oracle的外部數(shù)據(jù)類型 STRING 是為C類型字符串特別設(shè)計(jì)的接口。當(dāng)把 ename 字段值傳給 emp_name 時(shí),Oracle會(huì)自動(dòng)用' \n '結(jié)尾。

也可以使用 TYPE 語句將用戶自定義數(shù)據(jù)類型同等化為Oracle外部數(shù)據(jù)類型。語法是:

      EXEC SQL TYPE <user_type> IS <type_name> [ (<length>) ] [REFERENCE];
    

可以聲明一個(gè)用戶自定義類型的指針,顯式的如指向標(biāo)量或結(jié)構(gòu)的指針,或隱式的如數(shù)組,然后在 TYPE 表達(dá)式中使用這個(gè)類型。這種情況下,你需要在表達(dá)式后使用 REFERENCE 子句,如下所示:

      typedef unsigned char *my_raw;

EXEC SQL TYPE my_raw IS VARRAW(4000) REFERENCE;

my_raw buffer;

/* ... */

buffer = malloc(4004);
    

這里,我們分配了比源類型長(4000)更多的內(nèi)存,這是因?yàn)轭A(yù)編譯器要返回長度,而且可能需要填充適當(dāng)?shù)拈L度以滿足系統(tǒng)的對(duì)齊要求。


動(dòng)態(tài)SQL

嵌入SQL能夠滿足一個(gè)固定的應(yīng)用,但有時(shí)動(dòng)態(tài)產(chǎn)生完整的SQL語句也是很重要的。對(duì)于動(dòng)態(tài)SQL,語句存儲(chǔ)在字符串變量中, PREPARE 把字符串轉(zhuǎn)換為SQL語句,然后用 EXECUTE 執(zhí)行這個(gè)語句。考慮下面的例子:

      char *s = "INSERT INTO emp VALUES(1234, 'jon', 3)";

EXEC SQL PREPARE q FROM :s;

EXEC SQL EXECUTE q;
    

PREPARE EXECUTE 可放到一個(gè)語句中,像這樣:

      char *s = "INSERT INTO emp VALUES(1234, 'jon', 3)";

EXEC SQL EXECUTE IMMEDIATE :s;
    


事務(wù)

Oracle Pro*C支持標(biāo)準(zhǔn)SQL定義的事務(wù)。一個(gè)事務(wù)是一組SQL語句集合,Oracle把它當(dāng)作單獨(dú)的單元運(yùn)行。一個(gè)事務(wù)從第一個(gè)SQL語句開始,遇到" EXEC SQL COMMIT "(執(zhí)行當(dāng)前事務(wù)對(duì)數(shù)據(jù)庫的永久修改)或" EXEC SQL ROLLBACK "(取消從事務(wù)開始到當(dāng)前位置對(duì)數(shù)據(jù)庫的任何修改)時(shí)結(jié)束事務(wù)。當(dāng)前事務(wù)由 COMMIT ROLLBACK 語句結(jié)束后,下一條可執(zhí)行SQL語句將自動(dòng)開始一個(gè)新事務(wù)。

如果程序結(jié)束時(shí)沒有執(zhí)行 EXEC SQL COMMIT ,則對(duì)數(shù)據(jù)庫的所作的修改都將被忽略。


錯(cuò)誤處理

在每個(gè)可執(zhí)行的SQL表達(dá)式之后,可以在程序中檢查 SQLCA 顯式地或用 WHENEVER 語句隱式地得到執(zhí)行狀態(tài)信息。下面將詳細(xì)地介紹這兩種方法。


SQLCA

SQLCA(SQL Communications Area,SQL通訊區(qū))用于在程序中檢查錯(cuò)誤和狀態(tài)變化。每個(gè)可執(zhí)行SQL語句執(zhí)行后,Oracle 運(yùn)行時(shí)會(huì)在這個(gè)結(jié)構(gòu)中填入信息。

如果要使用SQLCA,你要用 #include 包含進(jìn) sqlca.h 頭文件。如果在很多地方包含了頭文件,你要使用 #undef SQLCA 來取消 SQLCA 的宏定義。 sqlca.h 中的相關(guān)程序塊如下:

      #ifndef SQLCA

#define SQLCA 1



struct sqlca {

    /* ub1 */ char sqlcaid[8];

    /* b4 */ long sqlabc;

    /* b4 */ long sqlcode;

    struct {

        /* ub2 */ unsigned short sqlerrml;

        /* ub1 */ char sqlerrmc[70];

    } sqlerrm;

    /* ub1 */ char sqlerrp[8];

    /* b4 */ long sqlerrd[6];

    /* ub1 */ char sqlwarn[8];

    /* ub1 */ char sqlext[8];

};

/* ... */
    

sqlca域有下列的意義:

sqlcaid 該字符串域初始化為"SQLCA",以指明這是個(gè)SQL通訊區(qū)。
sqlcabc 該整數(shù)域用byte標(biāo)識(shí)SQLCA結(jié)構(gòu)的長度。
sqlcode 這個(gè)整數(shù)域標(biāo)識(shí)最近執(zhí)行的SQL語句的狀態(tài)碼:
?
0 沒有錯(cuò)誤。
>0 語句執(zhí)行但捕獲異常。當(dāng)Oracle根據(jù) WHERE 條件查找不到任何記錄,或 SELECT INTO FETCH 影響記錄數(shù)為0時(shí)會(huì)發(fā)生這種情況。
<0 由于一個(gè)錯(cuò)誤Oracle不能執(zhí)行SQL語句。當(dāng)這個(gè)錯(cuò)誤發(fā)生時(shí),多數(shù)情況下當(dāng)前的事務(wù)應(yīng)該回滾(rollback)。
?
sqlerrm 這個(gè)內(nèi)嵌結(jié)構(gòu)包含兩個(gè)域:?
  • sqlerrml - 在 sqlerrmc 中保存的信息文本的長。
  • sqlerrmc - 最大到70個(gè)字符(character)的信息文本,與sqlcode中存儲(chǔ)的錯(cuò)誤碼相似。
    ?
sqlerrp 保留
sqlerrd 這個(gè)二進(jìn)制整形數(shù)組包含6個(gè)元素:?
  • sqlerrd[0] - 保留
  • sqlerrd[1] - 保留
  • sqlerrd[2] - 最近被執(zhí)行的SQL語句影響的記錄行數(shù)。
  • sqlerrd[3] - 保留
  • sqlerrd[4] - 分析最近執(zhí)行語句出現(xiàn)錯(cuò)誤,錯(cuò)誤的開始字符的偏移。
  • sqlerrd[5] - 保留
    ?
sqlwarn 這個(gè)單字符數(shù)組包含8個(gè)元素,用于警告標(biāo)志。Oracle使用字符' W '設(shè)置一個(gè)標(biāo)記。?
?
sqlwarn[0] 當(dāng)其它標(biāo)記被設(shè)置時(shí)設(shè)置。
sqlwarn[1] 當(dāng)輸出宿主變量中保存的是被截?cái)嗟淖侄沃禃r(shí)設(shè)置。
sqlwarn[2] 當(dāng)計(jì)算SQL統(tǒng)計(jì)如AVG或SUM時(shí),如果一個(gè) NULL 字段不能被使用時(shí)被設(shè)置。
sqlwarn[3] 當(dāng) SELECT 的字段數(shù)與 INTO 句中指定的宿主變量數(shù)不等時(shí)設(shè)置。
sqlwarn[4] 當(dāng)沒有使用 WHERE 子句的 UPDATE DELETE 語句處理了數(shù)據(jù)表中的每一行時(shí)設(shè)置。
sqlwarn[5] 當(dāng)由于PL/SQL編譯錯(cuò)誤而導(dǎo)致procedure/function/package/package body創(chuàng)建命令失敗時(shí)設(shè)置。
sqlwarn[6] 不再使用
sqlwarn[7] 不再使用
?
sqlext 保留

SQLCA只能在 sqlerrm 域中存儲(chǔ)最大70字符長的錯(cuò)誤信息。要得到更長的(或嵌套的)全部錯(cuò)誤信息字符,可以使用 sqlglm() 函數(shù):

      void sqlglm(char *msg_buf, size_t *buf_size, size_t *msg_length);
    

msg_buf 是Oracle存儲(chǔ)錯(cuò)誤信息的字符緩沖; buf_size 指定 msg_buf 的長(byte); Oracle在 *msg_length 中存放實(shí)際的錯(cuò)誤信息長。Oracle錯(cuò)誤信息的最大長度是512字節(jié)(byte)。


WHENEVER語句

這個(gè)表達(dá)式進(jìn)行自動(dòng)錯(cuò)誤檢查和處理。語法是:

      EXEC SQL WHENEVER <condition> <action>;
    

Oracle自動(dòng)檢查 <condition> 的SQLCA,當(dāng)條件被檢測(cè)到時(shí),程序會(huì)自動(dòng)執(zhí)行 <action>

<condition> 可以是下列各項(xiàng):

  • SQLWARNING - 由于Oracle返回一個(gè)警告而設(shè)置 sqlwarn[0]
  • SQLERROR - 由于Oracle返回一個(gè)錯(cuò)誤, sqlcode 的值為負(fù)
  • NOT FOUND - 由于Oracle按 WHERE 的條件沒有找到任何一條記錄,或 SELECT INTO FETCH 返回 0 條記錄,而使 sqlcode 為正

<action> 可以為下列各項(xiàng):

  • CONTINUE - 只要可能,程序會(huì)嘗試?yán)^續(xù)運(yùn)行之后的語句
  • DO - 程序?qū)⒖刂茩?quán)交給一個(gè)錯(cuò)誤處理模塊
  • GOTO <label> - 程序跳轉(zhuǎn)到被標(biāo)示的語句
  • STOP - 調(diào)用 exit() 結(jié)束程序,回滾未提交的操作

下面是 WHENEVER 語句的例子:

      EXEC SQL WHENEVER SQLWARNING DO print_warning_msg();

EXEC SQL WHENEVER NOT FOUND GOTO handle_empty;
    

下面是一個(gè)更詳細(xì)的例子:

      /* code to find student name given id */

/* ... */

for (;;)

{

    printf("Give student id number : ");

    scanf("%d", &id);

    EXEC SQL WHENEVER NOT FOUND GOTO notfound;

    EXEC SQL SELECT studentname INTO :st_name

             FROM   student

             WHERE  studentid = :id;

    printf("Name of student is %s.\n", st_name);

    continue;

notfound:

    printf("No record exists for id %d!\n", id);

}

/* ... */
    

注意 WHENEVER 表達(dá)式不遵從標(biāo)準(zhǔn)C的作用域規(guī)則,整個(gè)程序都是它的作用域。舉例來說,如果下面的語句在你程序中的什么地方(如在一個(gè)循環(huán)之前):

      EXEC SQL WHENEVER NOT FOUND DO break; 
    

這個(gè)文件在這行之后出現(xiàn)的所有SQL語句都會(huì)受其影響。當(dāng)不再需要 WHENEVER 的來影響程序時(shí)(比如在你的循環(huán)之后),確保使用下面的語句取消它的使用。

      EXEC SQL WHENEVER NOT FOUND CONTINUE; 
    


Demo程序

注意: 例程會(huì)創(chuàng)建、使用四個(gè)表: DEPT EMP PAY1 PAY2 。注意你的數(shù)據(jù)庫中可能會(huì)存在相同名子的表!

在leland系統(tǒng)的 /afs/ir/class/cs145/code/proc 下有很多例程。它們被命名為 sample*.pc (C用戶)和 cppdemo*.pc (C++用戶)。 " .pc "是Pro*C代碼的擴(kuò)展名。由于有幾個(gè)固定的步驟復(fù)制這些文件,所以不要手工復(fù)制它們。下面介紹如何下載和設(shè)置例程:

  1. 確認(rèn)你已經(jīng)運(yùn)行了 source /afs/ir/class/cs145/all.env
  2. 在你的目錄下,運(yùn)行 load_samples <db_username> <db_passwd> <sample_dir> <sample_idr> 是你想放置例程的地方(例: load_samples sally etaoinshrdlu cs145_samples
  3. cd <sample_dir>
  4. 運(yùn)行 make samples (C++用戶運(yùn)行 make cppsamples )編譯所有的例程。

第2步將會(huì)建立樣品數(shù)據(jù)庫,創(chuàng)建在 <sample_dir> 指定的新目錄,然后把文件復(fù)制到目錄下。它會(huì)在例程中修改你的用戶名和密碼,所有你不必每次運(yùn)行例程時(shí)都要輸入用戶名和密碼。 sample1 cppdemo1 也為用戶提供了輸入用戶名和密碼的接口,當(dāng)你想要學(xué)習(xí)如何使用的時(shí)候。如果在第2步輸入用戶名和密碼時(shí)產(chǎn)生了任何錯(cuò)誤,只要在你的目錄下運(yùn)行 clean_sample <db_username> <db_passwd> & lt;sample_dir> ,然后重做第2步到第4步。

對(duì)于第4步,你可以單獨(dú)編譯每一個(gè)例程。比如單獨(dú)編譯 sample1.pc 。編譯過程實(shí)際上有兩句:

  1. proc iname=sample1.pc
    把內(nèi)嵌SQL代碼轉(zhuǎn)換為相應(yīng)的庫調(diào)用,輸出 sample1.c
  2. cc <a_number_of_flags_here> sample1.c
    主成可執(zhí)行的 sample1

編譯你自己的代碼,如 foo.pc ,只要修改 Makefile 的幾個(gè)變量:在 SAMPLES 變量中加入 foo 程序名,在 SAMPLE_SRC 變量中加入 foo.pc 源文件名。然后,寫好 foo.pc make foo foo.pc 被預(yù)編譯為 foo.c ,再編譯為可執(zhí)行的 foo 。C++用戶要把程序名和源文件名加入到 CPPSAMPLE CPPSAMPLE_SRC 而不是 SAMPLES SAMPLE_SRC

例程運(yùn)行于下面的數(shù)據(jù)庫表上:

      CREATE TABLE DEPT

    (DEPTNO    NUMBER(2) NOT NULL,

     DNAME     VARCHAR2(14),

     LOC       VARCHAR2(13));



CREATE TABLE EMP

    (EMPNO     NUMBER(4) NOT NULL,

     ENAME     VARCHAR2(10),

     JOB       VARCHAR2(9),

     MGR       NUMBER(4),

     HIREDATE  DATE,

     SAL       NUMBER(7, 2),

     COMM      NUMBER(7, 2),

     DEPTNO    NUMBER(2));



CREATE TABLE PAY1

    (ENAME     VARCHAR2(10),

     SAL       NUMBER(7, 2));



CREATE TABLE PAY2

    (ENAME     VARCHAR2(10),

     SAL       NUMBER(7, 2));
    

當(dāng)在第2步運(yùn)行 load_samples 的時(shí)候這些表就自動(dòng)創(chuàng)建好了。一些tuples(譯注:沒找到合適的詞,把原詞放這了)也插入了。你可以在程序運(yùn)行前查看這些表也可以任意操作這些表(如:插入、刪除或是更新tuples)。當(dāng)你運(yùn)行 clean_sample 時(shí),這些表自動(dòng)被刪除。注意: clean_sample 也會(huì)清理整個(gè) <sample_dir>;

確保在運(yùn)行這個(gè)命令之前將你自己的文件轉(zhuǎn)移到其它的地方!

你應(yīng)該在運(yùn)行它之前看一看源代碼,頭部的注釋描述了程序都做些什么。例如, sample1 從一個(gè)雇員的 EMPNO 得到他的名子和工資,從 EMP 表中得到的那個(gè)雇員的傭金。

通過學(xué)習(xí)源程序你應(yīng)該可以學(xué)到下面的東西:

  • 如何從主機(jī)連接到Oracle
  • 如何在C/C++中嵌入SQL
  • 如何使用游標(biāo)
  • 如何使用宿主變量與數(shù)據(jù)庫通訊
  • 如何使用 WHENEVER 進(jìn)行不同的錯(cuò)誤處理動(dòng)作
  • 如何使用指示器變量檢測(cè)輸出中的空值

現(xiàn)在,你可以使用這些技術(shù)編寫你自己的數(shù)據(jù)庫應(yīng)用程序了。And have fun!


C++用戶

要使用預(yù)編譯器生成合適的C++代碼,你需要注意下面的事項(xiàng):

  • 代碼被預(yù)編譯器展開。要得到C++代碼,你需要在執(zhí)行 proc 時(shí)設(shè)置 CODE=CPP 選項(xiàng)。
  • 解析能力。 proc PARSE 選項(xiàng)可以是下面的值:
    • PARSE=NONE . C預(yù)處理指令只能在聲明節(jié)中被解析,所以所有的宿主變量需要在聲明節(jié)中聲明。
    • PARSE=PARTIAL . C預(yù)處理指令能被解析;然而,所有的宿主變量需要在聲明節(jié)中聲明。
    • PARSE=FULL . C預(yù)處理指令能被解析,而且宿主變量可以聲明在任何地方。當(dāng) CODE 不為 CPP 時(shí),這是默認(rèn)設(shè)置;但當(dāng) CODE=CPP 時(shí),指定 PARSE=FULL 卻是個(gè)錯(cuò)誤。
    所以,C++用戶必須指定 PARSE=NONE PARSE=PARTIAL ,因此這也失去了在任意地方聲明宿主變量的自由。更有,宿主變量必須被包在一個(gè)聲明節(jié)中,如下:
            EXEC SQL BEGIN DECLARE SECTION;
    
        // declarations...
    
    EXEC SQL END DECLARE SECTION;
          
    你需要使用這種方法去聲明所有的宿主和指示器變量。
  • 文件擴(kuò)展名。你要指定設(shè)置 CPP_SUFFIX=cc CPP_SUFFIX=C
  • 頭文件定位。默認(rèn)情況下, proc 像標(biāo)準(zhǔn)定位 stdio.h 文件一樣查找頭文件。然而C++有自己的頭文件,如 iostream.h ,被放置在別處。所以,你需要使用 SYS_INCLUDE 選項(xiàng)指定 proc 查找頭文件的路徑。

Pro*C支持的嵌入SQL語句列表

聲明表達(dá)式
EXEC SQL ARRAYLEN 在PL/SQL中使用宿主變量
EXEC SQL BEGIN DECLARE SECTION
EXEC SQL END DECLARE SECTION
聲明宿主變量
EXEC SQL DECLARE 給Oracle對(duì)像命名
EXEC SQL INCLUDE 從文件中復(fù)制
EXEC SQL TYPE 同等化數(shù)據(jù)類型
EXEC SQL VAR 同等化變量
EXEC SQL WHENEVER 處理運(yùn)行時(shí)錯(cuò)誤
執(zhí)行表達(dá)式
EXEC SQL ALLOCATE 聲明、控制Oracle數(shù)據(jù)
EXEC SQL ALTER
EXEC SQL ANALYZE
EXEC SQL AUDIT
EXEC SQL COMMENT
EXEC SQL CONNECT
EXEC SQL CREATE
EXEC SQL DROP
EXEC SQL GRANT
EXEC SQL NOAUDIT
EXEC SQL RENAME
EXEC SQL REVOKE
EXEC SQL TRUNCATE
EXEC SQL CLOSE
EXEC SQL DELETE 排序、修改Oracle數(shù)據(jù)
EXEC SQL EXPLAIN PLAN
EXEC SQL FETCH
EXEC SQL INSERT
EXEC SQL LOCK TABLE
EXEC SQL OPEN
EXEC SQL SELECT
EXEC SQL UPDATE
EXEC SQL COMMIT 處理事務(wù)
EXEC SQL ROLLBACK
EXEC SQL SAVEPOINT
EXEC SQL SET TRANSACTION
EXEC SQL DESCRIBE 使用動(dòng)態(tài)SQL
EXEC SQL EXECUTE
EXEC SQL PREPARE
EXEC SQL ALTER SESSION 控制會(huì)話
EXEC SQL SET ROLE
EXEC SQL EXECUTE
END-EXEC
內(nèi)嵌PL/SQL塊


This document was written originally by Ankur Jain and Jeff Ullman for CS145, Autumn 1997; revised by Jun Yang for Prof. Jennifer Widom's CS145 class in Spring, 1998; further revisions by Roy Goldman for Prof. Jeff Ullman's CS145 class in Autumn, 1999; further revisions by Calvin Yang for Prof. Jennifer Widom's CS145 class in Spring, 2002.

Pro*C介紹-內(nèi)嵌SQL


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 成人淫片 | 99免费视频 | 国产一区二区三区久久精品 | 美女羞羞视频 | 国产午夜亚洲精品久久www | 一级免费a| 久久久国产这里有的是精品 | 久久这里一区二区精品 | 欧美日韩一区二区三区麻豆 | 中文字幕丝袜在线56页 | 高清国产性色视频在线 | 狠狠澡夜夜澡人人爽 | 天天操天天操天天 | 国产高清福利91成人 | 免费看黄色的视频 | 九九九热精品 | 国产精品免费久久久久影院小说 | 国产综合视频 | 天天摸天天干天天操 | 99在线观看视频免费精品9 | 国产一区二区三区成人久久片 | 另类久久| 亚洲综合日本 | 91在线观 | 亚洲一区二区三区在线播放 | 国产h片在线观看 | 精品一区亚洲 | 日韩黄色精品 | 97色伦影院 | 国产一区二区三区免费视频 | 亚洲综合久久久久久中文字幕 | 久久99国产精品二区不卡 | aa大片成人免费网站 | 97视频在线观看视频最新 | 欧美激情在线精品三区 | 无码免费一区二区三区免费播放 | 91成人午夜性a一级毛片 | 操操操干干 | 欧美理论大片清免费观看 | 久久久久精彩视频 | α毛片|