應用程式體
EXEC SQL BEGIN DECLARE SECTION
(SQL變數的定義)
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLLA;
EXEC SQL CONNECT:< 使用者名稱>
IDENTIFIED BY: < 口令 >
SQL 陳述式及遊標的使用
1. 應用程式首部
應用程式的首部就是Pro*C的開始部分。它包括以下三部分:
l C變數描述部分;
l SQL變數描述部分(DECLARE部分);
l SQL通訊區。
(1) .DECLARE部分(描述部分)
描述部分說明程式的SQL變數, 定義部分以EXEC SQL BEGIN DECLARE SECTION ;開始和以 EXEC SQL END DECLARE
SECTION ;結束的。它可以出現在程式的主部,也可出現在局部
l SQL變數的說明和使用
在說明段能為SQL變數指定的資料類型如表所示:
資料類型描述
CHAR
CHAR(n)
INT
SHORT
LONG
FLOAT
DOUBLE
VARCHAR單字元
n個字元數組
整數
短整數
單精確度浮點數
雙精確度浮點數
變長字串
這些資料類型實際上就是C語言的資料類型, 其中VARCHAR中視為C資料類型的擴充。這在以後會談到。
SQL變數的使用應注意以下幾點:
l 必須在描述部分明確定義
l 必須使用與其定義相同的大小寫格式
l 在SQL語句中使用時,必須在其之前加一個“:”(冒號),但在C語句中引用時不需加冒號。
l 不能是SQL命令中的保留字。
l 可以帶指示變數。
例如:EXEC SQL BEGIN DECLARE SECTIONS;
VARCHAR programe[30];
Int porgsal, pempno;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT ENAME , SAL
INTO: programe, : progsal
FROM EMP
WHERE EMPNO = : pempno;
(2). 指標變數的說明和引用
指示變數實際上也是一類SQL變數,它被用來管理與其相關聯的宿主變數(即在SQL語句中充
當輸入或輸出的變數)。每一個宿主變數都可定義一個指標變數,主要用於處理空值(NULL)
指標變數的說明基本同一般SQL變數一樣, 但必須定義成2位元組的整型,如SHORT、INT。在SQL語句中引用時,
其前也應加“:”(冒號),而且必須附在其相關聯的宿主變數之後,在C語句中,可獨立使用。當指標變數為-1時,表示空值。例如:
EXEC SQL BEGIN DECLARE SECTION ;
INT dept- number;
SHORT ind – num;
CHAR emp –name;
EXEC SQL END DECLARE SECTION ;
Scanf(“90d %s”, & dept- number , dept – name );
If (dept – number ==0)
Ind – num = -1;
Else
Ind – num = 0;
EXEC SQL INSERT INTO DEPT (DEPTNO, DNAME)
VALUES(:dept – number : ind- num , :dept – name);
其中ind – num是dept – number 的指標變數。當輸入的dept – number 值是0時, 則向DEPT 表的DEPTNO列插入空值。
(3).指標SQL變數的說明和使用
指標SQL變數在引用前也必須在DECLARE
部分先說明。其說明格式同C語言。在SQL語句中引用時,指標名字前要加首碼“:”(冒號)而不加“*”(星號)。在C語句中用法如同C語言的指標變數。
(4).數組SQL變更的說明和引用
在SQL語句中引用數組時,只需寫數組名(名字前加冒號), 不需寫下標,在C語句中用法如同C語言的陣列變數。
使用數組可大大降低網路傳輸開銷。如要向一表插入100行資料,如果沒有數組,就要重複100次, 而引用後,只須執行一次insert語句、便可一次性插入。例如:
EXEC SQL BEGIN DECLARE SECTION;
Int emp_number[100];
Char emp_name[100][15];
Float salary[100],commission[100];
Int dept_number;
EXEC SQL END DECLARE SECTION;
….
EXEC SQL SELECT EMPNO,ENAME,SAL,COMM
INTO :emp_number,:emp_name,:salary,:commission
FROM EMP
WHERE DEPTNO=:dept_number;
在使用數組時,應注意以下幾點;
l 不支援指標數組
l 只支援一維數組, 而 emp-name [100][15]視為一維字串
l 數組最大維數為32767
l 在一條SQL語句中引用多個數組時,這些數組維數應相同
l 在VALUES , SET, INTO 或WHERE子名中, 不允許把簡單SQL變數與數組SQL變數混用
l 不能在DELARE部分初始化數組
例如:下面的引用是非法的
EXEC SQL BEGIN DECLARE SECTION;
Int dept – num [3] = {10,20,30};
EXEC SQL END DECLARE SECTION ;
EXEC SQL SELECT EMPNO, ENAME , SAL
INTO : emp – num [ i ], : emp – name [ i ], : salarg [ i ]
FROM EMP
(5) 偽類型VARCHAR的說明和引用
VARCHAR變數在引用之前也必須在說明段說明, 說明時必須指出串的最大
長度,如:
EXEC SQL BEGIN DECLARE SECTION;
Int book – number;
VARCHAR book – name [ 50 ];
EXEC SQL END DECLARE SECTION ;
在預編繹時, book – name 被翻譯成C語言中的一個結構變數;
Struct { unsigned short len ;
Unsigned chart arr [ 20 ] ;
} boo – name
由此看出, VARCHAR變數實際上是含長度成員和數群組成員的結構變數。在SQL語句中引用時,應引用以冒號為首碼的結構名, 而不加下標,在C語句 中引用結構成員。
VARCHAR變數在作輸出變數時,由ORACLE自動化佈建, 在作為輸入變數時,程式應先把字串存入數群組成員中,
其長度存入長度成員中,然後再在SQL語句中引用。例如:
Main( )
{ .......
scanf(“90s, 90d’, book – name .arr, & book – number );
book – name .len = strlen (book – name .arr);
EXEC SQL UPDATE BOOK
SET BNAME = : book – name ;
BDESC = : book – number ;
}
(6) SQL通訊區
SQL 通訊區是用下列語句描述的:
EXEC SQL INCLUDE SQLCA;
此部分提供了使用者運行程式的成敗記錄和錯誤處理。
A. 定義遊標
一個遊標必須首先定義, 才能使用它。文法為:
EXEC SQL DECLARE 〈遊標名〉CORSOR FOR
SELECT 〈列〉
FROM 〈表〉
例如:
EXEC SQL DECLARE CSOR, CURSOR FOR
SELECT ENAME , JOB, SAL
FROM EMP
WHERE DEPTNO=:DEPTNO;
當賦給一個與查詢相關聯的遊標CURSOR之後, 當SELECT查詢EMP時可從資料庫中返回多行,這些行就是CURSOR的一個即時區域。
注意:
1) 定義遊標必須在對遊標操作之前完成;
2) PRO*C不能引用沒有定義的遊標;
3) 遊標定義後,其作用範圍是整個程式。所以對一個程式來講, 同時定義兩個相同的遊標是錯誤的。
B. 開啟遊標
開啟遊標的OPEN語句主要用來輸入主變數的內容,這些主要是WHERE中使用的主變數。開啟遊標的語句是:EXEC SQL OPEN 〈遊標名〉
當開啟遊標後,可以從相關的查詢中取出多於一行的結果。所有滿足查詢標準的行組成一集合,叫做“遊標活動集”。通過取操作,活動集中的每一行或每一組是一個一個返回的,查詢完成後,
遊標就可關閉了。如圖所示:
定義遊標:DECLARE
開始查詢:SELECT
開啟遊標:OPEN
從活動集取資料:FETCH
查詢完成
關閉遊標:CLOSE
注意:1)遊標處於活動集的第一行前面;
2)若改變了輸入主變數就必須重新開啟遊標。
C. 取資料
從活動集中取出一行或一組把結果送到輸出主變數中的過程叫取資料。輸出主變數的定義在取資料語句中。取資料的語句如下:
EXEC SQL FETCH〈遊標名〉INTO:主變數1,主變數2,……
FETCH的工作過程如圖所示:
查詢結果
遊標
FETCH
查詢結果
在遊標開啟後
輸出至當前
……
如圖所示的查詢結果指滿足查詢條件的查詢結果。使用FETCH應注意以下幾點:
l 遊標必須先定義再開啟。
l 只有在遊標開啟之後才能取資料,即執行FETCH語句。
l
FETCH語句每執行一次,從當前行或當前組取資料一次,下一行或下一組向上移一次。遊標每次所指的行或組都為當前行或當前組,而FETCH每次都是取遊標所指定的行或組的資料。
l 當遊標活動集空之後,ORCLE返回一個SQLCA。SQLCA(=1403)。
l 若希望此遊標再操作, 必須先關閉再開啟它。
l 在C程式中可以開闢一個記憶體空間,來存放操作結果,這樣就能利用開闢的空間來靈活操縱查詢的結果。
D.關閉遊標
取完活動集中所有行後,必須關閉遊標,以釋放與該遊標有關的資源。
關閉遊標的格式為:
EXEC SQL CLOSE 遊標名;
例如:
EXEC SQL CLOSE C1;
ORACLE V5.0版支援SQL格式“CURRENT OF CURSOR”。這條語句將指向一個遊標中最新取出的行,
以用於修改和刪除操作。該語句必須有取操作之後使用,它等同儲存一個ROWID,並使用它。
(4).舉例
EXEC SQL DECLARE SALESPEOPLE CURSOR FOR
SELECT SSNO, NAME, SALARY
FROM EMPLOYEE
WHERE DNAME=‘Sales’;
EXEC SQL OPEN SALESPEOPLE;
EXEC SQL FETCH SALESPEOPLE
INTO :SS,:NAME,:SAL;
EXEC SQL CLOSE SALESPEOPLE;
(5)SQL嵌套的方法及應用
嵌入SQL與互動式SQL在形式上有如下差別:
1) 在SQL語句前增加首碼“EXEC SQL”, 這一小小的差別其目的是在於先行編譯時容易識別出來,
以便把每一條SQL作為一條進階語言來處理。
2) 每一SQL語句分為說明性語句和可執行語句兩大類。可執行語句又分為資料定義、資料控制、資料操縱、資料檢索四大類。
可執行性SQL語句寫在進階語言的可執行處;說明性SQL語句寫在進階語言的說明性的地方。
例如:在PRO*C程式中建立一個名為BOOK的表結構,過程如下:
#include〈stdio.h〉
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR uid[20], pwd[20];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;
Main()
{
/*login database*/
strcpy(uid.arr,’wu’);
uid.len=strlen(uid,arr);
strcpy(pwd.arr,’wu’);
pwd.len=strlen(pwd.arr);
EXEC SQL CONNECT:uid IDENTIFEED BY:pwd;
EXEC SQL CREATE TABLE book
( acqnum number, copies number , price number);
EXEC SQL COMMIT WORK RELEASE;
EXIT;
PRO*C可非常簡便靈活地訪問ORCLE資料庫中的資料,同時又具有C語言高速的特點,因而可完成一些ORACLE產品不能完成的任務,例如以下一個固定的特殊格式輸出結果。
SQL嵌套來源程式樣本
#unclude
typedef char asciz[20];
EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL TYPE asciz IS STRING (20) REFERENCE;
asciz username;
asciz password;
asciz emp_name(5);
int emp_number(5a);
float salary[5];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE sqlca;
Void print_rows();
Void sqlerror();
Main()
{
int num_ret;
strcpy(username,”SCOTT’);
strcpy(password, “TYGER”);
EXEC SQL WHENEVER SQLERROR DO sqlerror();
EXEC SQL CONNECT:username IDENTIFIED BY:password;
Print (“\nConnected to ORACLE as user:%s\n”, username);
EXEC SQL DECLARE c1 CURSOR FOR
SELECT EMPNO , ENAME , SAL FROM EMP;
EXEC SQL OPEN c1;
Num_ret = 0;
For(;;)
{
EXEC SQL WHENEVER NOT FOUND DO break;
EXEC SQL FETCH c1 INTO : emp_number , :emp_name , :salary;
Print_rows (sqlca.sqlerrd[2] – num_ret);
Num_ret=sqlca.sqlerrd[2];
}
if ((sqlca.sqlerrd[2] – num_ret)>0);
print _rows(sqlca.sqlerrd[2] –num_ret);
EXEC SQL CLOSE c1;
Printf(“\Have a good day.\n”);
EXEC SQL COMMIT WORK RELEASE;
}
void print_rows(n);
int n;
{
int i;
printf(“\nNumber Employee Salary\n”);
printf(“------------------------------\n”);
for (i=0;i printf(“% - 9d%- 8s%9.2f\n”,emp-number[i], emp---name[i],salary[i];
}
void sqlerror()
{
EXEC SQL WHENEVER SQLERROR CONTINUE;
Printf(“\noracle error detected:\n”);
Printf(‘\n%.70s\n”, sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK WORK RELEASE;
Exit(1);
}
2 指標變數
指標變數有時也稱指示變數.指示變數與一個主變數相關聯,指出主變數的返回情況.
=0:傳回值不為空白, 未被截斷,值放在主變數中;
傳回值= >0:傳回值為空白, 忽略主變數的值;
<0:主變數長度不夠就被截斷。
使用指示變數要注意:
l 在WHERE子句中不能用指示變數。用NULL屬性來測試空值。
例如下列子句:
SELECT…
FROM…
WHERE ENAME IS NULL;
是正確的,而
WHERE ENAME=:PEME:PEME1
是錯誤的。
l 指示變數在插入空值之前為—1
l 可輸出空值。
(7) 動態定義語句
SQL語句分動態定義語句和靜態定義語句兩種:
(1) 靜態定義語句:SQL語句事先編入PRO*C中,在經過先行編譯器編譯之後形成目標程式*。BOJ,然後執行目標程式預即可。
(2) 動態定義語句:有些語句不能事先嵌入到PRO*C程式中,要根據程式運行情況,使用者自己從輸入裝置上(如終端上)即時輸入即將執行的SQL語句。
動態定義語句有:
l EXECUTE IMMEDIATE;
l PREPARE 與EXECUTE;
l PREPARE與FETCH 和 OPEN ;
l BIND與DEFINE DESCRIPTOR。