1. 程式人生 > >Mysql資料庫的操作(C程式設計)

Mysql資料庫的操作(C程式設計)

Mysql資料庫是一種開源的關係型資料庫系統(RDBMS),使用常用的資料庫管理語言-結構性查詢語言(SQL)進行資料庫管理.
Mysql資料庫因為其速度 可靠性和適應性而備受關注.大多數人都認為再不需要事物話的處理情況下,Mysql是管理內容最好的選擇. 當然在嵌入式系統中,Mysql資料庫也得到了廣泛應用.
以下我們將通過具體的C語言程式碼,詳細說明Mysql資料庫的操作:
一, API解析

1. MYSQL *mysql_init(MYSQL *mysql)
描述
分配或初始化與mysql_real_connect()相適應的MYSQL物件。如果mysql是NULL
指標,該函式將分配、初始化、並返回新物件。否則,將初始化物件,並返回物件的地址。如果mysql_init()分配了新的物件,當呼叫mysql_close()來關閉連線時。將釋放該物件。 返回值 初始化的MYSQL*控制代碼。如果無足夠記憶體以分配新的物件,返回NULL。 錯誤 在記憶體不足的情況下,返回NULL2. mysql_real_connect() MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned
int port, const char *unix_socket, unsigned long client_flag) 描述 mysql_real_connect()嘗試與執行在主機上的MySQL資料庫引擎建立連線。在你能夠執行需要有效MySQL連線控制代碼結構的任何其他API函式之前,mysql_real_connect()必須成功完成。 引數的指定方式如下: · 第1個引數應是已有MYSQL結構的地址。呼叫mysql_real_connect()之前,必須呼叫mysql_init()來初始化MYSQL結構。通過mysql_options()呼叫,可更改多種連線選項。請參見25.2
.3.48節,“mysql_options()”。 · “host”的值必須是主機名或IP地址。如果“host”是NULL或字串"localhost",連線將被視為與本地主機的連線。如果作業系統支援套接字(Unix)或命名管道(Windows),將使用它們而不是TCP/IP連線到伺服器。 · “user”引數包含使用者的MySQL登入ID。如果“user”是NULL或空字串"",使用者將被視為當前使用者。在UNIX環境下,它是當前的登入名。在Windows ODBC下,必須明確指定當前使用者名稱。請參見26.1.9.2節,“在Windows上配置MyODBC DSN”。 · “passwd”引數包含使用者的密碼。如果“passwd”是NULL,僅會對該使用者的(擁有1個空密碼欄位的)使用者表中的條目進行匹配檢查。這樣,資料庫管理員就能按特定的方式設定MySQL許可權系統,根據使用者是否擁有指定的密碼,使用者將獲得不同的許可權。 註釋:呼叫mysql_real_connect()之前,不要嘗試加密密碼,密碼加密將由客戶端API自動處理。 · “db”是資料庫名稱。如果db為NULL,連線會將預設的資料庫設為該值。 · 如果“port”不是0,其值將用作TCP/IP連線的埠號。注意,“host”引數決定了連線的型別。 · 如果unix_socket不是NULL,該字串描述了應使用的套接字或命名管道。注意,“host”引數決定了連線的型別。 · client_flag的值通常為0,但是,也能將其設定為下述標誌的組合,以允許特定功能: 標誌名稱標誌描述CLIENT_COMPRESS使用壓縮協議。CLIENT_FOUND_ROWS返回發現的行數(匹配的),而不是受影響的行數。CLIENT_IGNORE_SPACE允許在函式名後使用空格。使所有的函式名成為保留字。CLIENT_INTERACTIVE關閉連線之前,允許interactive_timeout(取代了wait_timeout)秒的不活動時間。客戶端的會話wait_timeout變數被設為會話interactive_timeout變數的值。CLIENT_LOCAL_FILES允許LOAD DATA LOCAL處理功能。CLIENT_MULTI_STATEMENTS通知伺服器,客戶端可能在單個字串內傳送多條語句(由‘;’隔開)。如果未設定該標誌,將禁止多語句執行。CLIENT_MULTI_RESULTS通知伺服器,客戶端能夠處理來自多語句執行或儲存程式的多個結果集。如果設定了CLIENT_MULTI_STATEMENTS,將自動設定它。CLIENT_NO_SCHEMA禁止db_name.tbl_name.col_name語法。它用於ODBC。如果使用了該語法,它會使分析程式生成錯誤,在捕獲某些ODBC程式中的缺陷時,它很有用。CLIENT_ODBC客戶端是ODBC客戶端。它將mysqld變得更為ODBC友好。CLIENT_SSL使用SSL(加密協議)。該選項不應由應用程式設定,它是在客戶端庫內部設定的。 對於某些引數,能夠從選項檔案獲得取值,而不是取得mysql_real_connect()呼叫中的確切值。為此,在呼叫mysql_real_connect()之前,應與MYSQL_READ_DEFAULT_FILE或MYSQL_READ_DEFAULT_GROUP選項一起呼叫mysql_options()。隨後,在mysql_real_connect()呼叫中,為準備從選項檔案讀取值的每個引數指定“無值”值: · 對於host,指定NULL值或空字串("")。 · 對於user,指定NULL值或空字串。 · 對於passwd,指定NULL值。(對於密碼,mysql_real_connect()呼叫中的空字串的值不能被選項檔案中的字串覆蓋,這是因為,空字串明確指明MySQL賬戶必須有空密碼)。 · 對於db,指定NULL值或空字串 · 對於port,指定“0”值。 · 對於unix_socket,指定NULL值。 對於某一引數,如果在選項檔案中未發現值,將使用它的預設值,如本節前面介紹的那樣。 返回值 如果連線成功,返回MYSQL*連線控制代碼。如果連線失敗,返回NULL。對於成功的連線,返回值與第1個引數的值相同。 錯誤 · CR_CONN_HOST_ERROR 無法連線到MySQL伺服器。 · CR_CONNECTION_ERROR 無法連線到本地MySQL伺服器。 · CR_IPSOCK_ERROR 無法建立IP套接字。 · CR_OUT_OF_MEMORY 記憶體溢位。 · CR_SOCKET_CREATE_ERROR 無法建立Unix套接字。 · CR_UNKNOWN_HOST 無法找到主機名的IP地址。 · CR_VERSION_ERROR 協議不匹配,起因於:試圖連線到具有特定客戶端庫(該客戶端庫使用了不同的協議版本)的伺服器。如果使用很早的客戶端庫來建立與較新的伺服器(未使用“--old-protocol”選項開始的)的連線,就會出現該情況。 · CR_NAMEDPIPEOPEN_ERROR 無法在Windows平臺下建立命名管道。 · CR_NAMEDPIPEWAIT_ERROR 在Windows平臺下等待命名管道失敗。 · CR_NAMEDPIPESETSTATE_ERROR 在Windows平臺下獲取管道處理程式失敗。 · CR_SERVER_LOST 如果connect_timeout > 0,而且在連線伺服器時所用時間長於connect_timeout秒,或在執行init-command時伺服器消失。 3. mysql_options() int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg) 描述 可用於設定額外的連線選項,並影響連線的行為。可多次呼叫該函式來設定數個選項。 應在mysql_init()之後、以及mysql_connect()或mysql_real_connect()之前呼叫mysql_options()。 選項參量指的是你打算設定的選項。Arg參量是選項的值。如果選項是整數,那麼arg應指向整數的值。 可能的選項值: 選項參量型別功能MYSQL_INIT_COMMANDchar *連線到MySQL伺服器時將執行的命令。再次連線時將自動地再次執行。MYSQL_OPT_COMPRESS未使用使用壓縮客戶端/伺服器協議MYSQL_OPT_CONNECT_TIMEOUTunsigned int *以秒為單位的連線超時。MYSQL_OPT_GUESS_CONNECTION未使用對於與libmysqld連結的應用程式,允許庫“猜測”是否使用嵌入式伺服器或遠端伺服器。“猜測”表示,如果設定了主機名但不是本地主機,將使用遠端伺服器。該行為是預設行為。 可使用MYSQL_OPT_USE_EMBEDDED_CONNECTION 和MYSQL_OPT_USE_REMOTE_CONNECTION覆蓋它。對於與libmysqlclient連結的應用程式,該選項將被忽略。MYSQL_OPT_LOCAL_INFILE指向單元的可選指標如果未給定指標,或指標指向“unsigned int != 0”,將允許命令LOAD LOCAL INFILE。MYSQL_OPT_NAMED_PIPE未使用使用命名管道連線到NT平臺上的MySQL伺服器。MYSQL_OPT_PROTOCOLunsigned int *要使用的協議型別。應是mysql.h中定義的mysql_protocol_type的列舉值之一。MYSQL_OPT_READ_TIMEOUTunsigned int *從伺服器讀取資訊的超時(目前僅在Windows平臺的TCP/IP連線上有效)。MYSQL_OPT_RECONNECTmy_bool *如果發現連線丟失,啟動或禁止與伺服器的自動再連線。從MySQL 5.0.3開始,預設情況下禁止再連線,這是5.0.13中的新選項,提供了一種以顯式方式設定再連線行為的方法。MYSQL_OPT_SET_CLIENT_IPchar *對於與libmysqld連結的應用程式(具備鑑定支援特性的已編譯libmysqld),它意味著,出於鑑定目的,使用者將被視為從指定的IP地址(指定為字串)進行連線。對於與libmysqlclient連結的應用程式,,該選項將被忽略。MYSQL_OPT_USE_EMBEDDED_CONNECTION未使用對於與libmysqld連結的應用程式,對於連線來說,它將強制使用嵌入式伺服器。對於與libmysqlclient連結的應用程式,,該選項將被忽略。MYSQL_OPT_USE_REMOTE_CONNECTION未使用對於與libmysqld連結的應用程式,對於連線來說,它將強制使用遠端伺服器。對於與libmysqlclient連結的應用程式,,該選項將被忽略。MYSQL_OPT_USE_RESULT未使用不使用該選項。MYSQL_OPT_WRITE_TIMEOUTunsigned int *寫入伺服器的超時(目前僅在Windows平臺的TCP/IP連線上有效)。MYSQL_READ_DEFAULT_FILEchar *從命名選項檔案而不是從my.cnf讀取選項。MYSQL_READ_DEFAULT_GROUPchar *從my.cnf或用MYSQL_READ_DEFAULT_FILE指定的檔案中的命名組讀取選項。MYSQL_REPORT_DATA_TRUNCATIONmy_bool *通過MYSQL_BIND.error,對於預處理語句,允許或禁止通報資料截斷錯誤(預設為禁止)。MYSQL_SECURE_AUTHmy_bool*是否連線到不支援密碼混編功能的伺服器,在MySQL 4.1.1和更高版本中,使用了密碼混編功能。MYSQL_SET_CHARSET_DIRchar*指向包含字符集定義檔案的目錄的路徑名。MYSQL_SET_CHARSET_NAMEchar*用作預設字符集的字符集的名稱。MYSQL_SHARED_MEMORY_BASE_NAMEchar*命名為與伺服器進行通訊的共享記憶體物件。應與你打算連線的mysqld伺服器使用的選項“-shared-memory-base-name”相同。 注意,如果使用了MYSQL_READ_DEFAULT_FILE或MYSQL_READ_DEFAULT_GROUP,總會讀取客戶端組。 選項檔案中指定的組可能包含下述選項: 選項描述connect-timeout以秒為單位的連線超時。在Linux平臺上,該超時也用作等待伺服器首次迴應的時間。compress使用壓縮客戶端/伺服器協議。database如果在連線命令中未指定資料庫,連線到該資料庫。debug除錯選項。disable-local-infile禁止使用LOAD DATA LOCAL。host預設主機名。init-command連線到MySQL伺服器時將執行的命令。再次連線時將自動地再次執行。interactive-timeout等同於將CLIENT_INTERACTIVE指定為mysql_real_connect()。請參見25.2.3.51節,“mysql_real_connect()”。local-infile[=(0|1)]如果無參量或參量!= 0,那麼將允許使用LOAD DATA LOCAL。max_allowed_packet客戶端能夠從伺服器讀取的最大資訊包。multi-results允許多語句執行或儲存程式的多個結果集。multi-statements允許客戶端在1個字串內傳送多條語句。(由“;”隔開)。password預設密碼。pipe使用命名管道連線到NT平臺上的MySQL伺服器。protocol={TCP | SOCKET | PIPE | MEMORY}連線到伺服器時將使用的協議。port預設埠號。return-found-rows通知mysql_info()返回發現的行,而不是使用UPDATE時更新的行。shared-memory-base-name=name共享記憶體名稱,用於連線到伺服器(預設為"MYSQL")。socket預設的套接字檔案。user預設使用者。 注意,“timeout”(超時)已被“connect-timeout”(連線超時)取代,但為了保持向後相容,在MySQL 5.1.2-alpha中仍支援“timeout”(超時)。 關於選項檔案的更多資訊,請參見4.3.2節,“使用選項檔案”。 返回值 成功時返回0。如果使用了未知選項,返回非0值。 5. mysql_errno() unsigned int mysql_errno(MYSQL *mysql) 描述 對於由mysql指定的連線,mysql_errno()返回最近呼叫的API函式的錯誤程式碼,該函式呼叫可能成功也可能失敗。“0”返回值表示未出現錯誤。在MySQL errmsg.h標頭檔案中,列出了客戶端錯誤訊息編號。在附錄B:錯誤程式碼和訊息中,也列出了這些錯誤。 注意,如果成功,某些函式,如mysql_fetch_row()等,不會設定mysql_errno()。 經驗規則是,如果成功,所有向伺服器請求資訊的函式均會復位mysql_errno()。 返回值 如果失敗,返回上次mysql_xxx()呼叫的錯誤程式碼。“0”表示未出現錯誤。 錯誤 無。 6. mysql_error() const char *mysql_error(MYSQL *mysql) 描述 對於由mysql指定的連線,對於失敗的最近呼叫的API函式,mysql_error()返回包含錯誤訊息的、由Null終結的字串。如果該函式未失敗,mysql_error()的返回值可能是以前的錯誤,或指明無錯誤的空字串。 經驗規則是,如果成功,所有向伺服器請求資訊的函式均會復位mysql_error()。 對於復位mysql_errno()的函式,下述兩個測試是等效的: if(mysql_errno(&mysql)) { // an error occurred } if(mysql_error(&mysql)[0] != '\0') { // an error occurred } 通過重新編譯MySQL客戶端庫,可以更改客戶端錯誤訊息的語言。目前,能夠選擇數種語言顯示錯誤訊息,請參見5.10.2節,“設定錯誤訊息語言”。 返回值 返回描述錯誤的、由Null終結的字串。如果未出現錯誤,返回空字串。 錯誤 無。 7.mysql_ping() int mysql_ping(MYSQL *mysql) 描述 檢查與伺服器的連線是否工作。如果連線丟失,將自動嘗試再連線。 該函式可被閒置了較長時間的客戶端使用,用以檢查伺服器是否已關閉了連線,並在必要時再次連線。 返回值 如果與伺服器的連線有效返回0。如果出現錯誤,返回非0值。返回的非0值不表示MySQL伺服器本身是否已關閉,連線可能因其他原因終端,如網路問題等。 錯誤 · CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 · CR_SERVER_GONE_ERROR MySQL伺服器不可用。 · CR_UNKNOWN_ERROR 出現未知錯誤。 8. mysql_query() int mysql_query(MYSQL *mysql, const char *query) 描述 執行由“Null終結的字串”查詢指向的SQL查詢。正常情況下,字串必須包含1條SQL語句,而且不應為語句新增終結分號(‘;’)或“\g”。如果允許多語句執行,字串可包含多條由分號隔開的語句。請參見25.2.9節,“多查詢執行的C API處理”。 mysql_query()不能用於包含二進位制資料的查詢,應使用mysql_real_query()取而代之(二進位制資料可能包含字元‘\0’,mysql_query()會將該字元解釋為查詢字串結束)。 如果希望瞭解查詢是否應返回結果集,可使用mysql_field_count()進行檢查。請參見25.2.3.22節,“mysql_field_count()”。 返回值 如果查詢成功,返回0。如果出現錯誤,返回非0值。 錯誤 · CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 · CR_SERVER_GONE_ERROR MySQL伺服器不可用。 · CR_SERVER_LOST 在查詢過程中,與伺服器的連線丟失。 · CR_UNKNOWN_ERROR 出現未知錯誤。 9.mysql_use_result() MYSQL_RES *mysql_use_result(MYSQL *mysql) 描述 對於成功檢索資料的每個查詢(SELECT、SHOW、DESCRIBE、EXPLAIN),必須呼叫mysql_store_result()或mysql_use_result()。 mysql_use_result()將初始化結果集檢索,但並不像mysql_store_result()那樣將結果集實際讀取到客戶端。它必須通過對mysql_fetch_row()的呼叫,對每一行分別進行檢索。這將直接從伺服器讀取結果,而不會將其儲存在臨時表或本地緩衝區內,與mysql_store_result()相比,速度更快而且使用的記憶體也更少。客戶端僅為當前行和通訊緩衝區分配記憶體,分配的記憶體可增加到max_allowed_packet位元組。 另一方面,如果你正在客戶端一側為各行進行大量的處理操作,或者將輸出傳送到了使用者可能會鍵入“^S”(停止滾動)的螢幕,就不應使用mysql_use_result()。這會繫結伺服器,並阻止其他執行緒更新任何表(資料從這類表獲得)。 使用mysql_use_result()時,必須執行mysql_fetch_row(),直至返回NULL值,否則,未獲取的行將作為下一個檢索的一部分返回。C API給出命令不同步錯誤,如果忘記了執行該操作,將不能執行該命令。 不應與從mysql_use_result()返回的結果一起使用mysql_data_seek()、mysql_row_seek()、mysql_row_tell()、mysql_num_rows()或mysql_affected_rows(),也不應發出其他查詢,直至mysql_use_result()完成為止。(但是,提取了所有行後,mysql_num_rows()將準確返回提取的行數)。 一旦完成了對結果集的操作,必須呼叫mysql_free_result()。 使用libmysqld嵌入式伺服器時,由於在呼叫mysql_free_result()之前,記憶體使用將隨著每個檢索的行增加,記憶體效益將基本喪失。 返回值 MYSQL_RES結果結構。如果出現錯誤,返回NULL。 錯誤 如果成功,mysql_use_result()將復位mysql_error()和mysql_errno()。 · CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 · CR_OUT_OF_MEMORY 記憶體溢位。 · CR_SERVER_GONE_ERROR MySQL伺服器不可用。 · CR_SERVER_LOST 在查詢過程中,與伺服器的連線丟失。 · CR_UNKNOWN_ERROR 出現未知錯誤。 10. mysql_fetch_row() MYSQL_ROW mysql_fetch_row(MYSQL_RES *result) 描述 檢索結果集的下一行。在mysql_store_result()之後使用時,如果沒有要檢索的行,mysql_fetch_row()返回NULL。在mysql_use_result()之後使用時,如果沒有要檢索的行或出現了錯誤,mysql_fetch_row()返回NULL。 行內值的數目由mysql_num_fields(result)給出。如果行中儲存了呼叫mysql_fetch_row()返回的值,將按照row[0]到row[mysql_num_fields(result)-1],訪問這些值的指標。行中的NULL值由NULL指標指明。 可以通過呼叫mysql_fetch_lengths()來獲得行中欄位值的長度。對於空欄位以及包含NULL的欄位,長度為0。通過檢查欄位值的指標,能夠區分它們。如果指標為NULL,欄位為NULL,否則欄位為空。 返回值 下一行的MYSQL_ROW結構。如果沒有更多要檢索的行或出現了錯誤,返回NULL。 錯誤 注意,在對mysql_fetch_row()的兩次呼叫之間,不會復位錯誤。 · CR_SERVER_LOST 在查詢過程中,與伺服器的連線丟失。 · CR_UNKNOWN_ERROR 出現未知錯誤。

二, Mysql資料庫C程式設計案例 (對學生表進行資料庫管理)

#include <stdio.h>
#include <stdlib.h>
#include <mysql/mysql.h>
#include <mysql/mysqld_error.h>
#include <unistd.h>

int main(int argc,char ** argv)
{
    MYSQL mysql;//可以說是mysql資料庫的控制代碼
    char sql[128]={0};//儲存sql語句
    int ret;//接收返回值
    MYSQL_RES *res;
    MYSQL_ROW row;


    /****** 初始化資料庫 ******/
    mysql_init(&mysql);//實際上是初始化MYSQL結構

    /****** 連線資料庫 ******/
    if(!mysql_real_connect(&mysql,"localhost","root","1","mysql",0,NULL,0)){
    /*
        note:localhost->本地連結
             root->資料庫使用者名稱
             1->密碼
             mysql->資料庫名
    */
        printf("%d ERROR: fail to mysql_real_connect->%d:%s\n",__LINE__,mysql_errno(&mysql),mysql_error(&mysql));
        return -1;
    }
    puts("connect OK!");

#if 1  //測試"show tables"命令使用
     if (mysql_query(&mysql, "show tables")) 
    {
            fprintf(stderr, "%s\n", mysql_error(&mysql));
            exit(1);
    }
    printf("MySQL Tables in mysql database:\n");

    res = mysql_use_result(&mysql);

    puts("-------------------------------------------------->");
    while ((row = mysql_fetch_row(res)) != NULL)
    {
        printf("%s \n", row[0]);
    }
    puts("<--------------------------------------------------");
#endif

    /****** 建立資料庫 *******/
    ret=mysql_query(&mysql,"create table if not exists stu(id int not null primary key,name varchar(20) not null,score float not null)");
/*
    Note:建立一個stu表(不存在才建立)
         欄位為:int型別的id欄位(為鍵)
               varchar型別的name
               float 型別的score 且三個欄位都不能為空
*/
    printf("line=%d    ret=%d\n",__LINE__,ret);
    if(ret != 0){
        printf("%d ERROR: fail to crate table->%d:%s\n",__LINE__,mysql_errno(&mysql),mysql_error(&mysql));
        return -1;
    }
    puts("crate table ok!");

    /****** 插入資料 ******/
    //插入一條資料
    ret=mysql_query(&mysql,"insert into stu (id,name,score) values(5,'lihua',56)");
    printf("line=%d    ret=%d\n",__LINE__,ret);
    if(ret != 0){//插入資料
            printf("%d ERROR: fail to insert->%d:%s\n",__LINE__,mysql_errno(&mysql),mysql_error(&mysql));
            if(mysql_errno(&mysql) == 1062){//欄位不唯一
                puts("not Unique!");
            }
            else{
                return -1;
            }
    }
    puts("insert table ok!");   

    //插入一條資料
    ret=mysql_query(&mysql,"insert into stu (id,name,score) values(6,'haha',89)");
    printf("line=%d    ret=%d\n",__LINE__,ret);
    if(ret != 0){//插入資料
            printf("%d ERROR: fail to insert->%d:%s\n",__LINE__,mysql_errno(&mysql),mysql_error(&mysql));
            if(mysql_errno(&mysql) == 1062){//欄位不唯一
                puts("not Unique!");
            }
            else{
                return -1;
            }
    }
    puts("insert table ok!");   

    //插入一條資料
    ret=mysql_query(&mysql,"insert into stu (id,name,score) values(7,'zhangsan',66)");
    printf("line=%d    ret=%d\n",__LINE__,ret);
    if(ret != 0){//插入資料
            printf("%d ERROR: fail to insert->%d:%s\n",__LINE__,mysql_errno(&mysql),mysql_error(&mysql));
            if(mysql_errno(&mysql) == 1062){//欄位不唯一
                puts("not Unique!");
            }
            else{
                return -1;
            }
    }
    puts("insert table ok!");

    //插入一條資料
    ret=mysql_query(&mysql,"insert into stu (id,name,score) values(8,'huli',20)");
    printf("line=%d    ret=%d\n",__LINE__,ret);
    if(ret != 0){//插入資料
            printf("%d ERROR: fail to insert->%d:%s\n",__LINE__,mysql_errno(&mysql),mysql_error(&mysql));
            if(mysql_errno(&mysql) == 1062){//欄位不唯一
                puts("not Unique!");
            }
            else{
                return -1;
            }
    }
    puts("insert table ok!");
//當然可以多條同時插入
#if 0
    ret=mysql_query(&mysql,"insert into stu (id,name,score) values(5,'lihua',56),(6,'haha',89),(7,'zhangsan',66),(8,'huli',20)");
    printf("line=%d    ret=%d\n",__LINE__,ret);
    if(ret != 0){//插入資料
            printf("%d ERROR: fail to insert->%d:%s\n",__LINE__,mysql_errno(&mysql),mysql_error(&mysql));
            if(mysql_errno(&mysql) == 1062){//欄位不唯一
                puts("not Unique!");
            }
            else{
                return -1;
            }
    }
    puts("insert table ok!");   
#endif


    /****** 修改資料 ******/
    /*float score;
    int id;
    puts("input id>>>");
    scanf("%d",&id);
    puts("input score>>>");
    scanf("%f",&score);
    sprintf(sql,"update stu set score=%f where id=%d",score,id);
    ret=mysql_query(&mysql,sql);
    printf("line=%d    ret=%d\n",__LINE__,ret);
    if(ret != 0){//插入資料
    printf("%d ERROR: fail to insert->%d:%s\n",__LINE__,mysql_errno(&mysql),mysql_error(&mysql));
    if(mysql_errno(&mysql) == 1062){//欄位不唯一
        puts("not Unique!");
    }
    else{
        return -1;
    }
    }
    puts("delete table ok!");*/

    /****** 刪除資料 ******/
    /*sleep(5);
    ret=mysql_query(&mysql,"delete from stu where id=5");
    printf("line=%d    ret=%d\n",__LINE__,ret);
    if(ret != 0){//插入資料
            printf("%d ERROR: fail to insert->%d:%s\n",__LINE__,mysql_errno(&mysql),mysql_error(&mysql));
            if(mysql_errno(&mysql) == 1062){//欄位不唯一
                puts("not Unique!");
            }
            else{
                return -1;
            }
    }
    puts("delete table ok!");*/


    /****** 查詢資料 ******/
    //ret=mysql_query(&mysql,"select * from stu");
    //printf("line=%d    ret=%d\n",__LINE__,ret);
    if(mysql_query(&mysql,"select * from stu")){//查詢表
        printf("%d ERROR: fail to select->%d:%s\n",__LINE__,mysql_errno(&mysql),mysql_error(&mysql));
        return -1;
    }

    res = mysql_use_result(&mysql);
    puts("-------------------------------------------------->");
    while ((row = mysql_fetch_row(res)) != NULL)
    {
        printf("%-10s  %-10s  %-10s\n", row[0],row[1],row[2]);
    }
    puts("<--------------------------------------------------");


    /****** 釋放結果指標 ******/
    mysql_free_result(res);
    /****** 關閉資料庫 ******/
    mysql_close(&mysql);


    return 0;
}