廈門大學的一個課件 備查
http://www.cs.xmu.edu.cn/education/fine_courses/database/%BE%AB%C6%B7%BF%CE%B3%CC%BD%A8%C9%E8%C4%DA%C8%DD/3_%CD%F8%C2%E7%B0%E6cai/content/index.htm
3. 不用游標的嵌入式SQL語句應用技術
所謂不用游標的SQL語句,是指一般不需要返回結果數據,也不需要使用主變量的語句。它們是嵌入式SQL中最簡單的一類語句。有以下幾種:
· 說明性語句
· 數據定義語句
· 數據控制語句
· 查詢結果為單記錄的SELECT語句
· 非CURRENT形式的UPDATE語句
· 非CURRENT形式的DELETE語句
· INSERT語句
其中:
*) 所有的說明性語句、數據定義與控制語句都不需要使用游標,在主語言中嵌入說明性語句、數據定義與控制語句,只要給語句加上前綴EXEC SQL和語句結束符即可。
*) INSERT語句也不需要使用游標,但通常需要使用主變量。
*) SELECT語句、UPDATE語句、DELETE語句則更復雜些。
以下分別討論常見的幾種使用方法:
一、說明性語句
交互式SQL中沒有說明性語句,這里的說明性語句是專為在嵌入式SQL中說明主變量等而設置的,一對由兩條語句組成:
EXEC SQL BEGIN DECLARE SECTION;
<變量定義語句>
EXEC SQL END DECLARE SECTION;
兩條語句必須配對出現,相當于一個括號,兩條語句中間是主變量、指示變量的說明。
二、數據定義語句
例1 建立一個“學生”表Student
EXEC SQL CREATE TABLE Student
(Sno CHAR(5) NOT NULL UNIQUE,
Sname CHAR(20),
Ssex CHAR(1),
Sage INT,
Sdept CHAR(15));
數據定義語句中不允許使用主變量。例如下列語句是錯誤的:
EXEC SQL DROP TABLE :table_name;
三、數據控制語句
例2 把查詢Student表權限授給用戶U1
EXEC SQL GRANT SELECT ON TABLE Student TO U1;
四、查詢結果為單記錄的SELECT語句
在嵌入式SQL中,查詢結果為單記錄的SELECT語句需要用INTO子句指定查詢結果的存放地點。該語句的一般格式為:
EXEC SQL SELECT [ALL|DISTINCT] <目標列表達式>[,<目標列表達式>]...
INTO <主變量>[<指示變量>][,<主變量>[<指示變量>]]...
FROM <表名或視圖名>[,<表名或視圖名>] ...
[WHERE <條件表達式>]
[GROUP BY <列名1> [HAVING <條件表達式>]]
[ORDER BY <列名2> [ASC|DESC]];
說明:
該語句對交互式SELECT語句的擴充就是多了一個INTO子句,把從數據庫中找到的符合條件的記錄,放到INTO子句指出的主變量中去。其他子句的含義不變。使用該語句需要注意以下幾點:
*) INTO子句、WHERE子句的條件表達式、HAVING短語的的條件表達式中均可以使用主變量,但這些主變量必須事先加以說明,并且引用時前面要加上冒號。
*) 查詢返回的記錄中,可能某些列值為空值NULL,則如下處理:如果INTO子句中主變量后面跟有指示變量,則當查詢得出的某個數據項為空值時,系統會自動將相應主變量后面的指示變量置為負值,但不向該主變量執行賦值操作,即主變量值仍保持執行SQL語句之前的值。所以當發現指示變量值為負值時,不管主變量為何值,均應認為主變量值為NULL。指示變量只能用于INTO子句中,并且也必須事先加以說明,引用時前面要加上冒號。
*) 如果數據庫中沒有滿足條件的記錄,即查詢結果為空,則DBMS將SQLCODE的值置為100。
*) 如果查詢結果實際上并不是單條記錄,而是多條記錄,則程序出錯,DBMS會在SQLCA中返回錯誤信息。
例3 根據學生號碼查詢學生信息。假設已將要查詢的學生的學號賦給了主變量givensno
EXEC SQL SELECT Sno, Sname, Ssex, Sage, Sdept
INTO :Hsno, :Hname, :Hsex, :Hage, :Hdept
FROM Student
WHERE Sno=:givensno;
上面的SELECT語句中Hsno, Hname, Hsex, Hage, Hdept和givensno均是主變量,并均已在前面的程序中說明過了。
例4 查詢某個學生選修某門課程的成績。假設已將要查詢的學生的學號賦給了主變量givensno,將課程號賦給了主變量givencno
EXEC SQL SELECT Sno, Cno, Grade
INTO :Hsno, :Hcno, :Hgrade:Gradeid
FROM SC
WHERE Sno=:givensno AND Cno=:givencno;
由于學生選修一門課后有可能沒有參加考試,也就是說其成績為空值,所以我們在該例INTO子句中加了指示變量Gradeid,用于指示主變量Hgrade是否為空值。指示變量也需要和所有主變量一起在前面程序中事先說明。執行此語句后,如果Gradeid小于0,則不論Hgrade為何值,均認為該學生成績為空值。
雖然對于僅返回一行結果數據的SELECT語句可以不使用游標,但從應用程序獨立性角度考慮,最好還是使用游標。因為如果以后數據庫改變了,該SELECT語句可能會返回多行數據,這時不使用游標就會出錯。
五、非CURRENT形式的UPDATE語句
非CURRENT形式是指特殊情況下的應用。在這種情況下的嵌入式UPDATE語句中,SET子句和WHERE子句都可以使用主變量,其中SET子句中還可以使用指示變量。以下分別用幾個例子說明它們的應用技術:
例5 將全體學生1號課程的考試成績增加若干分。假設增加的分數已賦給主變量Raise
EXEC SQL UPDATE SC
SET Grade=Grade+:Raise
WHERE Cno='1';
該操作實際上是一個集合操作,DBMS會修改所有學生的1號課程的Grade屬性列。
例6 修改某個學生1號課程的成績。假設該學生的學號已賦給主變量givensno,修改后的成績已賦給主變量newgrade
EXEC SQL UPDATE SC
SET Grade=:newgrade
WHERE Sno=:givensno;
例7 將計算機系全體學生年齡置NULL值
Sageid=-1;
EXEC SQL UPDATE Student
SET Sage=:Raise:Sageid
WHERE Sdept='CS';
將指示變量Sageid賦一個負值后,無論主變量Raise為何值,DBMS都會將CS系所有記錄的年齡屬性置空值。它等價于:
EXEC SQL UPDATE Student
SET Sage=NULL
WHERE Sdept='CS';
六、非CURRENT形式的DELETE語句
與上同理,DELETE語句的WHERE子句中可以使用主變量指定刪除條件。
例8 某個學生退學了,現要將有關他的所有選課記錄刪除掉。假設該學生的姓名已賦給主變量stdname
EXEC SQL DELETE
FROM SC
WHERE Sno=
(SELECT Sno
FROM Student
WHERE Sname=:stdname);
另一種等價實現方法為:
EXEC SQL DELETE
FROM SC
WHERE :stdname=
(SELECT Sname
FROM Student
WHERE Studnet.Sno=SC.sno);
顯然第一種方法更直接,從而也更高效些。
如果該學生選修了多門課程,執行上面的語句時,DBMS會自動執行集合操作,即把他選修的所有課程都刪除掉。
七、INSERT語句
INSERT語句的VALUES子句中可以使用主變量和指示變量。
例9 某個學生新選修了某門課程,將有關記錄插入SC表中。假設學生的學號已賦給主變量stdno,課程號已賦給主變量couno。
gradeid=-1;
EXEC SQL INSERT
INTO SC(Sno, Cno, Grade)
VALUES(:stdno, :couno, :gr:gradeid);
由于該學生剛選修課程,尚未考試,因此成績列為空。所以本例中用指示變量指示相應的主變量為空值。
廈門大學計算機科學系 薛永生