1. 程式人生 > >Linux C語言程式設計-Linux資料庫操作--Linux上C語言操作SQLServer---知識點總結+例項

Linux C語言程式設計-Linux資料庫操作--Linux上C語言操作SQLServer---知識點總結+例項

*********************注意:為了保證文章的完整性和全面性,作者會不定期對文章進行更新和修正*********************
1.freetds是什麼?
    freetds其實就是個軟體而且是一款開源軟體,而且這個軟體支援相當多的系統,比如Linux, Unix, Windows, 當你在Linux上安裝了這個軟體並且配置了這個軟甲的環境變數,你就可以在shell上使用相關的命令來直接操作這個軟體來實現我們想要的功能, 同時我們在安裝完freetds軟體的時候, freetds軟體的發行商也提供給我們了相關的函式庫和標頭檔案,使得我們在自己開發的程式中也可以呼叫freetds的相關介面來實現我們想要的功能.

2.為什麼我們要使用freetds, freetds的功能是什麼?

    我們都知道,向我們在Linux上使用的資料庫一般都為MySQL, MySQL是一款開源資料庫,當你在Linux上安裝MySQL的時候, MySQL會提供給你連線它的方式, 但是當我們連接出了MySQL以外的一些比較特殊的資料庫是, 比如Windows上的不開源的SQLServer時怎麼辦? 微軟好像也沒有針對Linux開放出API, 因為這個軟體就是針對於Windows設計的, 這個時候我們就可以使用三方軟體freetds來完成對SQLServer的連線和操作, 而且freetds不僅支援SQLServer而且還支援Sybase databases(塞班資料庫).


3.freetds的相關函式介紹

一下相關函式介面用於freetds v0.91

**注意:我們在要使用freetds進行開發時候一定要引用freetds的相關標頭檔案sybfront.h和sybdb.h, 同時我們在編寫Makefile的使用也要連線freetds的相關函式庫-lsybdb, 否則標頭檔案是找不到函式的原型的

**注意:SQLServer的預設編碼可能是GBK, 而我們在Linux下程式設計使用的預設編碼集一般為UTF-8, 當我們在Linux程式中使用SQL語句操作SQLServer時候特別是我們的SQL語句中有中文的時候, SQL語句從UTF-8轉變為GBK,會產生亂碼, 使得你永遠都無法將SQL語句執行成功, 而且程式也不會給出明顯的錯誤提示

**注意
:我這邊再介紹幾個變數:
    <1>RETCODE:我們在標頭檔案sybdb.h標頭檔案中發現了他的先關定義, 其實RETCODE就是int, 原始程式碼是:typedef int RETCODE
    <2>SUCCEED:這個值也是int, 他的定義也位於sybdb.h上, 原始程式碼為:#define SUCCEED 1
    <3>FAIL:這個值也是int, 他的定義也位於sybdb.h上, 原始程式碼為:#define FAIL 0

(1)dbinit()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    RETCODE dbinit(void);

返回值:RETCODE:<1>成功時返回SUCCEED <2>失敗時返回FAIL
引數:
函式作用:在你呼叫freetds的其他的函式的時候一定要先呼叫這個函式, 這個函式的作用就是進行一些初始化工作, 好比如為結構體分配空間, 還有讀取你Linux上的一些配置檔案, 來確定日期格式和其他資訊

(2)dblogin()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    LOGINREC* dblogin(void)

返回值:<1>這個函式失敗時返回NULL
              <2>成功時返回一個LOGINREC指標, 這是一個結構體, 這個結構體中包含了連線資料庫的相關引數
  
       LOGINREC結構體中的內容:
      char* client_charset  客戶端字元編碼集
      char* client_hostname 連線資料庫的IP
      int connect_timeout   連線資料庫的超時時間
      char* password        連線資料庫時使用的密碼
      int query_timeout     傳送請求命令時的超時時間
      char* username        連線資料庫的使用者名稱稱
引數:
函式作用:建立一個LOGINRES指標,並且返回它

(3)dbsetlname()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    RETCODE dbsetlname(LOGINREC* login, const char* value, int which)

返回值:<1>成功時返回SUCCEED <2>失敗時返回FAIL
引數:<1>LOGINREC*:一個LOGINREC指標
         <2>value:我們要設定的選項的值
         <3>which:我們要設定的選項, 好比如: DBSETUSER(int型別)....
函式作用:設定LOGINREC中的相關的選項的值

(4)DBSETUSER()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    DBSETUSER(LOGINREC* login, char* UserName)

返回值:RETCODE:<1>函式執行成功時返回SUCCEED <2>函式執行失敗時返回FAIL
引數:<1>LOGINREC*:一個LOGINREC指標
         <2>UserName:登入資料庫的使用者的名稱
函式作用:向LOGINREC結構體中設定登入使用者的名稱
函式介紹:其實這個函式就是巨集定義函式, 在標頭檔案sybdb.h是這麼定義的:#define DBSETLUSER(x,y) dbsetlname((x), (y), DBSETUSER)

(5)DBSETLPWD()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    DBSETLPWD(LOGINREC* login, char* PassWord)


返回值:RETCODE:<1>函式執行成功時返回SUCCEED <2>函式執行失敗時返回FAIL
引數:<1>LOGINREC*:一個LOGINREC指標
          <2>PassWord:登入資料庫的使用者的密碼
函式作用:向LOGINREC結構體中設定登入使用者的密碼
函式介紹:其實這個函式就是巨集定義函式, 在標頭檔案sybdb.h是這麼定義的:#define DBSETLPWD(x,y) dbsetlname((x), (y), DBSETPWD)


(6)dbopen()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    DBPROCESS* dbopen(LOGINREC* login, const char* server)

返回值:<1>成功時返回DBPROCESS*, 一個成功連線到資料庫的控制代碼
              <2>失敗時返回NULL
引數:<1>LOGINREC*:一個LOGINREC指標, 指標中一定要儲存了連線使使用者的使用者名稱稱, 以及使用者的
         <2>server:要連線資料庫的IP地址
函式作用:連線到資料庫, 並且返回成功連線的控制代碼


(7)dbuse()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>


    RETCODE dbuse(DBPROCESS* dbproc, const char* name)


返回值:<1>成功時返回SUCCEED <2>失敗時返回FAIL
引數 :<1>dbproc:已經連線到資料庫的連線控制代碼
          <2>name:要使用的資料庫的名字
函式作用:使用SQLServer中的具體的某個資料庫, 相當於在資料庫中執行use XXXXdatabase命令, 這個函式一定要在dbopen()之後執行


(8)dbcmd()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    RETCODE dbcmd(DBPROCESS* dbproc, const char cmdstrmg[])

返回值:<1>執行成功時返回SUCCEED <2>執行失敗時返回FAIL
引數:<1>dbproc:已經連線到某個資料庫的控制代碼,其實就是執行完dbuse()之後的控制代碼
          <2>cmdstrmg:要執行的sql命令
函式作用:這個函式最好在執行完dbuse之後執行,這個函式的作用其實就是將cmdstrmg這個SQL命令儲存到dbproc指標指向的命令快取中,等待執行


(9)dbsqlexec()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    RETCODE dbsqlexec(DBPROCESS* dbproc)

返回值:<1>成功時返回SUCCEED <2>失敗時返回FAIL
引數:<1>儲存了SQL命令的資料庫連線控制代碼, 其實就是執行了dbcmd()函式之後的SQL連線控制代碼
函式作用:將連線控制代碼中快取中儲存的命令送到資料庫中執行, 並且等待執行的結果, 再將結果返回


(10)dbresults()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    RETCODE dbresults(DBPROCESS* dbproc)

返回值:<1>函式執行成功時返回SUCCEED <2>函式執行失敗時返回FAIL
引數:dbproc:運行了dbsqlexec()函式之後的資料庫連線控制代碼
函式作用:這個函式的作用就是用來判斷函式dbsqlexec()執行的命令是否執行成功


(11)dbind()
函式原型:
    #include <sybfront.h>
    #include <stbdb.h>

    RETCODE dbind(DBPROCESS* dbproc, int column, int vartype, DBINT valen, BYTE* varaddr)

返回值:<1>函式執行成功時返回SUCCEED <2>函式執行失敗時返回FAIL
引數:<1>dbproc:儲存了函式執行結果的資料庫連線控制代碼
         <2>column:你在資料庫中查詢到的資料的列數, 順序以及sql語句為準, 起始資料為1
         <3>vartype:資料的型別, 既是要接受從資料庫取出來的本級資料的型別
         <4>varlen:儲存取出資料的本機資料的大小
         <5>varaddr:儲存取出資料的本機資料的地址指標

函式作用:dbsqlexec()函式執行之後, 返回的結果不是單個數據, 而是多個數據的資料結果集合, 這個結果集合為行和列組成, 行就是一行資料,而列就是欄位名稱, 我們使用這個函式可以將結果集的column列的欄位繫結到varaddr指向的本地的資料


(12)dbnextrow()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    RETCODE dbnextrow(DBPROCESS* dbproc)

返回值:<1>NO_MORE_ROWS:結果集中沒有更多的資料
引數:<1>dbproc:儲存了查詢結果的資料庫連線控制代碼
函式作用:這個函式最好在dbind()函式呼叫之後呼叫, 我們在之前使用的dbind()函式, 將具體的欄位和本機值繫結到了一起, 而dbnextrow()的作用就是查詢結果集合中的下一行資料, 每當我們使用dbnextrow()函式的時候, 本地值中儲存的繫結的指定的欄位的值都會變為當前結果集那一行的對應欄位的值

(13)dbclose()
函式原型:
    #include <sybfront.h>
    #include <sybdb.h>

    void dbclose(DBPROCESS* dbproc)

返回值:
引數:dbproc:一個連線好資料庫的連線控制代碼
作用:關閉和資料庫的連線, 並且釋放這個連線控制代碼的資源

相關程式碼:

//其他的標頭檔案不給於列出
#include <sybfront.h>
#include <sybdb.h>

//建立到MSSQL資料庫的連線------------------------
DBINT result_code;                //定義儲存資料庫交易結果的型別
dbinit();                         //使用dbinit()函式, 進行freetds操作之前的初始化操作
LOGINREC *loginrec = dblogin();	  //建立一個到資料庫的連線的控制代碼
DBSETLUSER(loginrec, Q_SQLUser);  //向控制代碼中新增連線資料庫的使用者
DBSETLPWD(loginrec, Q_SQLPassword);                     //向資料庫連線控制代碼中新增密碼
DBPROCESS *dbprocess = dbopen(loginrec, Q_SQLServer);	//連線資料庫,並返回資料庫連線結果的控制代碼
    
if(dbprocess == FAIL) 									//如果連線失敗
{ 
    fprintf(stderr, "Connect Fail\n");                  //在標準錯誤中輸出資訊
    exit(EXIT_FAILURE);                                 //程序異常退出
}
else                                                    //如果連線成功
{
    printf("Connect success\n");
}
     
if(dbuse(dbprocess, Q_SQLName) == FAIL)                 //使用某個資料庫,如果使用失敗
{
    dbclose(dbprocess);                                 //關閉資料庫連線控制代碼, 並且回收相關資源
    exit(EXIT_FAILURE);                                 //程序異常退出
}
	
//開始進行資料庫中資料查詢的工作------------------
char mssqlbuf[1024];                                    //定義儲存資料庫查詢語句的字串
memset(mssqlbuf, 0x00, sizeof(mssqlbuf));               //開始初始化字串
sprintf(mssqlbuf, "SELECT name, age FROM testTable");   //組裝操作sql的語句, 將sql語句儲存到mssqlbuf
dbcmd(dbprocess, mssqlbuf);                             //將剛剛組裝好的sql命令, 使用dbcmd命令儲存到資料庫連線控制代碼的快取中
						
if(dbsqlexec(dbprocess) == FAIL)                        //如果執行的命令失敗
{ 
    dbclose(dbprocess);                                 //關閉資料庫操作程序
    exit(EXIT_FAILURE);                                 //程式異常退出
}

char name[100];                                         //定義兩個變數來儲存綁定出來的資料
char age[10];
memset(name, 0x00, sizeof(name));                       //對陣列進行初始化
memset(age, 0x00, sizeof(age));

//開始對資料取出的進行操作-------------------------
if((result_code = dbresults(dbprocess)) != NO_MORE_RESULTS && result_code == SUCCEED)  //如果sql命令執行成功
{
    //開始繫結資料
    dbbind(dbprocess, 1, CHARBIND, (DBCHAR)0, (BYTE*)name);    //將資料庫中查詢到的name(sql命令中我們查詢的時候name位於結果的第一個), 繫結給本地的name
	dbbind(dbprocess, 2, CHARBIND, (DBCHAR)0, (BYTE*)age);     //將資料庫中查詢到的age(sql命令中我們查詢的時候age位於結果的第二個), 繫結給本地的age
    
    while(dbnextrow(dbprocess) != NO_MORE_ROWS)                //開始遍歷結果集合, 並且沒執行一次判斷一次是否還有後續資料
    {
        //這裡新增你想要的對取出資料的操作
        printf("name is %s, age is %s", name, age);            //使用printf輸出我們取出的name(本機變數), age(本機變數)
    }			
}
	
dbclose(dbprocess);                                            //關閉資料庫連線