Sybase學習筆記

Sybase學習筆記

    前段時間從Sybase網站上當的Sybase ASE 15 Windows版(以下簡稱Sybase),這幾天沒事,便簡單瞭解了一下。
一、安裝
    將 下載的ase1500_de_win.zip文件解壓縮,雙擊setup.exe。由於整個安裝過程都有提示,因此不需要做太多說明,唯一要注意的是在選 擇安裝類型時,如果想使用ODBC、OleDb或者ADO.net進行開發,一定要選擇自定義安裝,因爲在默認情況下被安裝的只有JDBC驅動,其他驅動 是不會安裝的。
    安裝完之後,可以在“控制面板”->“性能和維護”->“管理工具”的“數據源 (ODBC)”中查看一下:
其中的“Adaptive Server Enterprise”就是Sybase的ODBC驅動。
    不過至此我們的安裝工作還沒有結束,如果不想看到自己輸入的中文變成亂碼,就按照下面方法去做。
    請 點擊“開始”菜單->“所有程序”->“Sybase”->“Adaptive Server Enterprise”->“Server Config”,打開“Configure Sybase Server”窗口。在窗口左側的Product欄中選擇Adaptive,然後點擊“Configure Adaptive Server...”按鈕,打開“Existing Servers”窗口。在窗口選中服務器,然後點擊Continue按鈕進入下一窗口。輸入用戶名和密碼,默認用戶名爲sa,密碼爲空,點擊 Continue。此時如果服務沒啓,Sybase會提示,點擊“確定”,稍等片刻,“Configure Adaptive Server”窗口就出現了。
在窗口中點擊“Language”按鈕,打開“Language Options”窗口。
點擊Character下的“Add/Remove”按鈕,打開“Install Character Sets”窗口,在Available欄中選中“Unicode 3.1 UTF-8 CHaracter Set”,即utf8字符集,點擊“Add”按鈕,點擊OK。下面再點擊Character下的“Set Default”按鈕,打開“Change Default Character Set”窗口,默認選中的是“Code Page 850 (Multilingual) character set”,即cp850字符集。這個字符集不對,請選中剛剛添加的utf8字符集,點擊OK,回到“Language Options”窗口,然後再點擊OK。由於我們對服務重新進行了設置,因此接下來需要等待一段時間。
    設置完成後,打開“運行”窗口,輸 入命令“services.msc /s”,打開“服務”。請選中“Sybase SQLServer _ IMAGE”,IMAGE是我的Sybase服務名,點擊“啓動服務”按鈕,等待片刻後,系統提示此次啓動失敗,重啓操作系統。重啓後,再次在“服務”中 啓動Sybase,如果還是提示錯誤,不要管他,再次啓動服務一切就OK了。
    服務啓動後,請點擊“開始”菜單->“所有程 序”->“Sybase”->“Sybase Central v4.3”,打開Sybase Central,這是一個Sybase客戶端工具。在左側的Folders中點開Adaptive Server Enterprise,選中Default,右建,選擇“Connect...”,打開Connect窗口。
在窗口中填寫User ID爲sa,Password爲空,Server name選擇IMAGE,Character set和Language分別設置爲cp936和Chinese。注意,這裏客戶端設置的字符集是cp936,而非cp850、utf8或者eucgb。 設置好後,點擊OK,就可以開始對Sybase的操作了。
二、簡單操作
1.創建數據庫設備
    數據庫設備其實就是一個用來保存數據的文件,一個數據庫通常會指定保存在一個或多個數據庫設備中。
    在 Sybase Central的Folders中找到Database Devices(數據庫設備),選中,然後在Details中雙擊“Add Database Device”。在彈出窗口的“Device Path”中設置存放路徑和文件名稱,我設置的是F:\YPJCCK\DataBase\Sybase\zhengTest.dat,點擊Next。新界 面是用來設置設備編號和文件大小的,這裏我只設置Size爲64M。點擊Next,無需修改,再次點擊Next:
這個界面是用來展示設置信息的,用戶可以根據這些信息確定自己之前的設置是否正確。請注意Preview按鈕,點擊該按鈕後即通過可查看到創建設備 的SQL語句。Sybase Central在創建視圖、存儲過程及觸發器等對象時同樣會提供該功能。確認信息無誤,點擊Finish創建設備。
    如果想在設備創建後查看SQL語句,請在Details中選中相應設備,右鍵,點擊Generate DDL就可以了。
    如果想刪掉設備,請在Details中選中相應設備,右鍵,點擊Delete:
這個界面是用來確認刪除對象的,確認後點擊Yes即可。這裏也請注意Preview按鈕,點擊該按鈕後同樣可以查看到刪除設備的SQL語句,而且Sybase Central在刪除表、視圖、存儲過程及觸發器等對象時也都提供了該功能。
2.創建數據庫
    在 Sybase Central的Folders中找到Databases(數據庫),選中,然後在Details中雙擊“Add Database”。在彈出窗口中設置數據庫名稱,我設置的是zhengTest,點擊Next。新界面是用來爲數據庫指定設備的,可以指定多個,請點擊 Add按鈕:
在彈出窗口中選中設備zhengTest,然後設置Size爲32,點擊OK返回,再點擊Finish,數據庫就被創建了。
    如果想 在數據庫創建後查看SQL語句,請在Details中選中zhengTest,右鍵,點擊Generate DDL。不過數據庫的Generate DDL下還有兩個子菜單,第一個爲Create Database DDL,選擇後只會看到創建數據庫本身的SQL語句;第二個爲Database Object DDL,點擊後會出現一個對話框:
這個對話框列出了數據庫中的所有對象類型,但要注意,在這個對話框中,選擇了哪個類型,屬於那個類型的對象的就不會出現在彈出窗口中,而沒有選擇的則會出現。Sybase Central對錶、視圖、存儲過程、觸發器等對象都提供了Generate DDL。
    如果想刪掉數據庫,只要選中zhengTest,右鍵,點擊Delete,或者在Interactive SQL(Sybase自帶的一個SQL命令執行工具,) 中執行命令:
    drop database zhengTest
即可。Sybase Central對錶、視圖、存儲過程、觸發器等對象也都提供了Delete。
3.創建數據表
    在Sybase Central的Folders中找到zhengTest->User Tables並選中,然後在Details中雙擊“Add Table”,打開“New Table”窗口:
在窗口中設置Name爲book,添加兩個字段:
    bookcode    nvarchar(10)    主鍵
    bookname    nvarchar(50)
然後點擊“Save and Close”按鈕,這樣book表就創建好了。
    下 面選中book表,右鍵,點擊“View Data in Interactive SQL”,就可以在Interactive SQL中查詢book的數據了。不過由於我們還沒有向book表中添加過任何數據,因此看到的結果爲空。請在Interactive SQL中執行以下命令:
    insert into book (bookcode, bookname) values ('0000000001', 'test')
    go
    insert into book (bookcode, bookname) values ('0000000002', '測試')
    go
然後再次執行select * from book,此時就看到剛剛插入的數據了。
    不過我現在又有了個新的想法,爲book表增加一個anthor,即作者字段。但一個作者似乎可以創作很多書,要是每條記錄都將作者信息重複填寫一遍,好麻煩啊,該怎麼辦呢?
    請在Sybase Central中創建一個新表author,字段如下:
    authorcode    nvarchar(10)    主鍵
    authorname    nvarchar(20)
創建之後,在Interactive SQL中向author表插入一條數據:
    insert into author (authorcode, authorname) values ('0000000001', 'Smile')
    下面選中book,右鍵,點擊Edit,修改book表如下:
新增加bookauthor字段,類型爲nvarchar(10),由於增加該字段之前表中已有數據,爲防止出錯須選中Allow Nulls,即允許該字段爲空。修改之後,在Interactive SQL中更新book表中的數據:
    update book set bookauthor = '0000000001'
這時再次查詢數據:
    select bookcode, bookname, authorname from book, author where bookauthor *= authorcode
就看到期待已久的結果了。
    如果想刪掉表,只要選中book,右鍵,點擊Delete,或者在Interactive SQL 中執行命令:
    drop table dbo.book
即可。
4.創建視圖
    視圖是虛擬的表,其特點是操作簡單、使用安全。
    請 在Sybase Central的Folders中找到zhengTest->Views並選中,然後在Details中雙擊“Add View(Wizard)”,打開“Add Trigger”嚮導。在第一個界面中輸入視圖名v_book,點擊Next進入下一個界面。
這個界面是用來編寫代碼的,除可以在文本域中編寫外,還提供有“SQL Editor”和“Load”兩個按鈕,前者點擊後會調出一個Sybase自帶的編輯器,下面在編輯器中編寫代碼如下:
    CREATE VIEW dbo.v_book
    AS select bookcode, bookname, authorname 
        from book, author 
        where bookauthor *= authorcode
然 後點擊“Save view and close”回到剛纔的界面;後者用於加載已經完成的SQL語句,這裏不使用。點擊Finish按鈕,Sybase提示視圖v_book已存在,因爲剛纔 在編輯器中點擊的是“Save view and close”,即保存視圖並關閉。此時點擊OK,然後點擊Cancel即可。類似的界面在後面編寫存儲過程和觸發器的時候還會遇到。
    下面選中視圖v_book,右鍵,點擊“View Data in Interactive SQL”,就可以在Interactive SQL中使用v_book來查詢數據了。
    如果想刪掉視圖,只要選中v_book,右鍵,點擊Delete,或者在Interactive SQL 中執行命令:
    drop view dbo.v_book
即可。
5.創建存儲過程
    存儲過程是一組存儲在數據庫服務器段執行特定操作的SQL語句,具有創建時編譯、可重複使用、安全性高等特點。
    最簡單的存儲過程(查詢):
    在Sybase Central的Folders中找到zhengTest->Stored Procedures並選中,然後在Details中雙擊“Add Procedures(Wizard)”,打開“Add Stored Procedure”嚮導。在第一個界面中填寫存儲過程名稱,例如simple_query,點擊Next。在接下來的兩個界面中不必進行任何操作,直接 點擊Next。在第四個界面中輸入代碼:
    CREATE PROCEDURE dbo.simple_query
    AS select bookcode, bookname, authorname 
        from book, author 
        where bookauthor *= authorcode
點擊Finish。至此,存儲過程創建完畢。
    這個存儲過程最爲簡單,即沒有參數,也沒有返回值,更沒有任何邏輯處理。
下 面選中存儲過程simple_query,右鍵,點擊“Execute with Interactive SQL”,在Interactive SQL中會生成一條語句“exec dbo.simple_query”,其中exec全拼爲execute,表示執行存儲過程。執行後,會返回一個結果集,即SQL語句的執行結果。
    下面來看一個內容相對完整的存儲過程例子:
    CREATE PROCEDURE dbo.simple_demo
    (
        @i_mesg nvarchar(100) = 'Y',            --輸入參數,設置默認值爲'Y'
        @o_mesg nvarchar(100) output       --輸出參數
    )
    AS
    BEGIN
        if @i_mesg = 'Y'    --邏輯處理
        begin
            select @o_mesg = '運行正常!'    --在Sybase中需要使用select語句爲變量賦值
            return 0        --返回值
        end
        select @o_mesg = '運行異常!'
        return -1           --返回值
    END
這個存儲過程雖然沒有調用數據表,但帶有輸入參數、輸出參數、邏輯處理和返回值,因此內容相對完整。這裏請注意,返回值只能是整數,而輸出參數也可以用來將值傳入並設置默認值。
下面在Interactive SQL中執行以下代碼:
    declare @o_mesg nvarchar(100),      --定義變量
                   @ret int
    exec @ret = dbo.simple_demo 'N', @o_mesg output     --執行存儲過程,注意,輸出參數必須標以output,否則不會輸出任何值
    print '%1!--------%2!', @ret, @o_mesg               --輸出結果
按F5鍵執行,輸出結果:-1--------運行異常!
    下面將這段代碼寫到存儲過程當中:
    CREATE PROCEDURE dbo.simple_call
    AS
    BEGIN
        declare @o_mesg nvarchar(100),
                       @ret int
        exec @ret = dbo.simple_demo 'N', @o_mesg output
        print '%1!--------%2!', @ret, @o_mesg
    END
這是一個存儲過程調用存儲過程的例子了。
    下面再新建一個simple_execute存儲過程,代碼如下:
    CREATE PROCEDURE dbo.simple_execute
    AS
    BEGIN
        execute ('select * from v_book')
    END
這個存儲過程含有兩個內容:一個SQL語句的動態執行,即Sybase中允許將SQL語句處理成一個字符串或字符串變量來執行;一個是對視圖的訪問。
    下面再看幾個存儲過程的例子。
    通過遊標讀取數據示例:
CREATE PROCEDURE dbo.p_query_list
AS
BEGIN
    declare @bc nvarchar(10)
                 ,@bn nvarchar(50)
                 ,@an nvarchar(20)
    --定義遊標
    declare book_curs cursor for 
    select bookcode, bookname, authorname 
        from book, author 
        where bookauthor *= authorcode
        order by bookcode
    open book_curs --打開遊標
    --循環遊標讀取數據
    fetch book_curs into @bc, @bn, @an
    while (@@sqlstatus = 0)
    begin
        print '編號:%1!|名稱:%2!|作者:%3!', @bc, @bn, @an
        fetch book_curs into @bc, @bn, @an
    end
    close book_curs --關閉遊標
    deallocate cursor book_curs --釋放遊標
END
    通過變量讀取數據示例:
CREATE PROCEDURE dbo.p_query_detail
@query      nvarchar(10)
AS
BEGIN
    declare @bookcode   nvarchar(10),
                  @bookname   nvarchar(50),
                  @authorname nvarchar(20)
    /* top用來指定取得結果集的前n條數據,這裏使用top 1即表示取得結果集的第一條記錄,否則當結果集中有多條記錄時,只有最後一條記錄的值纔會被賦值給變量 */
    select top 1 @bookcode = bookcode, @bookname = bookname, @authorname = authorname from v_book where bookcode = @query
    print '編號:%1!|名稱:%2!|作者:%3!', @bookcode, @bookname, @authorname
END
執行:在Sybase Central中選中p_query_detail,右鍵,點擊“Execute with Interactive SQL”,由於p_query_detail有一個輸入參數,因此Central會彈出一個Call窗口:
在窗口中填值時一定要注意,由於數據類型爲nvarchar(10),爲字符串,因此一定要在值的兩邊加上單引號“’”。然後點擊OK,在Interactive SQL中按F5鍵執行該存儲過程。
    使用存儲過程插入數據示例:
CREATE PROCEDURE dbo.p_insert
@bookname   nvarchar(50),
@bookauthor nvarchar(10),
@mesg       nvarchar(200) = 'ok' output
AS
BEGIN
    declare @bookcode nvarchar(10)
    --使用月、日、時、分、秒組成bookcode
    select @bookcode = convert(nvarchar(10), datepart(mm,getdate())*100000000 + datepart(dd,getdate())*1000000 + datepart(hh,getdate())*10000 + datepart(mi,getdate())*100 + datepart(ss,getdate()))
   
    --插入數據到book表
    insert into book (bookcode, bookname, bookauthor) values (@bookcode, @bookname, @bookauthor)
    if @@error <> 0 --異常處理
    begin
        select @mesg = '新增數據異常!' + convert(nvarchar(3), @@error)
        rollback    --事務回滾
        return -1
    end
    commit  --事務提交
    return 0
END
執行:在Interactive SQL中嘗試執行以下代碼調用p_insert存儲過程:
    declare @mesg nvarchar(200),
                   @flag int
    exec @flag = p_insert 'NUnit學習筆記', '0000000001', @mesg output
    if @flag <> 0
    begin
        print @mesg
    end
    else
    begin
        print '程序運行正常!'
    end
    go
    使用存儲過程修改數據示例:
CREATE PROCEDURE dbo.p_update
@bookcode   nvarchar(10),
@bookname   nvarchar(50),
@bookauthor nvarchar(10)
AS
BEGIN
    update book set bookname = @bookname, bookauthor = @bookauthor where bookcode = @bookcode
END
    使用存儲過程刪除數據示例:
CREATE PROCEDURE dbo.p_delete
@bookcode nvarchar(10)
AS
BEGIN
    delete book where bookcode = @bookcode
END
    如果想刪掉存儲過程,只要選中simple_query,右鍵,點擊Delete,或者在Interactive SQL 中執行命令:
    drop procedure dbo.simple_query
即可。
6.創建觸發器
    觸發器是因某一行爲而自動做出反應並進行特定操作的一組SQL語句,可以理解爲表的事件。例如在對錶進行插入、修改或刪除數據等操作時,都會導致觸發器被觸發。這裏我會創建三個觸發器,分別對應book表的插入、修改和刪除操作。
    insert觸發器:
    在Sybase Central的Folders中找到zhengTest->User Tables->book->Triggers並選中,然後在Details中雙擊“Add Trigger(Wizard)”,打開“Add Trigger”嚮導。在第一個界面中填寫觸發器名稱,例如t_insert,點擊Next;在第二個界面中選擇Insert,點擊Next;在第三個界 面中輸入代碼:
CREATE TRIGGER dbo.t_insert ON dbo.book
    For INSERT AS
BEGIN
    declare @bookcode   nvarchar(10),
                   @bookname   nvarchar(50),
                   @bookauthor nvarchar(20)
    select @bookcode = bookcode, @bookname = bookname, @bookauthor = bookauthor from inserted
    print '編號:%1!|名稱:%2!|作者:%3!', @bookcode, @bookname, @bookauthor
END
點擊Finish。至此,insert觸發器創建完畢。
    觸 發器其實也可以認爲是一種存儲過程,就像我們在VB、VC、Delphi、Swing等開發中寫的事件處理方法一樣,只不過這個存儲過程即沒有參數,也沒 有返回值,更不允許返回結果集,例如select * from book這種語句是絕對不能寫到觸發器中的。此外,觸發器中有兩個邏輯表,inserted和deleted,前者代表新插入或更新的值,後者代表數據表 中已存在並將被更新掉或刪除掉的值,這裏用到了inserted。下面趕緊向book表中插入一條數據,看看效果吧!
    update觸發器,代碼:
CREATE TRIGGER dbo.t_update ON dbo.book
    For UPDATE AS
BEGIN
    IF UPDATE (bookname)
    BEGIN
        rollback transaction
    END
    declare @o_mesg nvarchar(100),
                   @ret int
    exec @ret = dbo.simple_demo 'N', @o_mesg output
    print '%1!--------%2!', @ret, @o_mesg
END
這 裏需要說明的是IF UPDATE (bookname),該語句判斷bookname字段是否被更新,在這裏,bookname被更新便會導致回滾,即數據永遠無法通過update bookname字段的方式更改。當有多個字段需要作這種判斷時,只要寫作“IF UPDATE(bookcode) and|or UPDATE(bookname)”即可。此外,邏輯表inserted、deleted在update觸發器中同樣有效,相關說明請見insert觸發 器。
    delete觸發器,代碼:
CREATE TRIGGER dbo.t_delete ON dbo.book
    For DELETE AS
BEGIN
    declare @bc nvarchar(10)
                 ,@bn nvarchar(50)
                 ,@ba nvarchar(10)
    --定義遊標
    declare del_curs cursor for 
        select bookcode, bookname, bookauthor 
        from deleted
        order by bookcode
    open del_curs --打開遊標
    --循環遊標讀取數據
    fetch del_curs into @bc, @bn, @ba
    while (@@sqlstatus = 0)
    begin
        print '編號:%1!|名稱:%2!|作者:%3!', @bc, @bn, @ba
        fetch del_curs into @bc, @bn, @ba
    end
    close del_curs --關閉遊標
    deallocate cursor del_curs --釋放遊標
END
這裏使用了邏輯表deleted和遊標來查詢被刪除的數據。
    注意,insert、update、delete觸發器在每張表中都只允許創建一個,如果再次創建,例如insert觸發器,無論使用什麼 名字,如test_trigger,之前創建的insert觸發器都會被覆蓋掉。此外,Sybase也允許在一個觸發器中指定多個操作,例如:
CREATE TRIGGER dbo.t_author ON dbo.author
 For INSERT, DELETE, UPDATE AS
BEGIN
    print 'author表的觸發器被執行!'
END
這個觸發器就同時被指定了insert、update和delete操作。
    此外,我們還可以指定觸發器失效或者有效,只要選中觸發器,右鍵,點擊Disable/Enable,或者在Interactive SQL 中執行命令:
    alter table dbo.book disable| enable trigger dbo.t_insert
即可。
    如果想刪掉觸發器,只要選中觸發器,右鍵,點擊Delete,或者在Interactive SQL 中執行命令:
    drop trigger dbo.t_insert
即可。
三、使用Java訪問Sybase
    我寫了兩個Java訪問Sybase的例子,IDE任意,驅動位於${Sybase安裝目錄}\jConnect-6_0\devclasses下, 將文件jconn3d.jar引入即可。
    第一個例子的代碼如下:
package net.test.db.sybase;
import java.sql.*;
public class TestQuery {
 public static void main(String[] args) {
     Connection cn = null;
     CallableStatement cs = null;
     ResultSet rs = null;
     try {
        // 初始化連接對象
        Class.forName("com.sybase.jdbc3.jdbc.SybDriver");
        cn = DriverManager.getConnection("jdbc:sybase:Tds:p_w_picpath:5000/zhengTest?charset=cp936&jconnect_version=3", "sa", "");
        cs = cn.prepareCall("{call simple_query()}"); // 獲得聲明對象
        rs = cs.executeQuery(); // 執行,當有結果集時使用executeQuery()方法執行
        while (rs.next()) {
            System.out.print("編號:" + rs.getString(1));
            System.out.print("|名稱:" + rs.getString(2));
            System.out.println("|作者:" + rs.getString(3));
        }
        if (rs != null)
            rs.close(); //關閉結果集
        if (cs != null)
            cs.close(); // 關閉聲明
        if (cn != null)
            cn.close(); // 關閉連接
    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        rs = null;
        cs = null;
        cn = null;
    }
 }
}
這 個例子演示的是如何訪問存儲過程simple_query,該存儲過程會返回一個結果集。這裏需要注意兩點:由於simple_query會返回一個結果 集,因此需要使用cs.executeQuery()方法執行;在設置連接字符串的時候,設置了charset=cp936,即將客戶端的字符集設置成 cp936,這樣查看結果時纔不會亂碼。
    第二個例子的代碼如下:
package net.test.db.sybase;
import java.sql.*;
public class TestDemo {
 public static void main(String[] args) {
  Connection cn = null;
  CallableStatement cs = null;
  try {
   // 初始化連接對象
   Class.forName("com.sybase.jdbc3.jdbc.SybDriver");
   cn = DriverManager.getConnection("jdbc:sybase:Tds:p_w_picpath:5000/zhengTest?charset=cp936&jconnect_version=3","sa", "");
   cs = cn.prepareCall("{?=call simple_demo(?,?)}"); // 獲得聲明對象
   // 設置參數
   cs.registerOutParameter(1, Types.INTEGER);
   cs.setString(2, "N");
   cs.registerOutParameter(3, Types.VARCHAR);
   cs.execute(); // 執行,當沒有返回結果集時,爲防止出錯,使用execute()方法作執行
   // 輸出處理結果
   System.out.println(cs.getInt(1));
   System.out.println(cs.getString(3));
   if (cs != null)
    cs.close(); // 關閉聲明
   if (cn != null)
    cn.close(); // 關閉連接
  } catch (Exception ex) {
   ex.printStackTrace();
  } finally {
   cs = null;
   cn = null;
  }
 }
}
這個例子演示的是動態訪問存儲過程simple_demo,該存儲過程帶有一個輸出參數,並有一個返回值,在JDBC中,返回值和輸出參數可以認爲是一回事。這裏需要注意的是,由於這個存儲過程沒有結果集,因此執行時應該使用cs.execute()方法。
四、使用VB.net/C#訪問Sybase
    我 寫了兩個VB.net/C#訪問Sybase的例子,IDE使用SharpDevelop 2.1,環境爲.net Framework 2.0,驅動位於${Sybase安裝目錄}\DataAccess\ADONET\dll下, 引用其中的文件Sybase.Data.AseClient.dll到項目中即可。
    第一個例子的VB.net代碼如下:
Imports Sybase.Data.AseClient
Public Class TestQuery
 Sub New()
  Dim cn As AseConnection = Nothing
  Dim cmd As AseCommand = Nothing
  Dim rd As AseDataReader = Nothing
   
  Try
   '初始化連接對象
   cn = New AseConnection("Data Source=p_w_picpath;Port=5000;UID=sa;PWD=;Database=zhengTest;CharSet=cp936;")
    
   cn.Open() '打開連接
    
   cmd = New AseCommand("exec simple_query", cn) '獲得命令對象
    
   rd = cmd.ExecuteReader() '執行,當有隻讀記錄集時使用ExecuteReader()方法執行
   While rd.Read() 
    Console.Write("編號:" & rd.GetString(0))
    Console.Write("|名稱:" & rd.GetString(1))
    Console.WriteLine("|作者:" & rd.GetString(2))
   End While
   If rd IsNot Nothing Then
    rd.Close() '關閉只讀記錄集
   End If
   If cmd IsNot Nothing Then
    cmd.Dispose() '銷燬命令對象
   End If
   If cn IsNot Nothing Then
    cn.Close() '關閉連接對象
   End If
  Catch ex As AseException
   Console.WriteLine(ex.Message)
  Finally
   rd = Nothing
   cmd = Nothing
   cn = Nothing
  End Try
 End Sub
End Class
    C#代碼如下:
using System;
using Sybase.Data.AseClient;
namespace zhengTest_Sybase
{
 public class TestQuery
 {
  public TestQuery()
  {
   AseConnection cn = null;
   AseCommand cmd = null;
   AseDataReader rd = null;
   
   try
   {
    //初始化連接對象
    cn = new AseConnection("Data Source=p_w_picpath;Port=5000;UID=sa;PWD=;Database=zhengTest;CharSet=cp936;");
    
    cn.Open(); //打開連接
    
    cmd = new AseCommand("exec simple_query", cn); //獲得命令對象
    
    rd = cmd.ExecuteReader(); //執行,當有隻讀記錄集時使用ExecuteReader()方法執行
    while(rd.Read())
    {
     Console.Write("編號:" + rd.GetString(0));
     Console.Write("|名稱:" + rd.GetString(1));
     Console.WriteLine("|作者:" + rd.GetString(2));
    }
    
    if (rd != null)
     rd.Close(); //關閉只讀記錄集
    if (cmd != null)
     cmd.Dispose(); //銷燬命令對象
    if (cn != null)
     cn.Close(); //關閉連接對象
   }
   catch( AseException ex )
   {
    Console.WriteLine(ex.Message);
   }
   finally
   {
    rd = null;
    cmd = null;
    cn = null;
   }
  }
 }
}
跟 第一個Java例子一樣,也是演示如何訪問simple_query存儲過程並對記錄集進行操作的。這裏請注意幾點:第一,連接字符串中Data Source=p_w_picpath指的不是數據源,而是服務器,與設置Server=p_w_picpath效果一樣;第二,連接字符串中的CharSet=cp936用來設 置字符集,但從當前環境看,這個設置不是必須的,至於我是如何知道該參數有效的,我將字符集設置成cp850後出現亂碼了;第三,由於 simple_query會返回一個結果集,因此需要使用ExecuteReader方法來執行,這點與Java很類似。
    第二個例子的VB.net代碼如下:
Imports System.Data
Imports Sybase.Data.AseClient
Public Class TestDemo
 Sub New()
  Dim cn As AseConnection = Nothing
  Dim cmd As AseCommand = Nothing
  Try
   '初始化連接對象
   cn = New AseConnection("Data Source=p_w_picpath;Port=5000;UID=sa;PWD=;Database=zhengTest;")
   
   cn.Open()'打開連接
   
   cmd = New AseCommand("simple_demo", cn) '獲得命令對象
   cmd.CommandType = CommandType.StoredProcedure '設置命令類型爲存儲過程
   '設置參數
   cmd.Parameters.Add("RETURN_VALUE", AseDbType.[Integer]).Direction = ParameterDirection.ReturnValue
   cmd.Parameters.Add("@i_mesg", "N")
   cmd.Parameters.Add("@o_mesg", AseDbType.NVarChar, 50).Direction = ParameterDirection.Output
   cmd.ExecuteNonQuery() '執行,當沒有返回結果集時,使用ExecuteNonQuery()方法作執行
   '輸出處理結果
   Console.WriteLine(cmd.Parameters(0).Value)
   Console.WriteLine(cmd.Parameters(2).Value)
   If cmd IsNot Nothing Then
    cmd.Dispose() '銷燬命令對象
   End If
   
   If cn IsNot Nothing Then
    cn.Close() '關閉連接對象
   End If
  Catch ex As AseException
   Console.WriteLine(ex.Message)
  Finally
   cmd = Nothing
   cn = Nothing
  End Try
 End Sub
End Class
    C#代碼如下:
using System;
using System.Data;
using Sybase.Data.AseClient;
namespace zhengTest_Sybase
{
 public class TestDemo
 {
  public TestDemo()
  {
   AseConnection cn = null;
   AseCommand cmd = null;
   
   try
   {
    //初始化連接對象
    cn = new AseConnection("Data Source=p_w_picpath;Port=5000;UID=sa;PWD=;Database=zhengTest;");
    
    cn.Open(); //打開連接
    
    cmd = new AseCommand("simple_demo", cn); //獲得命令對象
    cmd.CommandType = CommandType.StoredProcedure; //設置命令類型爲存儲過程
    
    //設置參數
    cmd.Parameters.Add("RETURN_VALUE", AseDbType.Integer).Direction = ParameterDirection.ReturnValue;
    cmd.Parameters.Add("@i_mesg", "N");
    cmd.Parameters.Add("@o_mesg", AseDbType.NVarChar, 50).Direction = ParameterDirection.Output;
    
    cmd.ExecuteNonQuery(); //執行,當沒有返回結果集時,使用ExecuteNonQuery()方法作執行
    
    //輸出處理結果
    Console.WriteLine(cmd.Parameters[0].Value);
    Console.WriteLine(cmd.Parameters[2].Value);
    
    if (cmd != null)
     cmd.Dispose(); //銷燬命令對象
    if (cn != null)
     cn.Close(); //關閉連接對象
   }
   catch( AseException ex )
   {
    Console.WriteLine(ex.Message);
   }
   finally
   {
    cmd = null;
    cn = null;
   }
  }
 }
}
跟 第二個Java例子類似,演示如何訪問simple_demo存儲過程。不過ADO.net調用存儲過程的方式與JDBC不同,只允許在命令對象中輸入過 程名作爲語句,而且不支持“?”佔位符。關於參數設置中用到的RETURN_VALUE、@i_mesg、@o_mesg,分別代表 simple_demo的返回值和兩個參數。由於simple_demo不會返回記錄集,因此需要使用ExecuteNonQuery方法來執行。這裏推 薦一下文章《將存儲過程用於命令》,該文對ADO.net訪問存儲過程進行了比較詳細的介紹,從.net Framework自帶文檔或網上都能找到。
    另外,再提供兩個連接字符串:
    Sybase for OLED:PROVIDER=ASEOLEDB;Server=p_w_picpath;Port=5000;User Id=sa;Password=;Initial Catalog=zhengTest;CharSet=cp936;
請注意字符串中的Initial Catalog=zhengTest,表示要訪問我在Sybase中創建的zhengTest數據庫,而CharSet=cp936是用來設置字符集的,不設置會亂碼。
    Sybase for ODBC:DSN=zhengTest_Sybase;UID=sa;PWD=;CharSet=cp936;
字符串中的DSN=zhengTest_Sybase表示訪問我在ODBC中設置的數據源zhengTest_Sybase(如何在ODBC中設置數據源就不演示了),而CharSet=cp936也是用來設置字符集的,但在當前環境中不是必須的。
 關於OLEDB和ODBC的使用,與示例類似,請參考其他ADO.net書籍或文檔。
五、使用Perl訪問Sybase
     我使用的Perl是5.8.8 build 820,雖然默認不帶數據庫訪問接口,但可以使用工具ppm下載到DBI。
     打 開命令行工具,輸入ppm search dbi,查找dbi,有183個結果,我們需要的是第56個——DBI v1.57。下面執行命令ppm install dbi,如果提示錯誤,請嘗試ppm install 56,即安裝查詢結果中的第56個。不過安裝結束後,暫時還是無法使用DBI來連接數據庫,因爲DBI提供的只是一套數據庫接口,而不是數據庫驅動,因此 還需要安裝dbd-ado和dbd-odbc,安裝方法同dbi。
    不過您或許已經注意到了,我使用的dbi版本不是最新的1.58,而且驅動也不是dbd-sybase,的確,因爲這些都沒有安裝包,只能從http://www.perl.com/CPAN/上 下載源碼自己編譯。我自己倒是也做了不少嘗試,包括安裝FreeTDS,在cygwin和WinGW中make,結果都失敗了,自己推測原因大約是 Perl和DBI、DBD-SYBASE之間版本不對應,畢竟這些東東每個版本接口都會有所變化。最後在經過一週的折磨之後,終於連編譯Ruby的 dbd_sybase模塊的想法統統放棄了。
     這裏也是兩個例子。第一個例子的代碼如下:
use DBI;
#創建連接對象,類型爲ADO
$dbh=DBI->connect('DBI:ADO:PROVIDER=ASEOLEDB;Server=p_w_picpath;Port=5000;User Id=sa;Password=;Initial Catalog=zhengTest;CharSet=cp936;');
$sth=$dbh->prepare('exec simple_query' ); #獲得聲明對象
$sth->execute; #當有結果集時,使用execute方法
while (@row=$sth->fetchrow_array) {
  print '編號:', $row[0];
  print '|名稱:', $row[1];
  print '|作者:', $row[2], "\n";
}
$sth->finish if $sth; #關閉聲明
$dbh->disconnect if $dbh; #斷開連接
也是演示如何訪問simple_query存儲過程並對結果集進行 操作的。這裏請注意兩點:第一,本例使用的驅動類型爲ADO,其連接字符串中,Initial Catalog=zhengTest表示要訪問我在Sybase中創建的zhengTest數據庫,而CharSet=cp936則表示設置字符集爲 cp936,目的在於避免亂碼;第二,由於simple_query會返回一個結果集,因此需要使用execute方法來執行,這點與前面很類似。
    第二個例子的代碼如下:
use DBI;
#創建連接對象,類型爲ODBC
$dbh=DBI->connect('DBI:ODBC:DSN=zhengTest_Sybase;UID=sa;PWD=;CharSet=cp936;');
$sql='{?=call simple_demo(?,?)}';
$ret='';
$msg='';
$sth=$dbh->prepare($sql); #獲得聲明對象
#設置參數
$sth->bind_param_inout(1, \$ret, 1);
$sth->bind_param(2, 'N');
$sth->bind_param_inout(3, \$msg, 100);
$sth->execute; #執行
#輸出處理結果
print $ret, "\n";
print $msg, "\n";
$sth->finish if $sth; #關閉聲明
$dbh->disconnect if $dbh; #斷開連接
也是演示動態訪問simple_demo存儲過程的。這裏需要注意 的是,本例使用的驅動類型爲ODBC,其連接字符串中,DSN=zhengTest_Sybase表示訪問我在ODBC中設置的數據源 zhengTest_Sybase,而CharSet=cp936則表示設置字符集爲cp936,這裏是必須的。
六、使用Ruby訪問Sybase
    我使用的Ruby是1.8.6-25,已安裝Rails 1.2.3。由於Ruby默認不帶數據庫訪問接口,因此請先從http://rubyforge.org/projects/ruby-dbi下載ruby-dbi,當前版本0.1.1。由於Ruby版本的DBI是從Perl版本演變過來的,因此兩者有很多相似之出。
    下載完dbi-0.1.1.tar.gz文件之後,解壓縮,在命令行中定位到解壓後的目錄下,例如F:\ruby-dbi,執行命令:
    ruby setup.rb config --with=dbi,dbd_ado,dbd_odbc
    ruby setup.rb setup
    ruby setup.rb install
此時dbi接口連帶dbd_ado、dbd_odbc驅動就都安裝到系統中了。
    據 說dbi所提供的驅動僅是表層的,如果要使用還需要安裝底層驅動,例如PostgreSQL,就還需要安裝ruby-postgres。不過似乎是因爲我 安裝了Rails的緣故(Rails帶有activerecord,據說裏邊包含了很多驅動),我在使用的過程中倒也沒被要求安裝底層驅動。
    此 外,我也沒有使用dbd_sybase驅動。不知道爲什麼,dbd_sybase居然需要編譯,而我在cygwin和Windows命令行下都進行過嘗 試,還安裝了MinGW(GCC的Windows版本),甚至查找了perl-dbi和freetds的資料,結果還是失敗。最可恨的是 dbd_sybase調用的接口居然跟freetds和ruby中定義的接口不一致,後來看了dbd_sybase代碼才發現,居然是2001年的。最 後,dbd_sybase到底沒裝上,可是make倒學會了。汗!
    這裏也是還個例子。第一個例子的代碼如下:
require 'dbi'
#創建連接對象,類型爲ADO
dbh=DBI.connect('DBI:ADO:PROVIDER=ASEOLEDB;Server=p_w_picpath;Port=5000;User Id=sa;Password=;Initial Catalog=zhengTest;CharSet=cp936;')
sth=dbh.prepare('exec simple_query') #獲得聲明對象
sth.execute #當有結果集時,使用execute方法
while row=sth.fetch do
  print '編號:', row[0]
  print '|名稱:', row[1]
  print '|作者:', row[2], "\n"
end
sth.finish if sth #關閉聲明
dbh.disconnect if dbh #斷開連接
    第二個例子的代碼如下:
require 'dbi'
#創建連接對象,類型爲ODBC
dbh=DBI.connect('DBI:ODBC:DSN=zhengTest_Sybase;UID=sa;PWD=;CharSet=cp936;')
sql='{?=call simple_demo(?,?)}' #支持該代碼
ret=''
msg=''
sth=dbh.prepare(sql)  #獲得聲明對象
#設置參數
sth.bind_param(1, ret)
sth.bind_param(2, 'N')
sth.bind_param(3, msg)
sth.execute  #執行
#由於dbi不支持輸出參數,因此這裏無法獲取simple_demo的返回值與輸出參數
sth.finish if sth #關閉聲明
dbh.disconnect if dbh #斷開連接
演示動態訪問simple_demo存儲過程。不過由於dbi不支持存儲過程的輸出參數,注意是存儲過程,所以在這個示例中沒有獲取返回值的代碼。
    也不知道爲什麼,dbi只支持函數的輸出參數,而不支持存儲過程的輸出參數,似乎SQL Server和DB2的存儲過程也同樣無法返回輸出參數。
    由 於本文只是使用Ruby訪問Sybase,因此沒打算對dbi作深入介紹。如果對dbi有興趣,建議在網上找一篇名爲《firstworks Programming with SQL Relay using the Ruby DBI API》的文章,雖然是英文的,但內容很全面,對多種數據庫都有介紹,值得一看。
    別告訴我你英文不好,我英文也不好,不也是用着金山詞霸就那麼看了嗎^_^
七、小結
    本文只是對Sybase操作的簡單介紹,像索引、序列這些都沒有作說明,而且給出的Java、.net、Perl和Ruby示例也都比較簡單,如果希望瞭解更多內容,還請參考其他書籍或文檔。
    此 外,SQL Server與Sybase系出同門,大約是在Sybase 6的時候微軟不願再同Sybase公司合作而分成兩支的,因此如果手頭缺少Sybase資料,也不妨參考一下SQL Server的文檔。不過作爲一款大型數據庫,Sybase至今已發佈了15個大的版本,卻不知道爲什麼,在程序漢化和幫助文檔方面做得始終很差,而且提 供的功能也很弱,像用戶自定義函數、try-catch語句和row_number函數這些,至今沒有,因此在使用SQL Server文檔的時候,如果發現某些功能在Sybase中實現不了,請不要奇怪。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章