夏毅 一、ASP動態網站開發技術
隨著人們對因特網認識的加深和IT技術的發展,一成不變的靜態網頁已經越來越滿足不了信息交互和電子商務的需求,因此以數據庫為核心開發能夠實現信息交互和個性化服務的網頁已經成為一種潮流。為了迎合動態交互式網頁的開發趨勢,出現了可以與后臺數據庫進行互動的Web開發技術,目前比較流行的一類是建立在微軟Windows平臺IIS基礎上的ASP(Active Server Pages)技術。它是將VBscript、JavaScript等特定的腳本語言利用特殊的標記嵌入到HTML中,當Browser端提出請求時,Web服務器會使用相應的腳本解釋引擎對腳本解釋執行,完成數據庫的查詢、修改等任務,并把結果動態格式化成HTML形式送回到Browser請求端。
Oracle數據庫是目前國內外最常使用的數據庫,隨著Oracle 8i的發布,它又增添了對Java和對象的支持,大大方便了網絡軟件的開發。因此目前ASP應用程序的開發在很多場合需要與后臺Oracle數據庫打交道。下面,我們將以多個專題討論組的應用為例,著重介紹ASP腳本是如何利用ADO組件的Command對象訪問數據庫的存儲過程的。
多專題討論組用戶提交的信息都統一存儲在以下結構的數據庫表中:
CREATE TABLE messages(
m_id NUMBER,
m_forumName varchar2(30) NOT NULL,
m_subject varchar2(30) NOT NULL,
m_username varchar2(30) NOT NULL,
m_email varchar2(70) NOT NULL,
m_entrydate date default sysdate,
m_message varchar2(200),
m_ordernum number,
m_reply number);
其中各字段的含義如下:
m_id:每條消息唯一識別的標識號;
m_forumname:討論專題名稱;
m_subject:消息主題;
m_username:用戶名;
m_email:E-mail地址;
m_entrydate:提交時間;
m_message:消息內容;
m_ordernum:順序號;
m_reply:是否為回答消息。
二、ASP腳本調用Oracle數據庫包中的存儲過程
1.建立數據庫包
假設現在數據庫表中已經存有多個專題討論的消息,如果想要在網頁上分別顯示各專題的名稱及各專題的消息數目,首先在Oracle數據庫中定義一個名為getForum的存儲過程,放在名為forum_retrieve的包中。
如果存儲過程返回的結果是多行數據集,此過程必須放在一個包中。包是Oracle數據庫的一種對象,它可以將數據類型、存儲過程、函數、變量和常量封裝在一起,類似于VB中的標準代碼模塊。包在結構上又分為包頭和包體兩部分分別存儲的,因此這兩部分也要分別建立,包頭用來定義可被外部引用的元素;包體定義實際代碼,即邏輯執行部分。
此例的包頭與包體分別定義如下:
CREATE OR REPLACE PACKAGE forum_retrieve
AS
TYPE tforumname IS TABLE of messages.m_forumname %TYPE INDEX BY BINARY_INTEGER;
TYPE tcount IS TABLE of NUMBER INDEX BY BINARY_INTEGER;
PROCEDURE getForums
(
forumname OUT tforumname,
theCount OUT tcount
);
以上是包頭的定義,首先對tforumname和tcount這兩個PL/SQL表類型進行聲明,然后對外部調用到的存儲過程進行聲明。
CREATE OR REPLACE PACKAGE BODY forum_retrieve
AS
PROCEDURE getForums
(
forumname OUT tforumname,
theCount OUT tcount
)
AS
CURSOR c1 IS
SELECT m_forumname
FROM messages
GROUP by m_forumname
ORDER by m_forumname;
counter NUMBER DEFAULT 1;
BEGIN
FOR c IN c1 LOOP
forumname(counter):=c.m_forumname;
SELECT COUNT(*)
into thecount(counter)
FROM messages
WHERE m_forumname=forumname(counter);
counter :=counter+1;
END LOOP;
END;
以上是對包體的定義,它只包含了一個名為getforums的存儲過程。
由于Oracle與SQL Server等其他數據庫不同,不能在存儲過程中將查詢的多行結果直接返回到調用端,每次只能直接返回一行結果,但在這里我們查詢的討論組名稱和數目返回的是多行數據,因此我們使用了PL/SQL的光標c1,它首先查詢到不同專題名稱的結果集,然后建立游標循環分別對每一個討論組專題統計出各自的消息數目,將專題名稱和消息數目分別存到名為forumname和thecount的PL/SQL表變量中,并作為輸出變量返回到調用端。tforumname和tcount是PL/SQL的兩個表類型,這種類型類似于其他編程語言的數組,它們的定義在存儲過程中是無法進行的,因此這也是必須將getforums存儲過程放在一個包中的原因。
如果以上forum_retrieve包在創建過程沒有出現錯誤,那么它就已經被編譯后存儲在Oracle的數據字典中了,在SQL*plus下鍵入以下命令:
SELECT * FROM user_objects WHERE object_name='forum_retrieve';
會看到名為forum_retrieve的包頭和包體的狀態,正常應是VALID狀態。
2.在ASP文件中調用存儲過程
下一步我們就可以在客戶端的ASP文件中使用ADO Command對象來調用這個存儲過程了。首先在IIS所在主機上要建立好對Oracle數據庫ODBC的DSN連接,或直接在ASP文件中建立DSN-Less連接,這完全可以根據個人喜好和具體情況來選擇,代碼如下:
在以上例子中存儲過程只有輸出變量。如果被調用的存儲過程還包含輸入變量,SQL連接字符串應修改如下:
SQLstr={call package.procedure(?,..,{resultset 100,output1,output2,...})}
其中?是每個輸入變量的占位符,與輸入變量的個數一一對應。另外,還要分別對每個輸入變量賦值,格式如下:
CMD.Parameters.Append CMD.CreateParameter("輸入變量名",adVarChar,adParamInput,30,賦值變量)
其中adVarChar指定變量類型是字符串;adParamInput指定變量為輸入變量;30是指定字符串的最大長度,如果輸入變量是整型或其他類型,則無須設置此項。所有這些常量的定義都包含在ADOVBS.INC文件中,對于不同的參數類型可查看此文件進行設置。
三、ASP腳本調用Oracle數據庫中獨立的存儲過程
所謂獨立的存儲過程是指沒有放在包中,而是作為單獨的對象存儲在Oracle數據字典中的過程,ASP腳本對這種存儲過程的調用與上述方法略有不同,以下舉例說明。例如,要在ASP腳本中調用獨立的名為getmessages的存儲過程,代碼如下:
CREATE OR REPLACE PROCEDURE getmessages
(
forumname IN messages.m_forumname%TYPE,
lastmessage OUT messages.m_id%TYPE
)
AS
BEGIN
......‘內容省略
ENDgetmessages;
在ASP文件中也是使用ADO Command對象對此過程進行調用,代碼如下:
四、為什么要使用存儲過程
1.存儲過程可以將多條SQL語句包含在一起執行,ASP和數據庫的交互只是輸入、輸出參數的一次來回傳遞,傳遞信息少,因此提高了執行效率。
2.存儲過程在數據庫中是經過編譯后存儲的,因此其執行效率比起執行同樣功能的SQL語句要高很多。
3.在開發大型應用程序過程中可以將一些標準功能邏輯模塊作為存儲過程放在數據庫中,使得模塊化程序開發的結構更加清晰,而且易于維護。
|