<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### 第25章:API和庫 ** 目錄** [25.1. libmysqld,嵌入式MySQL服務器庫](#)[25.1.1. 嵌入式MySQL服務器庫概述](#)[ 25.1.2. 使用libmysqld編譯程序``](#)[ 25.1.3. 使用嵌入式MySQL服務器時的限制](#)[25.1.4. 與嵌入式服務器一起使用的選項](#)[ 25.1.5. 嵌入式服務器中尚需完成的事項(TODO)](#)[ 25.1.6. 嵌入式服務器示例](#)[ 25.1.7. 嵌入式服務器的許可](#)[25.2. MySQL C API](#)[ 25.2.1. C API數據類型](#)[ 25.2.2. C API函數概述](#)[ 25.2.3. C API函數描述](#)[ 25.2.4. C API預處理語句](#)[ 25.2.5. C API預處理語句的數據類型](#)[ 25.2.6. C API預處理語句函數概述](#)[ 25.2.7. C API預處理語句函數描述](#)[ 25.2.8. C API預處理語句方面的問題](#)[ 25.2.9. 多查詢執行的C API處理](#)[ 25.2.10. 日期和時間值的C API處理](#)[ 25.2.11. C API線程函數介紹](#)[ 25.2.12. C API嵌入式服務器函數介紹](#)[ 25.2.13. 使用C API時的常見問題](#)[ 25.2.14. 創建客戶端程序](#)[ 25.2.15. 如何生成線程式客戶端](#)[25.3. MySQL PHP API](#)[ 25.3.1. 使用MySQL和PHP的常見問題](#)[25.4. MySQL Perl API](#)[25.5. MySQL C++ API](#)[25.5.1. Borland C++](#)[25.6. MySQL Python API](#)[25.7. MySQL Tcl API](#)[25.8. MySQL Eiffel Wrapper](#)[ 25.9. MySQL程序開發實用工具](#)[ 25.9.1. msql2mysql:轉換mSQL程序以用于MySQL](#)[ 25.9.2. mysql_config:獲取編譯客戶端的編譯選項](#) [本章介紹了MySQL可使用的API,從哪里獲得它們,以及如何使用它們。]() 詳細介紹C API,這是因為它是由MySQL團隊開發的,而且它也是大多數其他API的基礎。 本章還介紹了libmysqld庫(嵌入式服務器),以及對應用程序開發人員有用的一些程序。 ### 25.1.?libmysqld,嵌入式MySQL服務器庫 [25.1.1. 嵌入式MySQL服務器庫概述](#)[ 25.1.2. 使用libmysqld編譯程序``](#)[ 25.1.3. 使用嵌入式MySQL服務器時的限制](#)[25.1.4. 與嵌入式服務器一起使用的選項](#)[ 25.1.5. 嵌入式服務器中尚需完成的事項(TODO)](#)[ 25.1.6. 嵌入式服務器示例](#)[ 25.1.7. 嵌入式服務器的許可](#) ### 25.1.1.?嵌入式MySQL服務器庫概述 使用嵌入式MySQL服務器庫,能夠在客戶端應用程序中使用具備全部特性的MySQL服務器。 主要優點在于,增加了速度,并使得嵌入式應用程序的管理更簡單。 嵌入式服務器庫是以MySQL的客戶端/服務器版本為基礎的,采用C/C++語言編寫。 其結果是嵌入式服務器也是用C/C++語言編寫的。 在其他語言中,嵌入式服務器不可用。 API與嵌入式MySQL版本和客戶端/服務器版本等效。 要想更改舊的線程式應用程序以使用嵌入式庫,正常情況下,僅需添加對下述函數的調用即可。 <table border="1" cellpadding="0" id="table1"><tr><td> <p><b>函數</b></p></td> <td> <p><b>何時調用</b></p></td> </tr><tr><td> <p> <span>mysql_server_init()</span></p></td> <td> <p>應在調用任何其他MySQL函數之前調用,最好是在<span>main()函數中調用。</span></p></td> </tr><tr><td> <p> <span>mysql_server_end()</span></p></td> <td> <p>應在程序退出前調用。</p></td> </tr><tr><td> <p> <span>mysql_thread_init()</span></p></td> <td> <p>應在你所創建的、用于訪問MySQL的每個線程中調用。</p></td> </tr><tr><td> <p> <span>mysql_thread_end()</span></p></td> <td> <p>應在調用<span>pthread_exit()之前調用。</span></p></td> </tr></table> 隨后,必須將你的代碼與libmysqld.a鏈接起來,而不是libmysqlclient.a。 在libmysqlclient.a中還包含mysql_server_*xxx*()函數,使用這類函數,通過將應用程序鏈接到恰當的庫,即可在嵌入式版本和客戶端/服務器版本之間切換。 請參見[25.2.12.1節,“mysql_server_init()”](# "25.2.12.1.?mysql_server_init()")。 嵌入式服務器和獨立服務器之間的一項差別在于,對于嵌入式服務器,默認情況下,連接鑒定是禁止的。 對于嵌入式服務器,要想使用鑒定功能,可在激活“**configure**”以配置MySQL分發版時使用“--with-embedded-privilege-control”選項。 ### 25.1.2.?使用libmysqld編譯程序`` 要想獲得libmysqld庫,應使用“--with-embedded-server”選項配置MySQL。 請參見[2.8.2節,“典型配置選項****”](# "2.8.2.?Typical configure Options")。 將你的程序與libmysqld鏈接時,還必須包含系統的pthread庫以及MySQL服務器使用的一些庫。 執行“**mysql_config --libmysqld-libs**”,可獲得庫的完整列表。 對于線程程序的編譯和鏈接,必須使用正確的標志,即使你未在代碼中直接調用任何線程函數也同樣。 要想編譯C程序以包含必要文件,并將MySQL服務器庫嵌入到程序的編譯版本中,可使用GNU C編譯器(gcc)。 編譯器需要知道各種文件的位置,并需了解如何編譯程序的指令。 在下面的示例中,介紹了如何從命令行編譯程序的方法: ~~~ gcc mysql_test.c -o mysql_test -lz \ ~~~ ~~~ `/usr/local/mysql/bin/mysql_config --include --libmysqld-libs` ~~~ 在gcc命令后緊跟著未編譯C程序文件的名稱。 接下來,給定的“-o”選項指明,它后面的文件名是編譯器將輸出文件的名稱,即編譯后的程序。 在下一行的代碼中,通知編譯器獲取包含文件和庫的位置,以及在其上進行編譯的系統的其他設置。 由于“**mysql_config**”存在的問題,在此添加了“-lz”選項(壓縮)。 “**mysql_config**”部分包含在backticks中,而不是單引號內。 ### 25.1.3.?使用嵌入式MySQL服務器時的限制 嵌入式服務器存在下述限制: ·???????? 不支持ISAM表。 (這樣做的主要目的是為了使庫更小)。 ·???????? 沒有自定義函數(UDF)。 ·???????? 沒有對核心轉儲的堆棧跟蹤。 ·???????? 沒有內部RAID支持。 (由于大多數當前操作系統均支持大文件,通常情況下不需要它)。 ·???????? 不能將其設置為“主”或“從”(無復制)。 ·???????? 在內存較低的系統上,可能無法使用很大的結果集。 ·???????? 不能使用套接字或TCP/IP從外部進程連接到嵌入式服務器。 但是,你可以連接到中間應用程序,隨后,該中間應用程序可代表遠程客戶端或外部進程連接到嵌入式服務器。 通過編輯“mysql_embed.h”包含文件并重新編譯MySQL,可更改某些限制。 ### 25.1.4.?與嵌入式服務器一起使用的選項 對于任何能夠與**mysqld**服務器端口監督程序一起給定的選項,也可以與嵌入式服務器庫一起使用。在數組中,可將服務器選項作為參量指定給用于初始化服務器的mysql_server_init()。也能在諸如my.cnf的選項文件中給定它們。要想為C程序指定選項文件,請使用“--defaults-file”選項作為函數mysql_server_init()的第2個參量的元素之一。關于mysql_server_init()函數的更多信息,請參見[25.2.12.1節,“mysql_server_init()”](# "25.2.12.1.?mysql_server_init()")。 使用選項文件,能夠簡化客戶端/服務器應用程序和嵌入了MySQL的應用程序之間的切換。將常用選項置于[server]組。它們可被兩種MySQL版本讀取。客戶端/服務器選項應被放在[mysqld]部分。將嵌入式MySQL服務器庫的選項放在[embedded]部分。將與應用程序相關的選項放在標記為[ApplicationName_SERVER]的部分。請參見[4.3.2節,“使用選項文件”](# "4.3.2.?Using Option Files")。 ### 25.1.5.?嵌入式服務器中尚需完成的事項(TODO) ·???????? 我們將提供一些選項以省去MySQL的某些部分,從而使庫變得更小。 ·???????? 仍有很多速度優化工作需要完成。 ·???????? 錯誤將被寫入stderr。我們將增加1個選項為它們指定文件名。 ·???????? 使用嵌入式版本時,需要更改InnoDB,使之不再冗長。如果你的數據庫不含InnoDB表,要想抑制相關消息,可為組[libmysqd_server]下的選項文件增加“--skip-innodb”選項,或在用**mysql_server_init()**初始化服務器時添加該選項。 ### 25.1.6.?嵌入式服務器示例 在Linux或FreeBSD系統上,無需更改就能使用下面這兩個示例程序。對于其他操作系統,需要進行小的修改,主要是文件路徑。設計這兩個示例的目的在于,為你提供足夠的細節信息,以便理解問題,它們是實際應用程序的必要組成部份。第1個示例十分直觀。第2個示例采用了一些錯誤檢查功能,略為復雜。在第1個示例的后面,給出了用于編譯程序的命令行條目。在第2個示例的后面,給出了GNUmake文件,該文件可用于編譯。 **示例:1** test1_libmysqld.c ~~~ #include <stdio.h> ~~~ ~~~ #include <stdlib.h> ~~~ ~~~ #include <stdarg.h> ~~~ ~~~ #include "mysql.h" ~~~ ~~~ ? ~~~ ~~~ MYSQL *mysql; ~~~ ~~~ MYSQL_RES *results; ~~~ ~~~ MYSQL_ROW record; ~~~ ~~~ ? ~~~ ~~~ static char *server_options[] = { "mysql_test", "--defaults-file=my.cnf" }; ~~~ ~~~ int num_elements = sizeof(server_options)/ sizeof(char *); ~~~ ~~~ ? ~~~ ~~~ static char *server_groups[] = { "libmysqld_server", "libmysqld_client" }; ~~~ ~~~ ? ~~~ ~~~ int main(void) ~~~ ~~~ { ~~~ ~~~ ?? mysql_server_init(num_elements, server_options, server_groups); ~~~ ~~~ ?? mysql = mysql_init(NULL); ~~~ ~~~ ?? mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_client"); ~~~ ~~~ ?? mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL); ~~~ ~~~ ? ~~~ ~~~ ?? mysql_real_connect(mysql, NULL,NULL,NULL, "database1", 0,NULL,0); ~~~ ~~~ ? ~~~ ~~~ ?? mysql_query(mysql, "SELECT column1, column2 FROM table1"); ~~~ ~~~ ? ~~~ ~~~ ?? results = mysql_store_result(mysql); ~~~ ~~~ ? ~~~ ~~~ ?? while((record = mysql_fetch_row(results))) { ~~~ ~~~ ????? printf("%s - %s \n", record[0], record[1]); ~~~ ~~~ ?? } ~~~ ~~~ ? ~~~ ~~~ ?? mysql_free_result(results); ~~~ ~~~ ?? mysql_close(mysql); ~~~ ~~~ ?? mysql_server_end(); ~~~ ~~~ ? ~~~ ~~~ ?? return 0; ~~~ ~~~ } ~~~ 下面給出了編譯上述程序的命令行命令: ~~~ gcc test1_libmysqld.c -o test1_libmysqld -lz \ ~~~ ~~~ `/usr/local/mysql/bin/mysql_config --include --libmysqld-libs` ~~~ **示例:2** 要想檢驗該示例,創建一個與MySQL源目錄同級的test2_libmysqld目錄。將test2_libmysqld.c源文件和GNUmakefile保存到該目錄,并在test2_libmysqld目錄下運行GNU make。 test2_libmysqld.c ~~~ /* ~~~ ~~~ * A simple example client, using the embedded MySQL server library ~~~ ~~~ */ ~~~ ~~~ ? ~~~ ~~~ #include <mysql.h> ~~~ ~~~ #include <stdarg.h> ~~~ ~~~ #include <stdio.h> ~~~ ~~~ #include <stdlib.h> ~~~ ~~~ ? ~~~ ~~~ MYSQL *db_connect(const char *dbname); ~~~ ~~~ void db_disconnect(MYSQL *db); ~~~ ~~~ void db_do_query(MYSQL *db, const char *query); ~~~ ~~~ ? ~~~ ~~~ const char *server_groups[] = { ~~~ ~~~ ? "test2_libmysqld_SERVER", "embedded", "server", NULL ~~~ ~~~ }; ~~~ ~~~ ? ~~~ ~~~ int ~~~ ~~~ main(int argc, char **argv) ~~~ ~~~ { ~~~ ~~~ ? MYSQL *one, *two; ~~~ ~~~ ? ~~~ ~~~ ? /* mysql_server_init() must be called before any other mysql ~~~ ~~~ ?? * functions. ~~~ ~~~ ?? * ~~~ ~~~ ?? * You can use mysql_server_init(0, NULL, NULL), and it ~~~ ~~~ ?? * initializes the server using groups = { ~~~ ~~~ ?? *?? "server", "embedded", NULL ~~~ ~~~ ?? *? }. ~~~ ~~~ ?? * ~~~ ~~~ ?? * In your $HOME/.my.cnf file, you probably want to put: ~~~ ~~~ ? ~~~ ~~~ [test2_libmysqld_SERVER] ~~~ ~~~ language = /path/to/source/of/mysql/sql/share/english ~~~ ~~~ ? ~~~ ~~~ ?? * You could, of course, modify argc and argv before passing ~~~ ~~~ ?? * them to this function.? Or you could create new ones in any ~~~ ~~~ ?? * way you like.? But all of the arguments in argv (except for ~~~ ~~~ ?? * argv[0], which is the program name) should be valid options ~~~ ~~~ ?? * for the MySQL server. ~~~ ~~~ ?? * ~~~ ~~~ ?? * If you link this client against the normal mysqlclient ~~~ ~~~ ?? * library, this function is just a stub that does nothing. ~~~ ~~~ ?? */ ~~~ ~~~ ? mysql_server_init(argc, argv, (char **)server_groups); ~~~ ~~~ ? ~~~ ~~~ ? one = db_connect("test"); ~~~ ~~~ ? two = db_connect(NULL); ~~~ ~~~ ? ~~~ ~~~ ? db_do_query(one, "SHOW TABLE STATUS"); ~~~ ~~~ ? db_do_query(two, "SHOW DATABASES"); ~~~ ~~~ ? ~~~ ~~~ ? mysql_close(two); ~~~ ~~~ ? mysql_close(one); ~~~ ~~~ ? ~~~ ~~~ ? /* This must be called after all other mysql functions */ ~~~ ~~~ ? mysql_server_end(); ~~~ ~~~ ? ~~~ ~~~ ? exit(EXIT_SUCCESS); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ static void ~~~ ~~~ die(MYSQL *db, char *fmt, ...) ~~~ ~~~ { ~~~ ~~~ ? va_list ap; ~~~ ~~~ ? va_start(ap, fmt); ~~~ ~~~ ? vfprintf(stderr, fmt, ap); ~~~ ~~~ ? va_end(ap); ~~~ ~~~ ? (void)putc('\n', stderr); ~~~ ~~~ ? if (db) ~~~ ~~~ ??? db_disconnect(db); ~~~ ~~~ ? exit(EXIT_FAILURE); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ MYSQL * ~~~ ~~~ db_connect(const char *dbname) ~~~ ~~~ { ~~~ ~~~ ? MYSQL *db = mysql_init(NULL); ~~~ ~~~ ? if (!db) ~~~ ~~~ ??? die(db, "mysql_init failed: no memory"); ~~~ ~~~ ? /* ~~~ ~~~ ?? * Notice that the client and server use separate group names. ~~~ ~~~ ?? * This is critical, because the server does not accept the ~~~ ~~~ ?? * client's options, and vice versa. ~~~ ~~~ ?? */ ~~~ ~~~ ? mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test2_libmysqld_CLIENT"); ~~~ ~~~ ? if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0)) ~~~ ~~~ ??? die(db, "mysql_real_connect failed: %s", mysql_error(db)); ~~~ ~~~ ? ~~~ ~~~ ? return db; ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ void ~~~ ~~~ db_disconnect(MYSQL *db) ~~~ ~~~ { ~~~ ~~~ ? mysql_close(db); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ void ~~~ ~~~ db_do_query(MYSQL *db, const char *query) ~~~ ~~~ { ~~~ ~~~ ? if (mysql_query(db, query) != 0) ~~~ ~~~ ??? goto err; ~~~ ~~~ ? ~~~ ~~~ ? if (mysql_field_count(db) > 0) ~~~ ~~~ ? { ~~~ ~~~ ??? MYSQL_RES?? *res; ~~~ ~~~ ??? MYSQL_ROW??? row, end_row; ~~~ ~~~ ??? int num_fields; ~~~ ~~~ ? ~~~ ~~~ ??? if (!(res = mysql_store_result(db))) ~~~ ~~~ ?????goto err; ~~~ ~~~ ??? num_fields = mysql_num_fields(res); ~~~ ~~~ ??? while ((row = mysql_fetch_row(res))) ~~~ ~~~ ??? { ~~~ ~~~ ?????(void)fputs(">> ", stdout); ~~~ ~~~ ????? for (end_row = row + num_fields; row < end_row; ++row) ~~~ ~~~ ??????? (void)printf("%s\t", row ? (char*)*row : "NULL"); ~~~ ~~~ ????? (void)fputc('\n', stdout); ~~~ ~~~ ??? } ~~~ ~~~ ??? (void)fputc('\n', stdout); ~~~ ~~~ ??? mysql_free_result(res); ~~~ ~~~ ? } ~~~ ~~~ ? else ~~~ ~~~ ??? (void)printf("Affected rows: %lld\n", mysql_affected_rows(db)); ~~~ ~~~ ? ~~~ ~~~ ? return; ~~~ ~~~ ? ~~~ ~~~ err: ~~~ ~~~ ? die(db, "db_do_query failed: %s [%s]", mysql_error(db), query); ~~~ ~~~ } ~~~ GNUmakefile ~~~ # This assumes the MySQL software is installed in /usr/local/mysql ~~~ ~~~ inc????? := /usr/local/mysql/include/mysql ~~~ ~~~ lib????? := /usr/local/mysql/lib ~~~ ~~~ ? ~~~ ~~~ # If you have not installed the MySQL software yet, try this instead ~~~ ~~~ #inc????? := $(HOME)/mysql-5.1/include ~~~ ~~~ #lib????? := $(HOME)/mysql-5.1/libmysqld ~~~ ~~~ ? ~~~ ~~~ CC ??????:= gcc ~~~ ~~~ CPPFLAGS := -I$(inc) -D_THREAD_SAFE -D_REENTRANT ~~~ ~~~ CFLAGS?? := -g -W -Wall ~~~ ~~~ LDFLAGS? := -static ~~~ ~~~ # You can change -lmysqld to -lmysqlclient to use the ~~~ ~~~ # client/server library ~~~ ~~~ LDLIBS??? = -L$(lib) -lmysqld -lz -lm -lcrypt ~~~ ~~~ ? ~~~ ~~~ ifneq (,$(shell grep FreeBSD /COPYRIGHT 2>/dev/null)) ~~~ ~~~ # FreeBSD ~~~ ~~~ LDFLAGS += -pthread ~~~ ~~~ else ~~~ ~~~ # Assume Linux ~~~ ~~~ LDLIBS += -lpthread ~~~ ~~~ endif ~~~ ~~~ ? ~~~ ~~~ # This works for simple one-file test programs ~~~ ~~~ sources := $(wildcard *.c) ~~~ ~~~ objects := $(patsubst %c,%o,$(sources)) ~~~ ~~~ targets := $(basename $(sources)) ~~~ ~~~ ? ~~~ ~~~ all: $(targets) ~~~ ~~~ ? ~~~ ~~~ clean: ~~~ ~~~ ??????? rm -f $(targets) $(objects) *.core ~~~ ### 25.1.7.?嵌入式服務器的許可 我們鼓勵所有人在GPL或兼容許可的旗幟下通過發布代碼來推廣免費軟件。對于有能力完成該類事項的人員,也可以選擇從MySQL AB購買MySQL的商用許可。詳情請參見[http://www.mysql.com/company/legal/licensing/](http://www.mysql.com/company/legal/licensing/)。 ### 25.2.?MySQL C API [ 25.2.1. C API數據類型](#)[ 25.2.2. C API函數概述](#)[ 25.2.3. C API函數描述](#)[ 25.2.4. C API預處理語句](#)[ 25.2.5. C API預處理語句的數據類型](#)[ 25.2.6. C API預處理語句函數概述](#)[ 25.2.7. C API預處理語句函數描述](#)[ 25.2.8. C API預處理語句方面的問題](#)[ 25.2.9. 多查詢執行的C API處理](#)[ 25.2.10. 日期和時間值的C API處理](#)[ 25.2.11. C API線程函數介紹](#)[ 25.2.12. C API嵌入式服務器函數介紹](#)[ 25.2.13. 使用C API時的常見問題](#)[ 25.2.14. 創建客戶端程序](#)[ 25.2.15. 如何生成線程式客戶端](#) C API代碼是與MySQL一起提供的。它包含在mysqlclient庫中,并允許C程序訪問數據庫。 MySQL源碼分發版的很多客戶端是用C語言編寫的。如果你正在尋找能演示如何使用C API的示例,可參看這些客戶端程序。你可以在MySQL源碼分發版的客戶端目錄下找到它們。 大多數其他客戶端API(除了Connector/J和Connector/NET)采用mysqlclient庫來與MySQL服務器進行通信。這意味著(例如),你可以利用很多相同環境變量(與其他客戶端程序使用的環境變量相同)帶來的好處,這是因為它們是從庫中引用的。關于這些變量的詳細清單,請參見[第8章:](#)[*客戶端和實用工具程序*](# "Chapter?8.?Client and Utility Programs")。 客戶端具有最大的通信緩沖區大小。初始分配的緩沖區大小(16KB)將自動增加到最大(最大為16MB)。由于緩沖區大小將按需增加,簡單地增加默認的最大限制,從其本身來說不會增加資源使用。該大小檢查主要是檢查錯誤查詢和通信信息包。 通信緩沖區必須足夠大,足以包含1條SQL語句(用于客戶端-服務器通信)以及1行返回的數據(用于服務器-客戶端通信)。每個線程的通信緩沖區將動態增加,以處理直至最大限制的任何查詢或行。例如,如果BLOB值包含高達16MB的數據,那么通信緩沖區的大小限制至少為16MB(在服務器和客戶端)。客戶端的默認最大值為16MB,但服務器的默認最大值為1MB。也可以在啟動服務器時,通過更改max_allowed_packet參數的值增加它。請參見[7.5.2節,“調節服務器參數”](# "7.5.2.?Tuning Server Parameters")。 每次查詢后,MySQL服務器會將通信緩沖區的大小降至net_buffer_length字節。對于客戶端,不會降低與連接相關緩沖區大小,直至連接關閉為止,此時,客戶端內存將被收回。 關于使用線程的編程方法,請參見[25.2.15節,“如何生成線程式客戶端”](# "25.2.15.?How to Make a Threaded Client")。關于在相同程序創建包含“服務器”和“客戶端”的獨立應用程序的更多信息(不與外部MySQL服務器通信),請參見[25.1節,“libmysqld,嵌入式MySQL服務器庫”](# "25.1.?libmysqld, the Embedded MySQL Server Library")。 ### 25.2.1.?C API數據類型 - MYSQL 該結構代表1個數據庫連接的句柄。幾乎所有的MySQL函數均使用它。不應嘗試拷貝MYSQL結構。不保證這類拷貝結果會有用。 - MYSQL_RES 該結構代表返回行的查詢結果(SELECT, SHOW, DESCRIBE, EXPLAIN)。在本節的剩余部分,將查詢返回的信息稱為“結果集”。 - MYSQL_ROW 這是1行數據的“類型安全”表示。它目前是按照計數字節字符串的數組實施的。(如果字段值可能包含二進制數據,不能將其當作由Null終結的字符串對待,這是因為這類值可能會包含Null字節)。行是通過調用mysql_fetch_row()獲得的。 - MYSQL_FIELD 該結構包含關于字段的信息,如字段名、類型和大小。這里詳細介紹了其成員。通過重復調用mysql_fetch_field(),可為每個字段獲得MYSQL_FIELD結構。字段值不是該結構的組成部份,它們包含在MYSQL_ROW結構中。 - MYSQL_FIELD_OFFSET 這是MySQL字段列表偏移量的“類型安全”表示(由mysql_field_seek()使用)。偏移量是行內的字段編號,從0開始。 - my_ulonglong 用于行數以及mysql_affected_rows()、mysql_num_rows()和mysql_insert_id()的類型。該類型提供的范圍為0~1.84e19。 在某些系統上,不能打印類型my_ulonglong的值。要想打印這類值,請將其轉換為無符號長整數類型并使用%lu打印格式,例如: ~~~ printf ("Number of rows: %lu\n", (unsigned long) mysql_num_rows(result)); ~~~ 下面列出了MYSQL_FIELD結構包含的成員: ·???????? char * name 字段名稱,由Null終結的字符串。如果用AS子句為該字段指定了別名,名稱的值也是別名。 ·???????? char * org_name 段名稱,由Null終結的字符串。忽略別名。 ·???????? char * table 包含該字段的表的名稱,如果該字段不是計算出的字段的話。對于計算出的字段,表值為空的字符串。如果用AS子句為該表指定了別名,表的值也是別名。 ·???????? char * org_table 表的名稱,由Null終結的字符串。忽略別名。 ·???????? char * db 字段源自的數據的名稱,由Null終結的字符串。如果該字段是計算出的字段,db為空的字符串。 ·???????? char * catalog catalog名稱。該值總是"def"。 ·???????? char * def 該字段的默認值,由Null終結的字符串。僅當使用mysql_list_fields()時才設置它。 ·???????? unsigned long length 字段的寬度,如表定義中所指定的那樣。 ·???????? unsigned long max_length 用于結果集的字段的最大寬度(對于實際位于結果集中的行,最長字段值的長度)。如果使用mysql_store_result()或mysql_list_fields(),它將包含字段的最大長度。如果使用mysql_use_result(),該變量的值為0。 ·???????? unsigned int name_length 名稱的長度。 ·???????? unsigned int org_name_length org_name的長度。 ·???????? unsigned int table_length 表的長度。 ·???????? unsigned int org_table_length org_table的長度。 ·???????? unsigned int db_length db的長度。 ·???????? unsigned int catalog_length catalog的長度。 ·???????? unsigned int def_length def的長度。 ·???????? unsigned int flags 用于字段的不同“位標志”。標志的值可以有0個或多個下述位集合: <table border="1" cellpadding="0" id="table2"><tr><td> <p><strong><span> 標志值</span></strong></p></td> <td> <p><strong><span> 標志描述</span></strong></p></td> </tr><tr><td> <p> <span>NOT_NULL_FLAG</span></p></td> <td> <p>字段不能為<span>NULL</span></p></td> </tr><tr><td> <p> <span>PRI_KEY_FLAG</span></p></td> <td> <p>字段是主鍵的組成部分</p></td> </tr><tr><td> <p> <span>UNIQUE_KEY_FLAG</span></p></td> <td> <p>字段是唯一鍵的組成部分</p></td> </tr><tr><td> <p> <span>MULTIPLE_KEY_FLAG</span></p></td> <td> <p>字段是非唯一鍵的組成部分</p></td> </tr><tr><td> <p> <span>UNSIGNED_FLAG</span></p></td> <td> <p>字段具有<span>UNSIGNED</span>屬性</p></td> </tr><tr><td> <p> <span>ZEROFILL_FLAG</span></p></td> <td> <p>字段具有<span>ZEROFILL</span>屬性</p></td> </tr><tr><td> <p> <span>BINARY_FLAG</span></p></td> <td> <p>字段具有<span>BINARY</span>屬性</p></td> </tr><tr><td> <p> <span>AUTO_INCREMENT_FLAG</span></p></td> <td> <p>字段具有<span>AUTO_INCREMENT</span>屬性</p></td> </tr><tr><td> <p> <span>ENUM_FLAG</span></p></td> <td> <p>字段是<span>ENUM</span>(不再重視)</p></td> </tr><tr><td> <p> <span>SET_FLAG</span></p></td> <td> <p>字段是 <span>SET</span>(不再重視)</p></td> </tr><tr><td> <p> <span>BLOB_FLAG</span></p></td> <td> <p>字段是<span>BLOB</span>或<span>TEXT</span>(不再重視)</p></td> </tr><tr><td> <p> <span>TIMESTAMP_FLAG</span></p></td> <td> <p>字段是<span>TIMESTAMP</span>(不再重視)</p></td> </tr></table> 不再重視BLOB_FLAG、ENUM_FLAG、SET_FLAG和TIMESTAMP_FLAG標志,原因在于,它們指出了字段的類型,而不是類型的屬性。更可取的方式是使用MYSQL_TYPE_BLOB、MYSQL_TYPE_ENUM、MYSQL_TYPE_SET或MYSQL_TYPE_TIMESTAMP測試field->type。 在下面的示例中,介紹了標志值的典型用法: ~~~ if (field->flags & NOT_NULL_FLAG) ~~~ ~~~ ??? printf("Field can't be null\n"); ~~~ 可以使用下述方面的宏來定義標志值的布爾狀態: <table border="1" cellpadding="0" id="table3"><tr><td> <p><strong><span> 標志狀態</span></strong></p></td> <td> <p><strong><span> 描述</span></strong></p></td> </tr><tr><td> <p> <span>IS_NOT_NULL(flags)</span></p></td> <td> <p>如果該字段定義為<span><span>NOT NULL</span>,為<span>“</span>真<span>”</span>。</span></p></td> </tr><tr><td> <p> <span>IS_PRI_KEY(flags)</span></p></td> <td> <p>如果該字段是主鍵<span>,為<span>“</span>真<span>”</span>。</span></p></td> </tr><tr><td> <p> <span>IS_BLOB(flags)</span></p></td> <td> <p>如果該字段是<span>BLOB</span>或<span>TEXT</span><span>,為<span>“</span>真<span>”</span>(不再重視</span>,用測試<span>field-&gt;type</span>取而代之)。</p></td> </tr></table> ·???????? unsigned int decimals 用于數值字段的十進制數數目。 ·???????? unsigned int charset_nr 用于字段的字符集編號。 ·???????? enum enum_field_types type 字段的類型。類型值可以是下標所列的MYSQL_TYPE_符號之一: <table border="1" cellpadding="0" id="table4"><tr><td> <p><strong><span> 類型值</span></strong></p></td> <td> <p><strong><span> 類型描述</span></strong></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TINY</span></p></td> <td> <p> <span>TINYINT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_SHORT</span></p></td> <td> <p> <span>SMALLINT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_LONG</span></p></td> <td> <p> <span>INTEGER</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_INT24</span></p></td> <td> <p> <span>MEDIUMINT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_LONGLONG</span></p></td> <td> <p> <span>BIGINT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DECIMAL</span></p></td> <td> <p> <span>DECIMAL</span>或<span>NUMERIC</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_NEWDECIMAL</span></p></td> <td> <p>精度數學<span>DECIMAL</span>或<span>NUMERIC</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_FLOAT</span></p></td> <td> <p> <span>FLOAT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DOUBLE</span></p></td> <td> <p> <span>DOUBLE</span>或<span>REAL</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_BIT</span></p></td> <td> <p> <span>BIT</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TIMESTAMP</span></p></td> <td> <p> <span>TIMESTAMP</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DATE</span></p></td> <td> <p> <span>DATE</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TIME</span></p></td> <td> <p> <span>TIME</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DATETIME</span></p></td> <td> <p> <span>DATETIME</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_YEAR</span></p></td> <td> <p> <span>YEAR</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_STRING</span></p></td> <td> <p> <span>CHAR</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_VAR_STRING</span></p></td> <td> <p> <span>VARCHAR</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_BLOB</span></p></td> <td> <p> <span>BLOB</span>或<span>TEXT</span>字段(使用<span><span>max_length</span>來確定最大長度)</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_SET</span></p></td> <td> <p> <span>SET</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_ENUM</span></p></td> <td> <p> <span>ENUM</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_GEOMETRY</span></p></td> <td> <p><span>Spatial</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_NULL</span></p></td> <td> <p> <span>NULL</span><span>-type</span>字段</p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_CHAR</span></p></td> <td> <p>不再重視,用<span>MYSQL_TYPE_TINY</span>取代</p></td> </tr></table> 可以使用IS_NUM()宏來測試字段是否具有數值類型。將類型值傳遞給IS_NUM(),如果字段為數值類型,會將其評估為“真”: ~~~ if (IS_NUM(field->type)) ~~~ ~~~ ??? printf("Field is numeric\n"); ~~~ ### 25.2.2.?C API函數概述 這里歸納了C API可使用的函數,并在下一節詳細介紹了它們。請參見[25.2.3節,“C API函數描述”](# "25.2.3.?C API Function Descriptions")。 <table border="1" cellpadding="0" id="table5"><tr><td> <p><strong><span> 函數</span></strong></p></td> <td> <p><strong><span> 描述</span></strong></p></td> </tr><tr><td> <p><strong> <span> mysql_affected_rows()</span></strong></p></td> <td> <p>返回上次<span>UPDATE</span>、<span>DELETE</span>或<span><span>INSERT</span>查詢更改/刪除/插入的行數。</span></p></td> </tr><tr><td> <p><strong> <span>mysql_autocommit()</span></strong></p></td> <td> <p>切換<span> autocommit</span>模式,<span>ON/OFF</span></p></td> </tr><tr><td> <p><strong> <span>mysql_change_user()</span></strong></p></td> <td> <p>更改打開連接上的用戶和數據庫。</p></td> </tr><tr><td> <p><strong> <span> mysql_charset_name()</span></strong></p></td> <td> <p>返回用于連接的默認字符集的名稱。</p></td> </tr><tr><td> <p><strong> <span>mysql_close()</span></strong></p></td> <td> <p>關閉服務器連接。</p></td> </tr><tr><td> <p><strong> <span>mysql_commit()</span></strong></p></td> <td> <p>提交事務。</p></td> </tr><tr><td> <p><strong> <span>mysql_connect()</span></strong></p></td> <td> <p>連接到<span>MySQL</span>服務器。該函數已不再被重視,使用<span>mysql_real_connect()</span>取代。</p></td> </tr><tr><td> <p><strong> <span>mysql_create_db()</span></strong></p></td> <td> <p>創建數據庫。該函數已不再被重視,使用<span>SQL</span>語句<span>CREATE DATABASE</span>取而代之。</p></td> </tr><tr><td> <p><strong> <span>mysql_data_seek()</span></strong></p></td> <td> <p>在查詢結果集中查找屬性行編號。</p></td> </tr><tr><td> <p><strong> <span>mysql_debug()</span></strong></p></td> <td> <p>用給定的字符串執行<span>DBUG_PUSH</span>。</p></td> </tr><tr><td> <p><strong> <span>mysql_drop_db()</span></strong></p></td> <td> <p>撤銷數據庫。該函數已不再被重視,使用<span>SQL</span>語句<span>DROP DATABASE</span>取而代之。</p></td> </tr><tr><td> <p><strong> <span> mysql_dump_debug_info()</span></strong></p></td> <td> <p>讓服務器將調試信息寫入日志。</p></td> </tr><tr><td> <p><strong> <span>mysql_eof()</span></strong></p></td> <td> <p>確定是否讀取了結果集的最后一行。該函數已不再被重視,可以使用<span>mysql_errno()</span>或<span>mysql_error()</span>取而代之。</p></td> </tr><tr><td> <p><strong> <span>mysql_errno()</span></strong></p></td> <td> <p>返回上次調用的<span>MySQL</span>函數的錯誤編號。</p></td> </tr><tr><td> <p><strong> <span>mysql_error()</span></strong></p></td> <td> <p>返回上次調用的<span>MySQL</span>函數的錯誤消息。</p></td> </tr><tr><td> <p><strong> <span> mysql_escape_string()</span></strong></p></td> <td> <p>為了用在<span>SQL</span>語句中,對特殊字符進行轉義處理。</p></td> </tr><tr><td> <p><strong> <span>mysql_fetch_field()</span></strong></p></td> <td> <p>返回下一個表字段的類型。</p></td> </tr><tr><td> <p><strong> <span> mysql_fetch_field_direct()</span></strong></p></td> <td> <p>給定字段編號,返回表字段的類型。</p></td> </tr><tr><td> <p><strong> <span> mysql_fetch_fields()</span></strong></p></td> <td> <p>返回所有字段結構的數組。</p></td> </tr><tr><td> <p><strong> <span> mysql_fetch_lengths()</span></strong></p></td> <td> <p>返回當前行中所有列的長度。</p></td> </tr><tr><td> <p><strong> <span>mysql_fetch_row()</span></strong></p></td> <td> <p>從結果集中獲取下一行</p></td> </tr><tr><td> <p><strong> <span>mysql_field_seek()</span></strong></p></td> <td> <p>將列光標置于指定的列。</p></td> </tr><tr><td> <p><strong> <span>mysql_field_count()</span></strong></p></td> <td> <p>返回上次執行語句的結果列的數目。</p></td> </tr><tr><td> <p><strong> <span>mysql_field_tell()</span></strong></p></td> <td> <p>返回上次<span><span>mysql_fetch_field()</span>所使用字段光標的位置。</span></p></td> </tr><tr><td> <p><strong> <span>mysql_free_result()</span></strong></p></td> <td> <p>釋放結果集使用的內存。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_client_info()</span></strong></p></td> <td> <p>以字符串形式返回客戶端版本信息。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_client_version()</span></strong></p></td> <td> <p>以整數形式返回客戶端版本信息。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_host_info()</span></strong></p></td> <td> <p>返回描述連接的字符串。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_server_version()</span></strong></p></td> <td> <p>以整數形式返回服務器的版本號。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_proto_info()</span></strong></p></td> <td> <p>返回連接所使用的協議版本。</p></td> </tr><tr><td> <p><strong> <span> mysql_get_server_info()</span></strong></p></td> <td> <p>返回服務器的版本號。</p></td> </tr><tr><td> <p><strong> <span>mysql_info()</span></strong></p></td> <td> <p>返回關于最近所執行查詢的信息。</p></td> </tr><tr><td> <p><strong> <span>mysql_init()</span></strong></p></td> <td> <p>獲取或初始化<span>MYSQL</span>結構。</p></td> </tr><tr><td> <p><strong> <span>mysql_insert_id()</span></strong></p></td> <td> <p>返回上一個查詢為<span><span>AUTO_INCREMENT</span>列生成的</span><span>ID</span>。</p></td> </tr><tr><td> <p><strong> <span>mysql_kill()</span></strong></p></td> <td> <p>殺死給定的線程。</p></td> </tr><tr><td> <p><strong> <span>mysql_library_end()</span></strong></p></td> <td> <p>最終確定<span>MySQL C API</span>庫。</p></td> </tr><tr><td> <p><strong> <span> mysql_library_init()</span></strong></p></td> <td> <p>初始化<span>MySQL C API</span>庫。</p></td> </tr><tr><td> <p><strong> <span>mysql_list_dbs()</span></strong></p></td> <td> <p>返回與簡單正則表達式匹配的數據庫名稱。</p></td> </tr><tr><td> <p><strong> <span>mysql_list_fields()</span></strong></p></td> <td> <p>返回與簡單正則表達式匹配的字段名稱。</p></td> </tr><tr><td> <p><strong> <span> mysql_list_processes()</span></strong></p></td> <td> <p>返回當前服務器線程的列表。</p></td> </tr><tr><td> <p><strong> <span>mysql_list_tables()</span></strong></p></td> <td> <p>返回與簡單正則表達式匹配的表名。</p></td> </tr><tr><td> <p><strong> <span> mysql_more_results()</span></strong></p></td> <td> <p>檢查是否還存在其他結果。</p></td> </tr><tr><td> <p><strong> <span>mysql_next_result()</span></strong></p></td> <td> <p>在多語句執行過程中返回<span>/</span>初始化下一個結果。</p></td> </tr><tr><td> <p><strong> <span>mysql_num_fields()</span></strong></p></td> <td> <p>返回結果集中的列數。</p></td> </tr><tr><td> <p><strong> <span>mysql_num_rows()</span></strong></p></td> <td> <p>返回結果集中的行數。</p></td> </tr><tr><td> <p><strong> <span>mysql_options()</span></strong></p></td> <td> <p>為<span><span>mysql_connect()</span>設置連接選項。</span></p></td> </tr><tr><td> <p><strong> <span>mysql_ping()</span></strong></p></td> <td> <p>檢查與服務器的連接是否工作,如有必要重新連接。</p></td> </tr><tr><td> <p><strong> <span>mysql_query()</span></strong></p></td> <td> <p>執行指定為“以<span>Null</span>終結的字符串”的<span>SQL</span>查詢。</p></td> </tr><tr><td> <p><strong> <span> mysql_real_connect()</span></strong></p></td> <td> <p>連接到<span>MySQL</span>服務器。</p></td> </tr><tr><td> <p><strong> <span> mysql_real_escape_string()</span></strong></p></td> <td> <p>考慮到連接的當前字符集,為了在<span>SQL</span>語句中使用,對字符串中的特殊字符進行轉義處理。</p></td> </tr><tr><td> <p><strong> <span>mysql_real_query()</span></strong></p></td> <td> <p>執行指定為計數字符串的<span>SQL</span>查詢。</p></td> </tr><tr><td> <p><strong> <span>mysql_refresh()</span></strong></p></td> <td> <p>刷新或復位表和高速緩沖。</p></td> </tr><tr><td> <p><strong> <span>mysql_reload()</span></strong></p></td> <td> <p>通知服務器再次加載授權表。</p></td> </tr><tr><td> <p><strong> <span>mysql_rollback()</span></strong></p></td> <td> <p>回滾事務。</p></td> </tr><tr><td> <p><strong> <span>mysql_row_seek()</span></strong></p></td> <td> <p>使用從<span><span>mysql_row_tell()</span>返回的值,查找結果集中的行偏移。</span></p></td> </tr><tr><td> <p><strong> <span>mysql_row_tell()</span></strong></p></td> <td> <p>返回行光標位置。</p></td> </tr><tr><td> <p><strong> <span>mysql_select_db()</span></strong></p></td> <td> <p>選擇數據庫。</p></td> </tr><tr><td> <p><strong> <span>mysql_server_end()</span></strong></p></td> <td> <p>最終確定嵌入式服務器庫。</p></td> </tr><tr><td> <p><strong> <span>mysql_server_init()</span></strong></p></td> <td> <p>初始化嵌入式服務器庫。</p></td> </tr><tr><td> <p><strong> <span> mysql_set_server_option()</span></strong></p></td> <td> <p>為連接設置選項(如多語句)。</p></td> </tr><tr><td> <p><strong> <span>mysql_sqlstate()</span></strong></p></td> <td> <p>返回關于上一個錯誤的<span>SQLSTATE</span>錯誤代碼。</p></td> </tr><tr><td> <p><strong> <span>mysql_shutdown()</span></strong></p></td> <td> <p>關閉數據庫服務器。</p></td> </tr><tr><td> <p><strong> <span>mysql_stat()</span></strong></p></td> <td> <p>以字符串形式返回服務器狀態。</p></td> </tr><tr><td> <p><strong> <span> mysql_store_result()</span></strong></p></td> <td> <p>檢索完整的結果集至客戶端。</p></td> </tr><tr><td> <p><strong> <span>mysql_thread_id()</span></strong></p></td> <td> <p>返回當前線程<span>ID</span>。</p></td> </tr><tr><td> <p><strong> <span>mysql_thread_safe()</span></strong></p></td> <td> <p>如果客戶端已編譯為線程安全的,返回<span>1</span>。</p></td> </tr><tr><td> <p><strong> <span>mysql_use_result()</span></strong></p></td> <td> <p>初始化逐行的結果集檢索。</p></td> </tr><tr><td> <p><strong> <span> mysql_warning_count()</span></strong></p></td> <td> <p>返回上一個<span>SQL</span>語句的告警數。</p></td> </tr></table> 與MySQL交互時,應用程序應使用該一般性原則: 1.??? 通過調用mysql_library_init(),初始化MySQL庫。庫可以是mysqlclient C客戶端庫,或mysqld嵌入式服務器庫,具體情況取決于應用程序是否與“-libmysqlclient”或“-libmysqld”標志鏈接。 2.??? 通過調用mysql_init()初始化連接處理程序,并通過調用mysql_real_connect()連接到服務器。 3.??? 發出SQL語句并處理其結果。(在下面的討論中,詳細介紹了使用它的方法)。 4.??? 通過調用mysql_close(),關閉與MySQL服務器的連接。 5.??? 通過調用mysql_library_end(),結束MySQL庫的使用。 調用mysql_library_init()和mysql_library_end()的目的在于,為MySQL庫提供恰當的初始化和結束處理。對于與客戶端庫鏈接的應用程序,它們提供了改進的內存管理功能。如果不調用mysql_library_end(),內存塊仍將保持分配狀態(這不會增加應用程序使用的內存量,但某些內存泄漏檢測器將抗議它)。對于與嵌入式服務器鏈接的應用程序,這些調用會啟動并停止服務器。 mysql_library_init()和mysql_library_end()實際上是#define符號,這類符號使得它們等效于mysql_server_init()和mysql_server_end(),但其名稱更清楚地指明,無論應用程序使用的是mysqlclient或mysqld庫,啟動或結束MySQL庫時,應調用它們。對于早期的MySQL版本,可調用mysql_server_init()和mysql_server_end()取而代之。 如果愿意,可省略對mysql_library_init()的調用,這是因為,必要時,mysql_init()會自動調用它。 要想連接到服務器,可調用mysql_init()來初始化連接處理程序,然后用該處理程序(以及其他信息,如主機名、用戶名和密碼)調用mysql_real_connect()。建立連接后,在低于5.0.3版的API中,mysql_real_connect()會將再連接標志(MYSQL結構的一部分)設置為1,或在較新的版本中,將其設置為0。對于該標志,值“1”指明,如果因連接丟失而無法執行語句,放棄之前,會嘗試再次連接到服務器。從MySQL 5.0.13開始,可以在mysql_options()上使用MYSQL_OPT_RECONNECT選項,以控制再連接行為。完成連接后,調用mysql_close()中止它。 當連接處于活動狀態時,客戶端或許會使用mysql_query()或mysql_real_query()向服務器發出SQL查詢。兩者的差別在于,mysql_query()預期的查詢為指定的、由Null終結的字符串,而mysql_real_query()預期的是計數字符串。如果字符串包含二進制數據(其中可能包含Null字節),就必須使用mysql_real_query()。 對于每個非SELECT查詢(例如INSERT、UPDATE、DELETE),通過調用mysql_affected_rows(),可發現有多少行已被改變(影響)。 對于SELECT查詢,能夠檢索作為結果集的行。注意,某些語句因其返回行,類似與SELECT。包括SHOW、DESCRIBE和EXPLAIN。應按照對待SELECT語句的方式處理它們。 客戶端處理結果集的方式有兩種。一種方式是,通過調用mysql_store_result(),一次性地檢索整個結果集。該函數能從服務器獲得查詢返回的所有行,并將它們保存在客戶端。第二種方式是針對客戶端的,通過調用mysql_use_result(),對“按行”結果集檢索進行初始化處理。該函數能初始化檢索結果,但不能從服務器獲得任何實際行。 在這兩種情況下,均能通過調用mysql_fetch_row()訪問行。通過mysql_store_result(),mysql_fetch_row()能夠訪問以前從服務器獲得的行。通過mysql_use_result(),mysql_fetch_row()能夠實際地檢索來自服務器的行。通過調用mysql_fetch_lengths(),能獲得關于各行中數據大小的信息。 完成結果集操作后,請調用mysql_free_result()釋放結果集使用的內存。 這兩種檢索機制是互補的。客戶端程序應選擇最能滿足其要求的方法。實際上,客戶端最常使用的是mysql_store_result()。 mysql_store_result()的1個優點在于,由于將行全部提取到了客戶端上,你不僅能連續訪問行,還能使用mysql_data_seek()或mysql_row_seek()在結果集中向前或向后移動,以更改結果集內當前行的位置。通過調用mysql_num_rows(),還能發現有多少行。另一方面,對于大的結果集,mysql_store_result()所需的內存可能會很大,你很可能遇到內存溢出狀況。 mysql_use_result()的1個優點在于,客戶端所需的用于結果集的內存較少,原因在于,一次它僅維護一行(由于分配開銷較低,mysql_use_result()能更快)。它的缺點在于,你必須快速處理每一行以避免妨礙服務器,你不能隨機訪問結果集中的行(只能連續訪問行),你不知道結果集中有多少行,直至全部檢索了它們為止。不僅如此,即使在檢索過程中你判定已找到所尋找的信息,也必須檢索所有的行。 通過API,客戶端能夠恰當地對查詢作出響應(僅在必要時檢索行),而無需知道查詢是否是SELECT查詢。可以在每次mysql_query()或mysql_real_query()后,通過調用mysql_store_result()完成該操作。如果結果集調用成功,查詢為SELECT,而且能夠讀取行。如果結果集調用失敗,可調用mysql_field_count()來判斷結果是否的確是所預期的。如果mysql_field_count()返回0,查詢不返回數據(表明它是INSERT、UPDATE、DELETE等),而且不返回行。如果mysql_field_count()是非0值,查詢應返回行,但沒有返回行。這表明查詢是失敗了的SELECT。關于如何實現該操作的示例,請參見關于mysql_field_count()的介紹。 無論是mysql_store_result()還是mysql_use_result(),均允許你獲取關于構成結果集的字段的信息(字段數目,它們的名稱和類型等)。通過重復調用mysql_fetch_field(),可以按順序訪問行內的字段信息,或者,通過調用mysql_fetch_field_direct(),能夠在行內按字段編號訪問字段信息。通過調用mysql_field_seek(),可以改變當前字段的光標位置。對字段光標的設置將影響后續的mysql_fetch_field()調用。此外,你也能通過調用mysql_fetch_fields(),一次性地獲得關于字段的所有信息。 為了檢測和通報錯誤,MySQL提供了使用mysql_errno()和mysql_error()函數訪問錯誤信息的機制。它們能返回關于最近調用的函數的錯誤代碼或錯誤消息,最近調用的函數可能成功也可能失敗,這樣,你就能判斷錯誤是在何時出現的,以及錯誤是什么。 ### 25.2.3.?C API函數描述 [25.2.3.1. mysql_affected_rows()](#)[25.2.3.2. mysql_autocommit()](#)[25.2.3.3. mysql_change_user()](#)[25.2.3.4. mysql_character_set_name()](#)[25.2.3.5. mysql_close()](#)[25.2.3.6. mysql_commit()](#)[25.2.3.7. mysql_connect()](#)[25.2.3.8. mysql_create_db()](#)[25.2.3.9. mysql_data_seek()](#)[25.2.3.10. mysql_debug()](#)[25.2.3.11. mysql_drop_db()](#)[25.2.3.12. mysql_dump_debug_info()](#)[25.2.3.13. mysql_eof()](#)[25.2.3.14. mysql_errno()](#)[25.2.3.15. mysql_error()](#)[25.2.3.16. mysql_escape_string()](#)[25.2.3.17. mysql_fetch_field()](#)[25.2.3.18. mysql_fetch_field_direct()](#)[25.2.3.19. mysql_fetch_fields()](#)[25.2.3.20. mysql_fetch_lengths()](#)[25.2.3.21. mysql_fetch_row()](#)[25.2.3.22. mysql_field_count()](#)[25.2.3.23. mysql_field_seek()](#)[25.2.3.24. mysql_field_tell()](#)[25.2.3.25. mysql_free_result()](#)[25.2.3.26. mysql_get_character_set_info()](#)[25.2.3.27. mysql_get_client_info()](#)[25.2.3.28. mysql_get_client_version()](#)[25.2.3.29. mysql_get_host_info()](#)[25.2.3.30. mysql_get_proto_info()](#)[25.2.3.31. mysql_get_server_info()](#)[25.2.3.32. mysql_get_server_version()](#)[25.2.3.33. mysql_hex_string()](#)[25.2.3.34. mysql_info()](#)[25.2.3.35. mysql_init()](#)[25.2.3.36. mysql_insert_id()](#)[25.2.3.37. mysql_kill()](#)[25.2.3.38. mysql_library_end()](#)[25.2.3.39. mysql_library_init()](#)[25.2.3.40. mysql_list_dbs()](#)[25.2.3.41. mysql_list_fields()](#)[25.2.3.42. mysql_list_processes()](#)[25.2.3.43. mysql_list_tables()](#)[25.2.3.44. mysql_more_results()](#)[25.2.3.45. mysql_next_result()](#)[25.2.3.46. mysql_num_fields()](#)[25.2.3.47. mysql_num_rows()](#)[25.2.3.48. mysql_options()](#)[25.2.3.49. mysql_ping()](#)[25.2.3.50. mysql_query()](#)[25.2.3.51. mysql_real_connect()](#)[25.2.3.52. mysql_real_escape_string()](#)[25.2.3.53. mysql_real_query()](#)[25.2.3.54. mysql_refresh()](#)[25.2.3.55. mysql_reload()](#)[25.2.3.56. mysql_rollback()](#)[25.2.3.57. mysql_row_seek()](#)[25.2.3.58. mysql_row_tell()](#)[25.2.3.59. mysql_select_db()](#)[25.2.3.60. mysql_set_character_set()](#)[25.2.3.61. mysql_set_server_option()](#)[25.2.3.62. mysql_shutdown()](#)[25.2.3.63. mysql_sqlstate()](#)[25.2.3.64. mysql_ssl_set()](#)[25.2.3.65. mysql_stat()](#)[25.2.3.66. mysql_store_result()](#)[25.2.3.67. mysql_thread_id()](#)[25.2.3.68. mysql_use_result()](#)[25.2.3.69. mysql_warning_count()](#) 在本節所作的介紹中,按照C編程語言,為NULL的參數或返回值表示NULL,而不是MySQL Null值。 返回值的函數通常會返回指針或整數。除非作了其他規定,返回指針的函數將返回非Null值,以指明成功,或返回NULL值以指明出錯。返回整數的函數將返回0以指明成功,或返回非0值以指明出錯。注意,非0值僅表明這點。除非在函數描述中作了其他說明,不要對非0值進行測試: ~~~ if (result)?????????????????? /* correct */ ~~~ ~~~ ??? ... error ... ~~~ ~~~ ? ~~~ ~~~ if (result < 0)?????????????? /* incorrect */ ~~~ ~~~ ??? ... error ... ~~~ ~~~ ? ~~~ ~~~ if (result == -1)???????????? /* incorrect */ ~~~ ~~~ ??? ... error ... ~~~ 當函數返回錯誤時,在函數描述的“錯誤”部分將列出可能的錯誤類型。通過調用mysql_errno()可發現出現的錯誤是什么。通過調用mysql_error(),可獲得錯誤的字符串表示。 #### 25.2.3.1.?mysql_affected_rows() my_ulonglong mysql_affected_rows(MYSQL *mysql) **描述** 返回上次UPDATE更改的行數,上次DELETE刪除的行數,或上次INSERT語句插入的行數。對于UPDATE、DELETE或INSERT語句,可在mysql_query()后立刻調用。對于SELECT語句,mysql_affected_rows()的工作方式與mysql_num_rows()類似。 **返回值** 大于0的整數表明受影響或檢索的行數。“0”表示UPDATE語句未更新記錄,在查詢中沒有與WHERE匹配的行,或未執行查詢。“-1”表示查詢返回錯誤,或者,對于SELECT查詢,在調用mysql_store_result()之前調用了mysql_affected_rows()。由于mysql_affected_rows()返回無符號值,通過比較返回值和“(my_ulonglong)-1”或等效的“(my_ulonglong)~0”,檢查是否為“-1”。 **錯誤** 無。 **示例:** ~~~ mysql_query(&mysql,"UPDATE products SET cost=cost*1.25 WHERE group=10"); ~~~ ~~~ printf("%ld products updated",(long) mysql_affected_rows(&mysql)); ~~~ 如果在連接至**mysqld**時指定了標志CLIENT_FOUND_ROWS,對于UPDATE語句,mysql_affected_rows()將返回WHERE語句匹配的行數。 注意,使用REPLACE命令時,如果新行替代了舊行,mysql_affected_rows()返回2。這是因為,在該情況下,刪除了重復行后插入了1行。 如果使用“INSERT ... ON DUPLICATE KEY UPDATE”來插入行,如果行是作為新行插入的,mysql_affected_rows()返回1,如果是更新了已有的行,返回2。 #### 25.2.3.2.?mysql_autocommit() my_bool mysql_autocommit(MYSQL *mysql, my_bool mode) **描述** 如果模式為“1”,啟用autocommit模式;如果模式為“0”,禁止autocommit模式。 **返回值** 如果成功,返回0,如果出現錯誤,返回非0值。 **錯誤** 無。 #### 25.2.3.3.?mysql_change_user() my_bool mysql_change_user(MYSQL *mysql, const char *user, const char *password, const char *db) **描述** 更改用戶,并使由db指定的數據庫成為由mysql指定的連接上的默認數據庫(當前數據庫)。在后續查詢中,對于不包含顯式數據庫區分符的表引用,該數據庫是默認數據庫。 如果不能確定已連接的用戶或用戶不具有使用數據庫的權限,mysql_change_user()將失敗。在這種情況下,不會改變用戶和數據庫。 如果不打算擁有默認數據庫,可將db參數設置為NULL。 該命令總是會執行活動事務的ROLLBACK操作,關閉所有的臨時表,解鎖所有的鎖定表,并復位狀態,就像進行了新連接那樣。即使未更改用戶,也會出現該情況。 **返回值** 0表示成功,非0值表示出現錯誤。 **錯誤** 與從mysql_real_connect()獲得的相同。 ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中丟失了與服務器的連接。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 ·???????? ER_UNKNOWN_COM_ERROR MySQL服務器未實施該命令(或許是較低版本的服務器)。 ·???????? ER_ACCESS_DENIED_ERROR 用戶或密碼錯誤。 ·???????? ER_BAD_DB_ERROR 數據庫不存在。 ·???????? ER_DBACCESS_DENIED_ERROR 用戶沒有訪問數據庫的權限。 ·???????? ER_WRONG_DB_NAME 數據庫名稱過長。 **示例:** ~~~ if (mysql_change_user(&mysql, "user", "password", "new_database")) ~~~ ~~~ { ~~~ ~~~ ?? fprintf(stderr, "Failed to change user.? Error: %s\n", ~~~ ~~~ ?????????? mysql_error(&mysql)); ~~~ ~~~ } ~~~ #### 25.2.3.4.?mysql_character_set_name() const char *mysql_character_set_name(MYSQL *mysql) **描述** 為當前連接返回默認的字符集。 **返回值** 默認字符集。 **錯誤** 無。 #### 25.2.3.5.?mysql_close() void mysql_close(MYSQL *mysql) **描述** 關閉前面打開的連接。如果句柄是由mysql_init()或mysql_connect()自動分配的,mysql_close()還將解除分配由mysql指向的連接句柄。 **返回值** 無。 **錯誤** 無。 #### 25.2.3.6.?mysql_commit() my_bool mysql_commit(MYSQL *mysql) **描述** 提交當前事務。 該函數的動作受completion_type系統變量的值控制。尤其是,如果completion_type的值為2,終結事務并關閉客戶端連接后,服務器將執行釋放操作。客戶端程序應調用mysql_close(),從客戶端一側關閉連接。 **返回值** 如果成功,返回0,如果出現錯誤,返回非0值。 **錯誤** 無。 #### 25.2.3.7.?mysql_connect() MYSQL *mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd) **描述** 該函數已過時。最好使用mysql_real_connect()取而代之。 mysql_connect()試圖建立與運行在主機上的MySQL數據庫引擎的連接。在能夠執行任何其他API函數之前,mysql_connect()必須成功完成,但mysql_get_client_info()例外。 這些參數的意義與mysql_real_connect()的對應參數的意義相同,差別在于連接參數可以為NULL。在這種情況下,C API將自動為連接結構分配內存,并當調用mysql_close()時釋放分配的內存。該方法的缺點是,如果連接失敗,你無法檢索錯誤消息。要想從mysql_errno()或mysql_error()獲得錯誤消息,必須提供有效的MYSQL指針。 **返回值** 與mysql_real_connect()的相同。 **錯誤** 與mysql_real_connect()的相同。 #### 25.2.3.8.?mysql_create_db() int mysql_create_db(MYSQL *mysql, const char *db) **描述** 創建由db參數命名的數據庫。 該函數已過時。最好使用mysql_query()來發出SQL CREATE DATABASE語句。 **返回值** 如果數據庫已成功創建,返回0,如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 **示例:** ~~~ if(mysql_create_db(&mysql, "my_database")) ~~~ ~~~ { ~~~ ~~~ ?? fprintf(stderr, "Failed to create new database.? Error: %s\n", ~~~ ~~~ ?????????? mysql_error(&mysql)); ~~~ ~~~ } ~~~ #### 25.2.3.9.?mysql_data_seek() void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset) **描述** 在查詢結果集中尋找任意行。偏移值為行號,范圍從0到mysql_num_rows(result)-1。 該函數要求結果集結構包含查詢的所有結果,因此,so mysql_data_seek()僅應與mysql_store_result()聯合使用,而不是與mysql_use_result()。 **返回值** 無。 **錯誤** 無。 #### 25.2.3.10.?mysql_debug() void mysql_debug(const char *debug) **描述** 用給定的字符串執行DBUG_PUSH。mysql_debug()采用Fred Fish調試庫。要想使用該函數,必須編譯客戶端庫,使之支持調試功能。請參見[E.1節,“調試MySQL服務器”](# "E.1.?Debugging a MySQL Server")。請參見[E.2節,“調試MySQL客戶端”](# "E.2.?Debugging a MySQL Client")。 **返回值** 無。 **錯誤** 無。 **示例:** 這里給出的調用將使客戶端庫在客戶端機器的/tmp/client.trace中生成1個跟蹤文件。 ~~~ mysql_debug("d:t:O,/tmp/client.trace"); ~~~ #### 25.2.3.11.?mysql_drop_db() int mysql_drop_db(MYSQL *mysql, const char *db) **描述** 撤銷由db參數命名數據庫。 該函數已過時。最好使用mysql_query()來發出SQL DROP DATABASE語句 **返回值** 如果成功撤銷了數據庫,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 **示例:** ~~~ if(mysql_drop_db(&mysql, "my_database")) ~~~ ~~~ ? fprintf(stderr, "Failed to drop the database: Error: %s\n", ~~~ ~~~ ????????? mysql_error(&mysql)); ~~~ #### 25.2.3.12.?mysql_dump_debug_info() int mysql_dump_debug_info(MYSQL *mysql) **描述** 指示服務器將一些調試信息寫入日志。要想使之工作,已連接的用戶必須具有SUPER權限。 **返回值** 如果命令成功,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.13.?mysql_eof() my_bool mysql_eof(MYSQL_RES *result) **描述** 該函數已過時。應使用mysql_errno()或mysql_error()取而代之。 mysql_eof()確定是否已讀取了結果集的最后1行。 如果通過成功調用mysql_store_result()獲得了結果集,客戶端將在1次操作中收到整個結果集。在該情況下,從mysql_fetch_row()返回的NULL總表示已到達結果集末尾,而且沒必要調用mysql_eof()。與mysql_store_result()一起使用時,mysql_eof()總返回“真”。 另一方面,如果你使用mysql_use_result()來初始化結果集檢索,當重復調用mysql_fetch_row()時,將逐個地從服務器獲取結果集的行。由于在該過程中,可能出現連接上的錯誤,從mysql_fetch_row()返回的NULL值不一定表示已正常地抵達結果集末尾。在該情況下,可以使用mysql_eof()來判定出現了什么情況。如果抵達結果集末尾,mysql_eof()返回非0值,如果出現錯誤,返回0。 從歷史的角度上看,mysql_eof()在日期上早于標準的MySQL錯誤函數mysql_errno()和mysql_error()。由于這類錯誤函數提供了相同的信息,它們優先于已過時的mysql_eof()。事實上,它們提供了更多信息,這是因為,mysql_eof()僅返回布爾值,錯誤函數能夠在出現錯誤時指明錯誤的原因。 **返回值** 如果未出現錯誤,返回0。如果抵達結果集的末尾,返回非0值。 **錯誤** 無。 **示例:** 在下面的示例中,介紹了使用mysql_eof()的方法: ~~~ mysql_query(&mysql,"SELECT * FROM some_table"); ~~~ ~~~ result = mysql_use_result(&mysql); ~~~ ~~~ while((row = mysql_fetch_row(result))) ~~~ ~~~ { ~~~ ~~~ ??? // do something with data ~~~ ~~~ } ~~~ ~~~ if(!mysql_eof(result))? // mysql_fetch_row() failed due to an error ~~~ ~~~ { ~~~ ~~~ ??? fprintf(stderr, "Error: %s\n", mysql_error(&mysql)); ~~~ ~~~ } ~~~ 但是,你也能使用標準的MySQL錯誤函數實現相同的結果: ~~~ mysql_query(&mysql,"SELECT * FROM some_table"); ~~~ ~~~ result = mysql_use_result(&mysql); ~~~ ~~~ while((row = mysql_fetch_row(result))) ~~~ ~~~ { ~~~ ~~~ ??? // do something with data ~~~ ~~~ } ~~~ ~~~ if(mysql_errno(&mysql))? // mysql_fetch_row() failed due to an error ~~~ ~~~ { ~~~ ~~~ ??? fprintf(stderr, "Error: %s\n", mysql_error(&mysql)); ~~~ ~~~ } ~~~ #### 25.2.3.14.?mysql_errno() unsigned int mysql_errno(MYSQL *mysql) **描述** 對于由mysql指定的連接,mysql_errno()返回最近調用的API函數的錯誤代碼,該函數調用可能成功也可能失敗。“0”返回值表示未出現錯誤。在MySQL errmsg.h頭文件中,列出了客戶端錯誤消息編號。在[附錄B:](#)[*錯誤代碼和消息*](# "Appendix?B.?Error Codes and Messages")中,也列出了這些錯誤。 注意,如果成功,某些函數,如mysql_fetch_row()等,不會設置mysql_errno()。 經驗規則是,如果成功,所有向服務器請求信息的函數均會復位mysql_errno()。 **返回值** 如果失敗,返回上次mysql_*xxx*()調用的錯誤代碼。“0”表示未出現錯誤。 **錯誤** 無。 #### 25.2.3.15.?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節,“設置錯誤消息語言”](# "5.10.2.?Setting the Error Message Language")。 **返回值** 返回描述錯誤的、由Null終結的字符串。如果未出現錯誤,返回空字符串。 **錯誤** 無。 #### 25.2.3.16.?mysql_escape_string() 應使用mysql_real_escape_string()取而代之! 該函數與mysql_real_escape_string()等同,但mysql_real_escape_string()會將連接處理程序作為其第1個參量,并按照當前字符集對字符串進行轉義處理。mysql_escape_string()不采用連接參量,而且不考慮當前字符集設置。 #### 25.2.3.17.?mysql_fetch_field() MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result) **描述** 返回采用MYSQL_FIELD結構的結果集的列。重復調用該函數,以檢索關于結果集中所有列的信息。未剩余字段時,mysql_fetch_field()返回NULL。 每次執行新的SELECT查詢時,將復位mysql_fetch_field(),以返回關于第1個字段的信息。調用mysql_field_seek()也會影響mysql_fetch_field()返回的字段。 如果調用了mysql_query()以在表上執行SELECT,但未調用mysql_store_result(),如果調用了mysql_fetch_field()以請求BLOB字段的長度,MySQL將返回默認的Blob長度(8KB)。之所以選擇8KB是因為MySQL不知道BLOB的最大長度。應在日后使其成為可配置的。一旦檢索了結果集,field->max_length將包含特定查詢中該列的最大值的長度。 **返回值** 當前列的MYSQL_FIELD結構。如果未剩余任何列,返回NULL。 **錯誤** 無。 **示例:** ~~~ MYSQL_FIELD *field; ~~~ ~~~ ? ~~~ ~~~ while((field = mysql_fetch_field(result))) ~~~ ~~~ { ~~~ ~~~ ??? printf("field name %s\n", field->name); ~~~ ~~~ } ~~~ #### 25.2.3.18.?mysql_fetch_field_direct() MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *result, unsigned int fieldnr) **描述** 給定結果集內某1列的字段編號fieldnr,以MYSQL_FIELD結構形式返回列的字段定義。可以使用該函數檢索任意列的定義。Fieldnr的值應在從0到mysql_num_fields(result)-1的范圍內。 **返回值** 對于指定列,返回MYSQL_FIELD結構。 **錯誤** 無。 **示例:** ~~~ unsigned int num_fields; ~~~ ~~~ unsigned int i; ~~~ ~~~ MYSQL_FIELD *field; ~~~ ~~~ ? ~~~ ~~~ num_fields = mysql_num_fields(result); ~~~ ~~~ for(i = 0; i < num_fields; i++) ~~~ ~~~ { ~~~ ~~~ ??? field = mysql_fetch_field_direct(result, i); ~~~ ~~~ ??? printf("Field %u is %s\n", i, field->name); ~~~ ~~~ } ~~~ #### 25.2.3.19.?mysql_fetch_fields() MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result) **描述** 對于結果集,返回所有MYSQL_FIELD結構的數組。每個結構提供了結果集中1列的字段定義。 **返回值** 關于結果集所有列的MYSQL_FIELD結構的數組。 **錯誤** 無。 **示例:** ~~~ unsigned int num_fields; ~~~ ~~~ unsigned int i; ~~~ ~~~ MYSQL_FIELD *fields; ~~~ ~~~ ? ~~~ ~~~ num_fields = mysql_num_fields(result); ~~~ ~~~ fields = mysql_fetch_fields(result); ~~~ ~~~ for(i = 0; i < num_fields; i++) ~~~ ~~~ { ~~~ ~~~ ?? printf("Field %u is %s\n", i, fields[i].name); ~~~ ~~~ } ~~~ #### 25.2.3.20.?mysql_fetch_lengths() unsigned long *mysql_fetch_lengths(MYSQL_RES *result) **描述** 返回結果集內當前行的列的長度。如果打算復制字段值,該長度信息有助于優化,這是因為,你能避免調用strlen()。此外,如果結果集包含二進制數據,必須使用該函數來確定數據的大小,原因在于,對于包含Null字符的任何字段,strlen()將返回錯誤的結果。 對于空列以及包含NULL值的列,其長度為0。要想了解區分這兩類情況的方法,請參見關于mysql_fetch_row()的介紹。 **返回值** 無符號長整數的數組表示各列的大小(不包括任何終結NULL字符)。如果出現錯誤,返回NULL。 **錯誤** mysql_fetch_lengths()僅對結果集的當前行有效。如果在調用mysql_fetch_row()之前或檢索了結果集中的所有行后調用了它,將返回NULL。 **示例:** ~~~ MYSQL_ROW row; ~~~ ~~~ unsigned long *lengths; ~~~ ~~~ unsigned int num_fields; ~~~ ~~~ unsigned int i; ~~~ ~~~ ? ~~~ ~~~ row = mysql_fetch_row(result); ~~~ ~~~ if (row) ~~~ ~~~ { ~~~ ~~~ ??? num_fields = mysql_num_fields(result); ~~~ ~~~ ??? lengths = mysql_fetch_lengths(result); ~~~ ~~~ ??? for(i = 0; i < num_fields; i++) ~~~ ~~~ ??? { ~~~ ~~~ ???????? printf("Column %u is %lu bytes in length.\n", i, lengths[i]); ~~~ ~~~ ??? } ~~~ ~~~ } ~~~ #### 25.2.3.21.?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_ROW row; ~~~ ~~~ unsigned int num_fields; ~~~ ~~~ unsigned int i; ~~~ ~~~ ? ~~~ ~~~ num_fields = mysql_num_fields(result); ~~~ ~~~ while ((row = mysql_fetch_row(result))) ~~~ ~~~ { ~~~ ~~~ ?? unsigned long *lengths; ~~~ ~~~ ?? lengths = mysql_fetch_lengths(result); ~~~ ~~~ ?? for(i = 0; i < num_fields; i++) ~~~ ~~~ ?? { ~~~ ~~~ ?????? printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL"); ~~~ ~~~ ?? } ~~~ ~~~ ?? printf("\n"); ~~~ ~~~ } ~~~ #### 25.2.3.22.?mysql_field_count() unsigned int mysql_field_count(MYSQL *mysql) **描述** 返回作用在連接上的最近查詢的列數。 該函數的正常使用是在mysql_store_result()返回NULL(因而沒有結果集指針)時。在這種情況下,可調用mysql_field_count()來判定mysql_store_result()是否應生成非空結果。這樣,客戶端就能采取恰當的動作,而無需知道查詢是否是SELECT(或類似SELECT的)語句。在這里給出的示例中,演示了完成它的方法。 請參見[25.2.13.1節,“為什么在mysql_query()返回成功后,mysql_store_result()有時會返回NULL``”](# "25.2.13.1.?Why mysql_store_result() Sometimes Returns NULL After mysql_query() Returns Success"). **返回值** 表示結果集中列數的無符號整數。 **錯誤** 無。 **示例:** ~~~ MYSQL_RES *result; ~~~ ~~~ unsigned int num_fields; ~~~ ~~~ unsigned int num_rows; ~~~ ~~~ ? ~~~ ~~~ if (mysql_query(&mysql,query_string)) ~~~ ~~~ { ~~~ ~~~ ??? // error ~~~ ~~~ } ~~~ ~~~ else // query succeeded, process any data returned by it ~~~ ~~~ { ~~~ ~~~ ??? result = mysql_store_result(&mysql); ~~~ ~~~ ??? if (result)? // there are rows ~~~ ~~~ ??? { ~~~ ~~~ ??????? num_fields = mysql_num_fields(result); ~~~ ~~~ ??????? // retrieve rows, then call mysql_free_result(result) ~~~ ~~~ ? ??} ~~~ ~~~ ??? else? // mysql_store_result() returned nothing; should it have? ~~~ ~~~ ??? { ~~~ ~~~ ??????? if(mysql_field_count(&mysql) == 0) ~~~ ~~~ ??????? { ~~~ ~~~ ??????????? // query does not return data ~~~ ~~~ ??????????? // (it was not a SELECT) ~~~ ~~~ ??????????? num_rows = mysql_affected_rows(&mysql); ~~~ ~~~ ??????? } ~~~ ~~~ ??????? else // mysql_store_result() should have returned data ~~~ ~~~ ??????? { ~~~ ~~~ ??????????? fprintf(stderr, "Error: %s\n", mysql_error(&mysql)); ~~~ ~~~ ??????? } ~~~ ~~~ ??? } ~~~ ~~~ } ~~~ 另一種可選的方法是,用mysql_errno(&mysql)替換mysql_field_count(&mysql)調用。在該情況下,無論語句是否是SELECT,你將直接從mysql_store_result()查找錯誤,而不是從mysql_field_count()的值進行推斷。 #### 25.2.3.23.?mysql_field_seek() MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset) **描述** 將字段光標設置到給定的偏移處。對mysql_fetch_field()的下一次調用將檢索與該偏移相關的列定義。 要想查找行的開始,請傳遞值為0的偏移量。 **返回值** 字段光標的前一個值。 **錯誤** 無。 #### 25.2.3.24.?mysql_field_tell() MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES *result) **描述** 返回上一個mysql_fetch_field()所使用的字段光標的定義。該值可用作mysql_field_seek()的參量。 **返回值** 字段光標的當前偏移量。 **錯誤** 無。 #### 25.2.3.25.?mysql_free_result() void mysql_free_result(MYSQL_RES *result) **描述** 釋放由mysql_store_result()、mysql_use_result()、mysql_list_dbs()等為結果集分配的內存。完成對結果集的操作后,必須調用mysql_free_result()釋放結果集使用的內存。 釋放完成后,不要嘗試訪問結果集。 **返回值** 無。 **錯誤** 無。 #### 25.2.3.26.?mysql_get_character_set_info() void mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs) **描述** 該函數提供了關于默認客戶端字符集的信息。可以使用mysql_set_character_set()函數更改默認的字符集。 該函數是在MySQL 5.0.10中增加的。 **示例:** ~~~ if (!mysql_set_character_set(&mysql, "utf8")) ~~~ ~~~ { ~~~ ~~~ ??? MY_CHARSET_INFO cs; ~~~ ~~~ ??? mysql_get_character_set_info(&mysql, &cs); ~~~ ~~~ ??? printf("character set information:\n"); ~~~ ~~~ ??? printf("character set name: %s\n", cs.name); ~~~ ~~~ ??? printf("collation name: %s\n", cs.csname); ~~~ ~~~ ??? printf("comment: %s\n", cs.comment); ~~~ ~~~ ??? printf("directory: %s\n", cs.dir); ~~~ ~~~ ??? printf("multi byte character min. length: %d\n", cs.mbminlen); ~~~ ~~~ ??? printf("multi byte character max. length: %d\n", cs.mbmaxlen); ~~~ ~~~ } ~~~ #### 25.2.3.27.?mysql_get_client_info() char *mysql_get_client_info(void) **描述** 返回表示客戶端庫版本的字符串。 **返回值** 表示MySQL客戶端庫版本的字符串。 **錯誤** 無。 #### 25.2.3.28.?mysql_get_client_version() unsigned long mysql_get_client_version(void) **描述** 返回表示客戶端庫版本的整數。該值的格式是XYYZZ,其中X是主版本號,YY是發布級別,ZZ是發布級別內的版本號。例如,值40102表示客戶端庫的版本是4.1.2。 **返回值** 表示MySQL客戶端庫版本的整數。 **錯誤** 無。 #### 25.2.3.29.?mysql_get_host_info() char *mysql_get_host_info(MYSQL *mysql) **描述** 返回描述了所使用連接類型的字符串,包括服務器主機名。 **返回值** 代表服務器主機名和連接類型的字符串。 **錯誤** 無。 #### 25.2.3.30.?mysql_get_proto_info() unsigned int mysql_get_proto_info(MYSQL *mysql) **描述** 返回當前連接所使用的協議版本。 **返回值** 代表當前連接所使用協議版本的無符號整數。 **錯誤** 無。 #### 25.2.3.31.?mysql_get_server_info() char *mysql_get_server_info(MYSQL *mysql) **描述** 返回代表服務器版本號的字符串。 **返回值** 代表服務器版本號的字符串。 **錯誤** 無。 #### 25.2.3.32.?mysql_get_server_version() unsigned long mysql_get_server_version(MYSQL *mysql) **描述** 以整數形式返回服務器的版本號。 **返回值** 表示MySQL服務器版本的數值,格式如下: ~~~ major_version*10000 + minor_version *100 + sub_version ~~~ 例如,對于5.0.12,返回500012。 在客戶端程序中,為了快速確定某些與版本相關的服務器功能是否存在,該函數很有用。 **錯誤** 無。 #### 25.2.3.33.?mysql_hex_string() unsigned long mysql_hex_string(char *to, const char *from, unsigned long length) **描述** 該函數用于創建可用在SQL語句中的合法SQL字符串。請參見[9.1.1節,“字符串”](# "9.1.1.?Strings")。 該字符串從形式上編碼為十六進制格式,每個字符編碼為2個十六進制數。結果被置入其中,并添加1個終結Null字節。 “from”所指向的字符串必須是長度字節“long”。必須為“to”分配緩沖區,緩沖區至少為length*2+1字節長。當mysql_hex_string()返回時,“to”的內容為由Null終結的字符串。返回值是編碼字符串的長度,不包括終結用Null字符。 可采用0x*value*或X'*value*'格式將返回值置于SQL語句中。但是,返回值不包括0x或X'...'。調用者必須提供所希望的格式是何種。 **示例:** ~~~ char query[1000],*end; ~~~ ~~~ ? ~~~ ~~~ end = strmov(query,"INSERT INTO test_table values("); ~~~ ~~~ end = strmov(end,"0x"); ~~~ ~~~ end += mysql_hex_string(end,"What's this",11); ~~~ ~~~ end = strmov(end,",0x"); ~~~ ~~~ end += mysql_hex_string(end,"binary data: \0\r\n",16); ~~~ ~~~ *end++ = ')'; ~~~ ~~~ ? ~~~ ~~~ if (mysql_real_query(&mysql,query,(unsigned int) (end - query))) ~~~ ~~~ { ~~~ ~~~ ?? fprintf(stderr, "Failed to insert row, Error: %s\n", ~~~ ~~~ ?????????? mysql_error(&mysql)); ~~~ ~~~ } ~~~ 示例中所使用的strmov()函數包含在mysqlclient庫中,它的工作方式類似于strcpy(),但返回指向第1個參數終結Null的指針。 **返回值** 置于“to”中的值的長度,不包括終結用Null字符。 **錯誤** 無。 #### 25.2.3.34.?mysql_info() char *mysql_info(MYSQL *mysql) **描述** 檢索字符串,該字符串提供了關于最近執行查詢的信息,但僅對這里列出的語句有效。對于其他語句,mysql_info()返回NULL。字符串的格式取決于查詢的類型,如本節所述。數值僅是說明性的,字符串包含與查詢相適應的值。 ·???????? INSERT INTO ... SELECT ... 字符串格式:記錄,100;副本,0;警告,0 ·???????? INSERT INTO ... VALUES (...),(...),(...)... 字符串格式:記錄,3;副本,0;警告,0 ·???????? LOAD DATA INFILE ... 字符串格式:記錄,1;刪除,0;跳過,0;警告,0 ·???????? ALTER TABLE 字符串格式:記錄,3;副本,0;警告,0 ·???????? UPDATE 字符串格式:匹配行,40;更改,40;警告,0 注意,mysql_info()為INSERT ... VALUES返回非NULL值,INSERT ... VALUES僅用于多行形式的語句(也就是說,僅當指定了多個值列表時)。 **返回值** 字符串,它表示最近所執行查詢的額外信息。如果該查詢無可用信息,返回NULL。 **錯誤** 無。 #### 25.2.3.35.?mysql_init() MYSQL *mysql_init(MYSQL *mysql) **描述** 分配或初始化與mysql_real_connect()相適應的MYSQL對象。如果mysql是NULL指針,該函數將分配、初始化、并返回新對象。否則,將初始化對象,并返回對象的地址。如果mysql_init()分配了新的對象,當調用mysql_close()來關閉連接時。將釋放該對象。 **返回值** 初始化的MYSQL*句柄。如果無足夠內存以分配新的對象,返回NULL。 **錯誤** 在內存不足的情況下,返回NULL。 #### 25.2.3.36.?mysql_insert_id() my_ulonglong mysql_insert_id(MYSQL *mysql) **描述** 返回由以前的INSERT或UPDATE語句為AUTO_INCREMENT列生成的值。在包含AUTO_INCREMENT字段的表中執行了INSERT語句后,應使用該函數。 更準確地講,將在下述條件下更新mysql_insert_id(): ·???????? 將值保存到AUTO_INCREMENT列中的INSERT語句。無論值是通過在列中存儲特殊值NULL或0自動生成的,還是確切的非特殊值,都成立。 ·???????? 在有多行INSERT語句的情況下,mysql_insert_id()返回第1個自動生成的AUTO_INCREMENT值,如果未生成這類值,將返回插入在AUTO_INCREMENT列中的最后1個確切值。 ·???????? 通過將LAST_INSERT_ID(*expr*)插入到任意列中以生成AUTO_INCREMENT值的INSERT語句。 ·???????? 通過更新任意列至LAST_INSERT_ID(*expr*)以生成AUTO_INCREMENT值的INSERT語句。 ·???????? mysql_insert_id()的值不受諸如SELECT等返回結果集的語句的影響。 ·???????? 如果前面的語句返回了錯誤,mysql_insert_id()的值將是不確定的。 注意,如果前面的語句未使用AUTO_INCREMENT,mysql_insert_id()返回0。如果需要保存值,在生成值的語句后,務必立刻調用mysql_insert_id()。 mysql_insert_id()的值僅受在當前客戶端連接內發出的語句的影響。不受由其他客戶端發出的語句的影響。 請參見[12.9.3節,“信息函數”](# "12.9.3.?Information Functions")。 此外還應注意,SQL LAST_INSERT_ID()函數的值總包含最近生成的AUTO_INCREMENT值,而且在語句之間不會被復位,原因在于該函數的值是在服務器中維護的。另一個區別是,如果設置了AUTO_INCREMENT列來指定非特殊值,不會更新LAST_INSERT_ID()。 LAST_INSERT_ID()不同于mysql_insert_id()的原因在于,LAST_INSERT_ID()在腳本中很容易使用,而mysql_insert_id()則試圖提供關于在AUTO_INCREMENT列中出現情況的更準確信息。 **返回值** 在前面的討論中予以了介紹。 **錯誤** 無。 #### 25.2.3.37.?mysql_kill() int mysql_kill(MYSQL *mysql, unsigned long pid) **描述** 請求服務器殺死由pid指定的線程。 **返回值** 0表示成功,非0值表示出現錯誤。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.38.?mysql_library_end() void mysql_library_end(void) **描述** 它是mysql_server_end()函數的同義詞。 關于具體的用法,請參見[25.2.2節,“C API函數概述”](# "25.2.2.?C API Function Overview")。 #### 25.2.3.39.?mysql_library_init() int mysql_library_init(int argc, char **argv, char **groups) **描述** 這是mysql_server_init()函數的同義詞。 關于具體的用法,請參見[25.2.2節,“C API函數概述”](# "25.2.2.?C API Function Overview")。 #### 25.2.3.40.?mysql_list_dbs() MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild) **描述** 返回由服務器上的數據庫名稱組成的結果集,該服務器與由通配符參數指定的簡單正則表達式匹配。通配符參數可以包含通配符“%”或“_”,也可以是NULL指針,以便與所有的數據庫匹配。調用mysql_list_dbs()的方法類似于執行查詢SHOW database [LIKE wild]。 必須用mysql_free_result()釋放結果集。 **返回值** 成功后返回MYSQL_RES結果集。如果出現錯誤,返回NULL。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_OUT_OF_MEMORY 內存溢出。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.41.?mysql_list_fields() MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table, const char *wild) **描述** 返回由給定表中的字段名稱組成的結果集,給定表與由通配符參數指定的簡單正則表達式匹配。通配符參數可以包含通配符“%”或“_”,也可以是NULL指針,以便與所有的字段匹配。調用mysql_list_fields()的方法類似于執行查詢SHOW COLUMNS FROM *tbl_name* [LIKE *wild*]。 注意,建議使用SHOW COLUMNS FROM *tbl_name*,而不是mysql_list_fields()。 必須用mysql_free_result()釋放結果集。 **返回值** 如果成功,返回MYSQL_RES結果集。如果出現錯誤,返回NULL。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.42.?mysql_list_processes() MYSQL_RES *mysql_list_processes(MYSQL *mysql) **描述** 返回描述當前服務器線程的結果集。該類信息與**mysqladmin processlist**或SHOW PROCESSLIST查詢給出的信息相同。 必須用mysql_free_result()釋放結果集。 **返回值** 如果成功,返回MYSQL_RES結果集。如果出現錯誤,返回NULL。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.43.?mysql_list_tables() MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild) **描述** 返回由當前數據庫內的表名組成的結果集,當前數據庫與由通配符參數指定的簡單正則表達式匹配。通配符參數可以包含通配符“%”或“_”,也可以是NULL指針,以便與所有的表匹配。調用mysql_list_tables()的方法類似于執行查詢HOW tables [LIKE *wild*]。 必須用mysql_free_result()釋放結果集。 **返回值** 如果成功,返回MYSQL_RES結果集。 如果出現錯誤,返回NULL。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.44.?mysql_more_results() my_bool mysql_more_results(MYSQL *mysql) **描述** 如果當前執行的查詢存在多個結果,返回“真”,而且應用程序必須調用mysql_next_result()來獲取結果。 **返回值** 如果存在多個結果,返回“真”(1),如果不存在多個結果,返回“假”(0)。 在大多數情況下,可調用mysql_next_result()來測試是否存在多個結果,如果存在多個結果,對檢索進行初始化操作。 請參見[25.2.9節,“多查詢執行的C API處理”](# "25.2.9.?C API Handling of Multiple Query Execution")。請參見[25.2.3.45節,“mysql_next_result()”](# "25.2.3.45.?mysql_next_result()")。 **錯誤** 無。 #### 25.2.3.45.?mysql_next_result() int mysql_next_result(MYSQL *mysql) **描述** 如果存在多個查詢結果,mysql_next_result()將讀取下一個查詢結果,并將狀態返回給應用程序。 如果前面的查詢返回了結果集,必須為其調用mysql_free_result()。 調用了mysql_next_result()后,連接狀態就像你已為下一查詢調用了mysql_real_query()或mysql_query()時的一樣。這意味著你能調用mysql_store_result()、mysql_warning_count()、mysql_affected_rows()等等。 如果mysql_next_result()返回錯誤,將不執行任何其他語句,也不會獲取任何更多的結果, 請參見[25.2.9節,“多查詢執行的C API處理”](# "25.2.9.?C API Handling of Multiple Query Execution")。 **返回值** <table border="1" cellpadding="0" id="table6"><tr><td> <p><strong> <span>返回值</span></strong></p></td> <td> <p><strong> <span>描述</span></strong></p></td> </tr><tr><td> <p><span>0</span></p></td> <td> <p>成功并有多個結果。</p></td> </tr><tr><td> <p><span>-1</span></p></td> <td> <p>成功但沒有多個結果。</p></td> </tr><tr><td> <p><span>&gt;0</span></p></td> <td> <p>出錯</p></td> </tr></table> **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。例如,沒有為前面的結果集調用mysql_use_result()。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.46.?mysql_num_fields() unsigned int mysql_num_fields(MYSQL_RES *result) 要想傳遞MYSQL*參量取而代之,請使用無符號整數mysql_field_count(MYSQL *mysql)。 **描述** 返回結果集中的行數。 注意,你可以從指向結果集的指針或指向連接句柄的指針獲得行數。如果mysql_store_result()或mysql_use_result()返回NULL,應使用連接句柄(因而沒有結果集指針)。在該情況下,可調用mysql_field_count()來判斷mysql_store_result()是否生成了非空結果。這樣,客戶端程序就能采取恰當的行動,而不需要知道查詢是否是SELECT語句(或類似SELECT的語句)。在下面的示例中,介紹了執行該操作的方式。 請參見[25.2.13.1節,“為什么在mysql_query()返回成功后,mysql_store_result()有時會返回NULL``”](# "25.2.13.1.?Why mysql_store_result() Sometimes Returns NULL After mysql_query() Returns Success")。 **返回值** 表示結果集中行數的無符號整數。 **錯誤** 無。 **示例:** ~~~ MYSQL_RES *result; ~~~ ~~~ unsigned int num_fields; ~~~ ~~~ unsigned int num_rows; ~~~ ~~~ ? ~~~ ~~~ if (mysql_query(&mysql,query_string)) ~~~ ~~~ { ~~~ ~~~ ??? // error ~~~ ~~~ } ~~~ ~~~ else // query succeeded, process any data returned by it ~~~ ~~~ { ~~~ ~~~ ??? result = mysql_store_result(&mysql); ~~~ ~~~ ??? if (result)? // there are rows ~~~ ~~~ ??? { ~~~ ~~~ ??????? num_fields = mysql_num_fields(result); ~~~ ~~~ ??????? // retrieve rows, then call mysql_free_result(result) ~~~ ~~~ ??? } ~~~ ~~~ ??? else? // mysql_store_result() returned nothing; should it have? ~~~ ~~~ ??? { ~~~ ~~~ ??????? if (mysql_errno(&mysql)) ~~~ ~~~ ??????? { ~~~ ~~~ ?????????? fprintf(stderr, "Error: %s\n", mysql_error(&mysql)); ~~~ ~~~ ??????? } ~~~ ~~~ ??????? else if (mysql_field_count(&mysql) == 0) ~~~ ~~~ ??????? { ~~~ ~~~ ??????????? // query does not return data ~~~ ~~~ ??????????? // (it was not a SELECT) ~~~ ~~~ ??????????? num_rows = mysql_affected_rows(&mysql); ~~~ ~~~ ??????? } ~~~ ~~~ ??? } ~~~ ~~~ } ~~~ 另一種可選方式是(如果你知道你的查詢應返回結果集),使用檢查“mysql_field_count(&mysql) is = 0”來替換mysql_errno(&mysql)調用。僅當出錯時才應使用它。 #### 25.2.3.47.?mysql_num_rows() my_ulonglong mysql_num_rows(MYSQL_RES *result) **描述** 返回結果集中的行數。 mysql_num_rows()的使用取決于是否采用了mysql_store_result()或mysql_use_result()來返回結果集。如果使用了mysql_store_result(),可以立刻調用mysql_num_rows()。如果使用了mysql_use_result(),mysql_num_rows()不返回正確的值,直至檢索了結果集中的所有行為止。 **返回值** 結果集中的行數。 **錯誤** 無。 #### 25.2.3.48.?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應指向整數的值。 可能的選項值: <table border="1" cellpadding="0" width="612" style="width: 459.0pt" id="table7"><tr><td> <p><strong> <span>選項</span></strong></p></td> <td> <p><strong> <span>參量類型</span></strong></p></td> <td> <p><strong> <span>功能</span></strong></p></td> </tr><tr><td> <p> <span>MYSQL_INIT_COMMAND</span></p></td> <td> <p> <span>char *</span></p></td> <td> <p>連接到<span>MySQL</span>服務器時將執行的命令。再次連接時將自動地再次執行。</p></td> </tr><tr><td> <p> <span>MYSQL_OPT_COMPRESS</span></p></td> <td> <p>未使用</p></td> <td> <p>使用壓縮客戶端/服務器協議</p></td> </tr><tr><td> <p> <span>MYSQL_OPT_CONNECT_TIMEOUT</span></p></td> <td> <p> <span>unsigned int *</span></p></td> <td> <p>以秒為單位的連接超時。</p></td> </tr><tr><td> <p> <span>MYSQL_OPT_GUESS_CONNECTION</span></p></td> <td> <p>未使用</p></td> <td> <p>對于與<span><span>libmysqld</span>鏈接的應用程序,允許庫<span>“</span>猜測<span>”</span>是否使用</span>嵌入式服務器或遠程服務器。“<span class="quote">猜測</span>”表示,如果設置了主機名但不是本地主機,將使用遠程服務器。該行為是默認行為。 可使用<span>MYSQL_OPT_USE_EMBEDDED_CONNECTION</span><span> </span>和<span><span>MYSQL_OPT_USE_REMOTE_CONNECTION</span>覆蓋它。</span>對于與<span><span>libmysqlclient</span>鏈接的應用程序,該選項將被忽略。</span></p></td> </tr><tr><td> <p> <span>MYSQL_OPT_LOCAL_INFILE</span></p></td> <td> <p>指向單元的可選指針</p></td> <td> <p>如果未給定指針,或指針指向“<span><span>unsigned int != 0”</span>,將允許</span>命令<span>LOAD LOCAL INFILE</span>。</p></td> </tr><tr><td> <p> <span>MYSQL_OPT_NAMED_PIPE</span></p></td> <td> <p>未使用</p></td> <td> <p>使用命名管道連接到<span>NT</span>平臺上的<span>MySQL</span>服務器。</p></td> </tr><tr><td> <p> <span>MYSQL_OPT_PROTOCOL</span></p></td> <td> <p> <span>unsigned int *</span></p></td> <td> <p>要使用的協議類型。應是<span><span>mysql.h</span>中定義的<span>mysql_protocol_type</span>的枚舉值之一。</span></p></td> </tr><tr><td> <p> <span>MYSQL_OPT_READ_TIMEOUT</span></p></td> <td> <p> <span>unsigned int *</span></p></td> <td> <p>從服務器讀取信息的超時(目前僅在<span>Windows</span>平臺的<span>TCP/IP</span>連接上有效)。</p></td> </tr><tr><td> <p> <span>MYSQL_OPT_RECONNECT</span></p></td> <td> <p> <span>my_bool *</span></p></td> <td> <p>如果發現連接丟失,啟動或禁止與服務器的自動再連接。從<span>MySQL 5.0.3開始,默認情況下禁止再連接,這是5.0.13</span>中的新選項,提供了一種以顯式方式設置再連接行為的方法。</p></td> </tr><tr><td> <p> <span>MYSQL_OPT_SET_CLIENT_IP</span></p></td> <td> <p> <span>char *</span></p></td> <td> <p>對于與<span><span>libmysqld</span>鏈接的應用程序(具備鑒定支持特性的已編譯<span>libmysqld</span>)</span>,它意味著,出于鑒定目的,用戶將被視為從指定的<span>IP</span>地址(指定為字符串)進行連接。對于與<span><span>libmysqlclient</span>鏈接的應用程序,,該選項將被忽略。</span></p></td> </tr><tr><td> <p> <span>MYSQL_OPT_USE_EMBEDDED_CONNECTION</span></p></td> <td valign="top"> <p>未使用</p></td> <td> <p>對于與<span><span>libmysqld</span>鏈接的應用程序,對于連接來說,它將強制使用嵌入式服務器</span>。對于與<span><span>libmysqlclient</span>鏈接的應用程序,,該選項將被忽略。</span></p></td> </tr><tr><td> <p> <span>MYSQL_OPT_USE_REMOTE_CONNECTION</span></p></td> <td valign="top"> <p>未使用</p></td> <td> <p>對于與<span><span>libmysqld</span>鏈接的應用程序,對于連接來說,它將強制使用遠程服務器</span>。對于與<span><span>libmysqlclient</span>鏈接的應用程序,,該選項將被忽略。</span></p></td> </tr><tr><td> <p> <span>MYSQL_OPT_USE_RESULT</span></p></td> <td> <p>未使用</p></td> <td> <p>不使用該選項。</p></td> </tr><tr><td> <p> <span>MYSQL_OPT_WRITE_TIMEOUT</span></p></td> <td> <p> <span>unsigned int *</span></p></td> <td> <p>寫入服務器的超時(目前僅在<span>Windows</span>平臺的<span>TCP/IP</span>連接上有效)。</p></td> </tr><tr><td> <p> <span>MYSQL_READ_DEFAULT_FILE</span></p></td> <td> <p> <span>char *</span></p></td> <td> <p>從命名選項文件而不是從<span><span>my.cnf</span>讀取選項。</span></p></td> </tr><tr><td> <p> <span>MYSQL_READ_DEFAULT_GROUP</span></p></td> <td> <p> <span>char *</span></p></td> <td> <p>從<span><span>my.cnf</span>或用<span>MYSQL_READ_DEFAULT_FILE</span>指定的文件中的命名組讀取選項。</span></p></td> </tr><tr><td> <p> <span>MYSQL_REPORT_DATA_TRUNCATION</span></p></td> <td> <p> <span>my_bool *</span></p></td> <td> <p>通過<span><span>MYSQL_BIND.error</span>,對于預處理語句,允許或禁止通報數據截斷錯誤</span>(默認為禁止)。</p></td> </tr><tr><td> <p> <span>MYSQL_SECURE_AUTH</span></p></td> <td> <p> <span>my_bool*</span></p></td> <td> <p>是否連接到不支持密碼混編功能的服務器,在<span>MySQL 4.1.1</span>和更高版本中,使用了密碼混編功能。</p></td> </tr><tr><td> <p> <span>MYSQL_SET_CHARSET_DIR</span></p></td> <td> <p> <span>char*</span></p></td> <td> <p>指向包含字符集定義文件的目錄的路徑名。</p></td> </tr><tr><td> <p> <span>MYSQL_SET_CHARSET_NAME</span></p></td> <td> <p> <span>char*</span></p></td> <td> <p>用作默認字符集的字符集的名稱。</p></td> </tr><tr><td> <p> <span>MYSQL_SHARED_MEMORY_BASE_NAME</span></p></td> <td> <p> <span>char*</span></p></td> <td> <p>命名為與服務器進行通信的共享內存對象。應與你打算連接的<span>mysqld</span>服務器使用的選項“<span><span>-shared-memory-base-name”</span>相同。</span></p></td> </tr></table> 注意,如果使用了MYSQL_READ_DEFAULT_FILE或MYSQL_READ_DEFAULT_GROUP,總會讀取客戶端組。 選項文件中指定的組可能包含下述選項: <table border="1" cellpadding="0" id="table8"><tr><td> <p><strong> <span>選項</span></strong></p></td> <td> <p><strong> <span>描述</span></strong></p></td> </tr><tr><td> <p> <span>connect-timeout</span></p></td> <td> <p>以秒為單位的連接超時。在<span>Linux</span>平臺上,該超時也用作等待服務器首次回應的時間。</p></td> </tr><tr><td> <p> <span>compress</span></p></td> <td> <p>使用壓縮客戶端/服務器協議。</p></td> </tr><tr><td> <p> <span>database</span></p></td> <td> <p>如果在連接命令中未指定數據庫,連接到該數據庫。</p></td> </tr><tr><td> <p> <span>debug</span></p></td> <td> <p>調試選項。</p></td> </tr><tr><td> <p> <span>disable-local-infile</span></p></td> <td> <p>禁止使用<span>LOAD DATA LOCAL</span>。</p></td> </tr><tr><td> <p> <span>host</span></p></td> <td> <p>默認主機名。</p></td> </tr><tr><td> <p> <span>init-command</span></p></td> <td> <p>連接到<span>MySQL</span>服務器時將執行的命令。再次連接時將自動地再次執行。</p></td> </tr><tr><td> <p> <span>interactive-timeout</span></p></td> <td> <p>等同于將<span>CLIENT_INTERACTIVE</span>指定為<span>mysql_real_connect()</span>。請參見<a href="apis.html#mysql-real-connect" title="25.2.3.51.?mysql_real_connect()">25.2.3.51節,“mysql_real_connect()”</a>。</p></td> </tr><tr><td> <p> <span>local-infile[=(0|1)]</span></p></td> <td> <p>如果無參量或參量<span>!= 0</span>,那么將允許使用<span>LOAD DATA LOCAL</span>。</p></td> </tr><tr><td> <p> <span>max_allowed_packet</span></p></td> <td> <p>客戶端能夠從服務器讀取的最大信息包。</p></td> </tr><tr><td> <p> <span>multi-results</span></p></td> <td> <p>允許多語句執行或存儲程序的多個結果集。</p></td> </tr><tr><td> <p> <span>multi-statements</span></p></td> <td> <p>允許客戶端在<span>1</span>個字符串內發送多條語句。(由“<span>;</span>”隔開)。</p></td> </tr><tr><td> <p> <span>password</span></p></td> <td> <p>默認密碼。</p></td> </tr><tr><td> <p> <span>pipe</span></p></td> <td> <p>使用命名管道連接到<span>NT</span>平臺上的<span>MySQL</span>服務器。</p></td> </tr><tr><td> <p> <span>protocol={TCP | SOCKET | PIPE | MEMORY}</span></p></td> <td> <p>連接到服務器時將使用的協議。</p></td> </tr><tr><td> <p> <span>port</span></p></td> <td> <p>默認端口號。</p></td> </tr><tr><td> <p> <span>return-found-rows</span></p></td> <td> <p>通知<span><span>mysql_info()</span>返回發現的行,而不是使用<span>UPDATE</span>時更新的行</span>。</p></td> </tr><tr><td> <p> <span>shared-memory-base-name=<i>name</i></span></p></td> <td> <p>共享內存名稱,用于連接到服務器(默認為<span>"MYSQL"</span>)。</p></td> </tr><tr><td> <p> <span>socket</span></p></td> <td> <p>默認的套接字文件。</p></td> </tr><tr><td> <p> <span>user</span></p></td> <td> <p>默認用戶。</p></td> </tr></table> 注意,“timeout”(超時)已被“connect-timeout”(連接超時)取代,但為了保持向后兼容,在MySQL 5.1.2-alpha中仍支持“timeout”(超時)。 關于選項文件的更多信息,請參見[4.3.2節,“使用選項文件”](# "4.3.2.?Using Option Files")。 **返回值** 成功時返回0。如果使用了未知選項,返回非0值。 **示例:** ~~~ MYSQL mysql; ~~~ ~~~ ? ~~~ ~~~ mysql_init(&mysql); ~~~ ~~~ mysql_options(&mysql,MYSQL_OPT_COMPRESS,0); ~~~ ~~~ mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"odbc"); ~~~ ~~~ if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0)) ~~~ ~~~ { ~~~ ~~~ ??? fprintf(stderr, "Failed to connect to database: Error: %s\n", ~~~ ~~~ ????????? mysql_error(&mysql)); ~~~ ~~~ } ~~~ 該代碼請求客戶端使用壓縮客戶端/服務器協議,并從my.cnf文件的obdc部分讀取額外選項。 #### 25.2.3.49.?mysql_ping() int mysql_ping(MYSQL *mysql) **描述** 檢查與服務器的連接是否工作。如果連接丟失,將自動嘗試再連接。 該函數可被閑置了較長時間的客戶端使用,用以檢查服務器是否已關閉了連接,并在必要時再次連接。 **返回值** 如果與服務器的連接有效返回0。如果出現錯誤,返回非0值。返回的非0值不表示MySQL服務器本身是否已關閉,連接可能因其他原因終端,如網絡問題等。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.50.?mysql_query() int mysql_query(MYSQL *mysql, const char *query) **描述** 執行由“Null終結的字符串”查詢指向的SQL查詢。正常情況下,字符串必須包含1條SQL語句,而且不應為語句添加終結分號(‘;’)或“\g”。如果允許多語句執行,字符串可包含多條由分號隔開的語句。請參見[25.2.9節,“多查詢執行的C API處理”](# "25.2.9.?C API Handling of Multiple Query Execution")。 mysql_query()不能用于包含二進制數據的查詢,應使用mysql_real_query()取而代之(二進制數據可能包含字符‘\0’,mysql_query()會將該字符解釋為查詢字符串結束)。 如果希望了解查詢是否應返回結果集,可使用mysql_field_count()進行檢查。請參見[25.2.3.22節,“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 出現未知錯誤。 #### 25.2.3.51.?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()”](# "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”](# "26.1.9.2.?Configuring a MyODBC DSN on Windows")。 ·???????? “passwd”參數包含用戶的密碼。如果“passwd”是NULL,僅會對該用戶的(擁有1個空密碼字段的)用戶表中的條目進行匹配檢查。這樣,數據庫管理員就能按特定的方式設置MySQL權限系統,根據用戶是否擁有指定的密碼,用戶將獲得不同的權限。 **注釋:**調用mysql_real_connect()之前,不要嘗試加密密碼,密碼加密將由客戶端API自動處理。 ·???????? “db”是數據庫名稱。如果db為NULL,連接會將默認的數據庫設為該值。 ·???????? 如果“port”不是0,其值將用作TCP/IP連接的端口號。注意,“host”參數決定了連接的類型。 ·???????? 如果unix_socket不是NULL,該字符串描述了應使用的套接字或命名管道。注意,“host”參數決定了連接的類型。 ·???????? client_flag的值通常為0,但是,也能將其設置為下述標志的組合,以允許特定功能: <table border="1" cellpadding="0" id="table9"><tr><td> <p><strong> <span>標志名稱</span></strong></p></td> <td> <p><strong> <span>標志描述</span></strong></p></td> </tr><tr><td> <p> <span>CLIENT_COMPRESS</span></p></td> <td> <p>使用壓縮協議。</p></td> </tr><tr><td> <p> <span>CLIENT_FOUND_ROWS</span></p></td> <td> <p>返回發現的行數(匹配的),而不是受影響的行數。</p></td> </tr><tr><td> <p> <span>CLIENT_IGNORE_SPACE</span></p></td> <td> <p>允許在函數名后使用空格。使所有的函數名成為保留字。</p></td> </tr><tr><td> <p> <span>CLIENT_INTERACTIVE</span></p></td> <td> <p>關閉連接之前,允許<span><span>interactive_timeout</span>(取代了<span>wait_timeout</span>)秒的不活動時間。</span>客戶端的會話<span><span>wait_timeout</span>變量被設為會話<span>interactive_timeout</span>變量的值。</span></p></td> </tr><tr><td> <p> <span>CLIENT_LOCAL_FILES</span></p></td> <td> <p>允許<span>LOAD DATA LOCAL</span>處理功能。</p></td> </tr><tr><td> <p> <span>CLIENT_MULTI_STATEMENTS</span></p></td> <td> <p>通知服務器,客戶端可能在單個字符串內發送多條語句(由‘<span>;</span>’隔開)。如果未設置該標志,將禁止多語句執行。</p></td> </tr><tr><td> <p> <span>CLIENT_MULTI_RESULTS</span></p></td> <td> <p> 通知服務器,客戶端能夠處理來自多語句執行或存儲程序的多個結果集。如果設置了<span><span>CLIENT_MULTI_STATEMENTS</span>,將自動設置它。</span></p></td> </tr><tr><td> <p> <span>CLIENT_NO_SCHEMA</span></p></td> <td> <p>禁止<span><i><span>db_name.tbl_name.col_name</span></i></span>語法。它用于<span>ODBC</span>。如果使用了該語法,它會使分析程序生成錯誤,在捕獲某些<span>ODBC</span>程序中的缺陷時,它很有用。</p></td> </tr><tr><td> <p> <span>CLIENT_ODBC</span></p></td> <td> <p>客戶端是<span>ODBC</span>客戶端。它將<strong><span>mysqld</span></strong>變得更為<span>ODBC</span>友好。</p></td> </tr><tr><td> <p> <span>CLIENT_SSL</span></p></td> <td> <p>使用<span>SSL</span>(加密協議)。該選項不應由應用程序設置,它是在客戶端庫內部設置的。</p></td> </tr></table> 對于某些參數,能夠從選項文件獲得取值,而不是取得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時服務器消失。 **示例:** ~~~ MYSQL mysql; ~~~ ~~~ ? ~~~ ~~~ mysql_init(&mysql); ~~~ ~~~ mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"your_prog_name"); ~~~ ~~~ if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0)) ~~~ ~~~ { ~~~ ~~~ ??? fprintf(stderr, "Failed to connect to database: Error: %s\n", ~~~ ~~~ ????????? mysql_error(&mysql)); ~~~ ~~~ } ~~~ 通過使用mysql_options(),MySQL庫將讀取my.cnf文件的[client]和[your_prog_name]部分,以確保程序工作,即使某人以某種非標準的方式設置MySQL也同樣。 注意,一旦建立了連接,mysql_real_connect()將設置再連接標志(MYSQL結構的組成部份)的值,在低于5.0.3版的API中,將其設為“1”,在較新的版本中,將其設為“0”。對于該標志,值“1”表示,如果因連接丟失而無法執行語句,放棄前,將嘗試再次連接到服務器。從MySQL 5.0.13開始,可以對mysql_options()使用MYSQL_OPT_RECONNECT選項,對再連接行為進行控制。 #### 25.2.3.52.?mysql_real_escape_string() unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length) 注意,mysql必須是有效的開放式連接。之所以需要它是因為,轉義功能取決于服務器使用的字符集。 **描述** 該函數用于創建可在SQL語句中使用的合法SQL字符串。請參見[9.1.1節,“字符串”](# "9.1.1.?Strings")。 按照連接的當前字符集,將“from”中的字符串編碼為轉義SQL字符串。將結果置于“to”中,并添加1個終結用NULL字節。編碼的字符為NUL (ASCII 0)、‘\n’、‘\r’、‘\’、‘'’、‘"’、以及Control-Z(請參見[9.1節,“文字值”](# "9.1.?Literal Values"))。(嚴格地講,MySQL僅需要反斜杠和引號字符,用于引用轉義查詢中的字符串。該函數能引用其他字符,從而使得它們在日志文件中具有更好的可讀性)。 “from”指向的字符串必須是長度字節“long”。必須為“to”緩沖區分配至少length*2+1字節。在最壞的情況下,每個字符或許需要使用2個字節進行編碼,而且還需要終結Null字節。當mysql_real_escape_string()返回時,“to”的內容是由Null終結的字符串。返回值是編碼字符串的長度,不包括終結用Null字符。 如果需要更改連接的字符集,應使用mysql_set_character_set()函數,而不是執行SET NAMES (或SET CHARACTER SET)語句。mysql_set_character_set()的工作方式類似于SET NAMES,但它還能影響mysql_real_escape_string()所使用的字符集,而SET NAMES則不能。 **示例:** ~~~ char query[1000],*end; ~~~ ~~~ ? ~~~ ~~~ end = strmov(query,"INSERT INTO test_table values("); ~~~ ~~~ *end++ = '\''; ~~~ ~~~ end += mysql_real_escape_string(&mysql, end,"What's this",11); ~~~ ~~~ *end++ = '\''; ~~~ ~~~ *end++ = ','; ~~~ ~~~ *end++ = '\''; ~~~ ~~~ end += mysql_real_escape_string(&mysql, end,"binary data: \0\r\n",16); ~~~ ~~~ *end++ = '\''; ~~~ ~~~ *end++ = ')'; ~~~ ~~~ ? ~~~ ~~~ if (mysql_real_query(&mysql,query,(unsigned int) (end - query))) ~~~ ~~~ { ~~~ ~~~ ?? fprintf(stderr, "Failed to insert row, Error: %s\n", ~~~ ~~~ ?? ????????mysql_error(&mysql)); ~~~ ~~~ } ~~~ 該示例中使用的strmov()函數包含在mysqlclient庫中,工作方式與strcpy()類似,但會返回指向第1個參數終結用Null的指針。 **返回值** 置于“to”中的值的長度,不包括終結用Null字符。 **錯誤** 無。 #### 25.2.3.53.?mysql_real_query() int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length) **描述** 執行由“query”指向的SQL查詢,它應是字符串長度字節“long”。正常情況下,字符串必須包含1條SQL語句,而且不應為語句添加終結分號(‘;’)或“\g”。如果允許多語句執行,字符串可包含由分號隔開的多條語句。請參見[25.2.9節,“多查詢執行的C API處理”](# "25.2.9.?C API Handling of Multiple Query Execution")。 對于包含二進制數據的查詢,必須使用mysql_real_query()而不是mysql_query(),這是因為,二進制數據可能會包含‘\0’字符。此外,mysql_real_query()比mysql_query()快,這是因為它不會在查詢字符串上調用strlen()。 如果希望知道查詢是否應返回結果集,可使用mysql_field_count()進行檢查[25.2.3.22節,“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 出現未知錯誤。 #### 25.2.3.54.?mysql_refresh() int mysql_refresh(MYSQL *mysql, unsigned int options) **描述** 該函數用于刷新表或高速緩沖,或復位復制服務器信息。連接的用戶必須具有RELOAD權限。 “options”參量是一種位掩碼,由下述值的任意組合構成。能夠以“Or”(或)方式將多個值組合在一起,用一次調用執行多項操作。 ·???????? REFRESH_GRANT 刷新授權表,與FLUSH PRIVILEGES類似。 ·???????? REFRESH_LOG 刷新日志,與FLUSH LOGS類似。 ·???????? REFRESH_TABLES 刷新表高速緩沖,與FLUSH TABLES類似。 ·???????? REFRESH_HOSTS 刷新主機高速緩沖,與FLUSH HOSTS類似。 ·???????? REFRESH_STATUS 復位狀態變量,與FLUSH STATUS類似。 ·???????? REFRESH_THREADS 刷新線程高速緩沖。 ·???????? REFRESH_SLAVE 在從復制服務器上,復位主服務器信息,并重新啟動從服務器,與RESET SLAVE類似。 ·???????? REFRESH_MASTER 在主復制服務器上,刪除二進制日志索引中列出的二進制日志文件,并截短索引文件,與RESET MASTER類似。 **返回值** 0表示成功,非0值表示出現錯誤。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.55.?mysql_reload() int mysql_reload(MYSQL *mysql) **描述** 請求MySQL服務器重新加載授權表。連接的用戶必須具有RELOAD權限。 該函數已過時。最好使用mysql_query()來發出SQL FLUSH PRIVILEGES語句。 **返回值** 0表示成功,非0值表示出現錯誤。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.56.?mysql_rollback() my_bool mysql_rollback(MYSQL *mysql) **描述** 回滾當前事務。 該函數的動作取決于completion_type系統變量的值。尤其是,如果completion_type的值為“2”,終結事務后,服務器將執行釋放操作,并關閉客戶端連接。客戶端程序應調用mysql_close(),從客戶端一側關閉連接。 **返回值** 如果成功,返回0,如果出現錯誤,返回非0值。 **錯誤** 無。 #### 25.2.3.57.?mysql_row_seek() MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset) **描述** 將行光標置于查詢結果集中的任意行。“offset”值是行偏移量,它應是從mysql_row_tell()或mysql_row_seek()返回的值。該值不是行編號,如果你打算按編號查找結果集中的行,請使用mysql_data_seek()。 該函數要求在結果集的結構中包含查詢的全部結果,因此,mysql_row_seek()僅應與mysql_store_result()一起使用,而不是與mysql_use_result()。 **返回值** 行光標的前一個值。該值可傳遞給對mysql_row_seek()的后續調用。 **錯誤** 無。 #### 25.2.3.58.?mysql_row_tell() MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result) **描述** 對于上一個mysql_fetch_row(),返回行光標的當前位置。該值可用作mysql_row_seek()的參量。 僅應在mysql_store_result()之后,而不是mysql_use_result()之后使用mysql_row_tell()。 **返回值** 行光標的當前偏移量。 **錯誤** 無。 #### 25.2.3.59.?mysql_select_db() int mysql_select_db(MYSQL *mysql, const char *db) **描述** 使由db指定的數據庫成為由mysql指定的連接上的默認數據庫(當前數據庫)。在后續查詢中,該數據庫將是未包含明確數據庫區分符的表引用的默認數據庫。 除非已連接的用戶具有使用數據庫的權限,否則mysql_select_db()將失敗。 **返回值** 0表示成功,非0值表示出現錯誤。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.60.?mysql_set_character_set() int mysql_set_character_set(MYSQL *mysql, char *csname) **描述** 該函數用于為當前連接設置默認的字符集。字符串csname指定了1個有效的字符集名稱。連接校對成為字符集的默認校對。該函數的工作方式與SET NAMES語句類似,但它還能設置mysql->charset的值,從而影響了由mysql_real_escape_string()設置的字符集。 該函數是在MySQL 5.0.7中增加的。 **返回值** 0表示成功,非0值表示出現錯誤。 **示例:** ~~~ MYSQL mysql; ~~~ ~~~ ? ~~~ ~~~ mysql_init(&mysql); ~~~ ~~~ if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0)) ~~~ ~~~ { ~~~ ~~~ ??? fprintf(stderr, "Failed to connect to database: Error: %s\n", ~~~ ~~~ ????????? mysql_error(&mysql)); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ if (!mysql_set_charset_name(&mysql, "utf8")) ~~~ ~~~ { ~~~ ~~~ ??? printf("New client character set: %s\n", mysql_character_set_name(&mysql)); ~~~ ~~~ } ~~~ #### 25.2.3.61.?mysql_set_server_option() int mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option) **描述** 允許或禁止連接的選項。選項可以取下述值之一: <table border="1" cellpadding="0" id="table10"><tr><td> <p><span> MYSQL_OPTION_MULTI_STATEMENTS_ON</span></p></td> <td> <p>允許多語句支持。</p></td> </tr><tr><td> <p><span> MYSQL_OPTION_MULTI_STATEMENTS_OFF</span></p></td> <td> <p>禁止多語句支持。</p></td> </tr></table> **返回值** 0表示成功,非0值表示出現錯誤。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? ER_UNKNOWN_COM_ERROR 服務器不支持mysql_set_server_option()(當服務器版本低于4.1.1時),或服務器不支持試圖設置的選項。 ? #### 25.2.3.62.?mysql_shutdown() int mysql_shutdown(MYSQL *mysql, enum enum_shutdown_level shutdown_level) **描述** 請求數據庫服務器關閉。已連接的用戶必須具有SHUTDOWN權限。MySQL 5.1服務器僅支持1種關閉類型,shutdown_level必須等效于SHUTDOWN_DEFAULT。設計規劃了額外的關閉級別,以便能夠選擇所需的級別。對于用舊版本libmysqlclient頭文件編譯并調用mysql_shutdown()的動態鏈接可執行程序,需要與舊版的libmysqlclient動態庫一起使用。 在[5.5節,“MySQL服務器關機進程”](# "5.5.?The MySQL Server Shutdown Process")中,介紹了關機進程。 **返回值** 0表示成功,非0值表示出現錯誤。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.63.?mysql_sqlstate() const char *mysql_sqlstate(MYSQL *mysql) **描述** 返回由Null終結的字符串,該字符串包含關于上次錯誤的SQLSTATE錯誤代碼。錯誤代碼包含5個字符。'00000'表示無錯誤。其值由ANSI SQL和ODBC指定。關于可能取值的列表,請參見[附錄B:](#)[*錯誤代碼和消息*](# "Appendix?B.?Error Codes and Messages")。 注意,并非所有的MySQL錯誤均會被映射到SQLSTATE錯誤代碼。值'HY000'(一般錯誤)用于未映射的錯誤。 **返回值** 包含SQLSTATE錯誤碼的、由Null終結的字符串。 **另請參見:** 請參見[25.2.3.14節,“mysql_errno()”](# "25.2.3.14.?mysql_errno()")。請參見[25.2.3.15節,“mysql_error()”](# "25.2.3.15.?mysql_error()")。請參見[25.2.7.26節,“mysql_stmt_sqlstate()”](# "25.2.7.26.?mysql_stmt_sqlstate()")。 #### 25.2.3.64.?mysql_ssl_set() int mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher) **描述** 使用mysql_ssl_set(),可采用SSL建立安全連接。必須在mysql_real_connect()之前調用它。 除非在客戶端庫中允許了OpenSSL支持,否則mysql_ssl_set()不作任何事。 Mysql是從mysql_init()返回的連接處理程序。其他參數的指定如下: ·???????? key是key文件的路徑名。 ·???????? cert是證書文件的路徑名。 ·???????? ca是證書授權文件的路徑名。 ·???????? capath是指向目錄的路徑名,該目錄中包含以pem格式給出的受信任SSL CA證書。 ·???????? cipher是允許密碼的列表,用于SSL加密。 對于任何未使用的SSL參數,可為其給定NULL。 **返回值** 該函數總返回0。如果SSL設置不正確,當你嘗試連接時,mysql_real_connect()將返回錯誤。 #### 25.2.3.65.?mysql_stat() char *mysql_stat(MYSQL *mysql) **描述** 返回包含特定信息的字符串,該信息與**mysqladmin status**命令提供的信息類似。包括以秒為單位的正常運行時間,以及運行線程的數目,問題數,再加載次數,以及打開的表數目。 **返回值** 描述服務器狀態的字符集。如果出現錯誤,返回NULL。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.3.66.?mysql_store_result() MYSQL_RES *mysql_store_result(MYSQL *mysql) **描述** 對于成功檢索了數據的每個查詢(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等),必須調用mysql_store_result()或mysql_use_result()。 對于其他查詢,不需要調用mysql_store_result()或mysql_use_result(),但是如果在任何情況下均調用了mysql_store_result(),它也不會導致任何傷害或性能降低。通過檢查mysql_store_result()是否返回0,可檢測查詢是否沒有結果集(以后會更多)。 如果希望了解查詢是否應返回結果集,可使用mysql_field_count()進行檢查。請參見[25.2.3.22節,“mysql_field_count()”](# "25.2.3.22.?mysql_field_count()")。 mysql_store_result()將查詢的全部結果讀取到客戶端,分配1個MYSQL_RES結構,并將結果置于該結構中。 如果查詢未返回結果集,mysql_store_result()將返回Null指針(例如,如果查詢是INSERT語句)。 如果讀取結果集失敗,mysql_store_result()還會返回Null指針。通過檢查mysql_error()是否返回非空字符串,mysql_errno()是否返回非0值,或mysql_field_count()是否返回0,可以檢查是否出現了錯誤。 如果未返回行,將返回空的結果集。(空結果集設置不同于作為返回值的空指針)。 一旦調用了mysql_store_result()并獲得了不是Null指針的結果,可調用mysql_num_rows()來找出結果集中的行數。 可以調用mysql_fetch_row()來獲取結果集中的行,或調用mysql_row_seek()和mysql_row_tell()來獲取或設置結果集中的當前行位置。 一旦完成了對結果集的操作,必須調用mysql_free_result()。 請參見[25.2.13.1節,“為什么在mysql_query()返回成功后,mysql_store_result()有時會返回NULL``”](# "25.2.13.1.?Why mysql_store_result() Sometimes Returns NULL After mysql_query() Returns Success"). **返回值** 具有多個結果的MYSQL_RES結果集合。如果出現錯誤,返回NULL。 **錯誤** 如果成功,mysql_store_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 出現未知錯誤。 #### 25.2.3.67.?mysql_thread_id() unsigned long mysql_thread_id(MYSQL *mysql) **描述** 返回當前連接的線程ID。該值可用作mysql_kill()的參量以殺死線程。 如果連接丟失,并使用mysql_ping()進行了再連接,線程ID將改變。這意味著你不應獲取線程ID并保存它供以后使用。應在需要時獲取它。 **返回值** 當前連接的線程ID。 **錯誤** 無。 #### 25.2.3.68.?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 出現未知錯誤。 #### 25.2.3.69.?mysql_warning_count() unsigned int mysql_warning_count(MYSQL *mysql) **錯誤** 返回執行前一個SQL語句期間生成的告警數目。 **返回值** 告警計數。 **錯誤** 無。 ### 25.2.4.?C API預處理語句 MySQL客戶端/服務器協議提供了預處理語句。該功能采用了由mysql_stmt_init()初始化函數返回的MYSQL_STMT語句處理程序數據結構。對于多次執行的語句,預處理執行是一種有效的方式。首先對語句進行解析,為執行作好準備。接下來,在以后使用初始化函數返回的語句句柄執行一次或多次。 對于多次執行的語句,預處理執行比直接執行快,主要原因在于,僅對查詢執行一次解析操作。在直接執行的情況下,每次執行語句時,均將進行查詢。此外,由于每次執行預處理語句時僅需發送參數的數據,從而減少了網絡通信量。 預處理語句的另一個優點是,它采用了二進制協議,從而使得客戶端和服務器之間的數據傳輸更有效率。 下述語句可用作預處理語句:CREATE TABLE、DELETE、DO、INSERT、REPLACE、SELECT、SET、UPDATE、以及大多數SHOW語句。在MySQL 5.1中,不支持其他語句。 ### 25.2.5.?C API預處理語句的數據類型 預處理語句主要使用MYSQL_STMT和MYSQL_BIND數據結構。第3種結構MYSQL_TIME用于傳輸暫時性數據。 ·???????? MYSQL_STMT 該結構表示預處理語句。通過調用mysql_stmt_init()創建語句,返回語句句柄,即指向MYSQL_STMT的指針。該句柄用戶所有后續的與語句有關的函數,直至使用mysql_stmt_close()關閉了它為止。 MYSQL_STMT結構沒有供應用程序使用的參數。此外,不應嘗試復制MYSQL_STMT結構。不保證這類復制物會有用。 多個語句句柄能夠與單個連接關聯起來。對句柄數目的限制取決于系統資源。 ·???????? MYSQL_BIND 該結構用于語句輸入(發送給服務器的數據值)和輸出(從服務器返回的結果值)。對于輸入,它與mysql_stmt_bind_param()一起使用,用于將參數數據值綁定到緩沖區上,以供mysql_stmt_execute()使用。對于輸出,它與mysql_stmt_bind_result()一起使用,用于綁定結果緩沖區,以便用于with mysql_stmt_fetch()以獲取行。 MYSQL_BIND結構包含下述供應用程序使用的成員。每個成員用于輸入和輸出,但在某些時候,也能用于不同的目的,具體情況取決于數據傳輸的方向。 o??????? enum enum_field_types buffer_type 緩沖的類型。在本節后面列出了允許的buffer_type值。對于輸入,buffer_type指明了與語句參數捆綁的值類型。對于輸出,它指明了你希望從結果緩沖收到的值類型。 o??????? void *buffer 對于輸入,這是指向存儲語句參數數據值的緩沖的指針。對于輸出,它是指向返回結果集列值的緩沖的指針。對于數值列類型,緩沖應指向恰當的C類型變量(如果將該變量與具有UNSIGNED屬性的列關聯起來,變量unsigned C類型。通過使用is_unsigned成員,指明變量是signed或unsigned類型,詳情請參見本節后面的介紹)。對于日期和時間列類型,緩沖應指向MYSQL_TIME結構。對于字符和二進制字符串列類型,緩沖應指向字符緩沖區。 o??????? unsigned long buffer_length *buffer的實際大小,單位為字節。它指明了可保存在緩沖區內的最大數據。對于字符和二進制C數據,buffer_length值指定了與mysql_stmt_bind_param()一起使用時的*buffer長度,或與mysql_stmt_bind_result()一起使用時能夠提取到緩沖區內的最大數據。 o??????? unsigned long *length 指向unsigned long變量的指針,該變量指明了存儲在*buffer中數據的實際字節數。“length”用于字符或二進制C數據。對于輸入參數數據綁定,“length”指向unsigned long變量,該變量指明了存儲在*buffer中參數值的長度,供mysql_stmt_execute()使用。對于輸出值綁定,mysql_stmt_fetch()會將返回的列值保存到“length”指向的變量中。 對于數值和臨時數據類型,“length”將被忽略,原因在于,數據值的長度是由buffer_type值決定的。 o??????? my_bool *is_null 該成員指向my_bool變量,如果值為NULL,該變量為“真”,如果值為非Null,該變量為“假”。對于輸入,將*is_null設置為“真”,指明以語句參數的形式傳遞NULL值。對于輸出,如果從語句返回的結果集列值為NULL,當獲取了行后,該值將被設為“真”。 “is_null”是指向布爾類型的指針,而不是布爾標量,以便能以下述方式使用它: §???????? 如果數據值總是NULL,使用MYSQL_TYPE_NULL綁定列。 §???????? 如果數據值總是NOT NULL,設置is_null = (my_bool*) 0。 §???????? 在所有其他情況下,應將is_null設置為my_bool變量的地址,并在各次執行之間恰當地更改變量的值,以指明數據值是NULL或NOT NULL。 o??????? my_bool is_unsigned 該成員用于整數類型。(對應于MYSQL_TYPE_TINY、MYSQL_TYPE_SHORT、MYSQL_TYPE_LONG、以及MYSQL_TYPE_LONGLONG類型的代碼)。對于無符號類型,應將“is_unsigned”設置為“真”,對于帶符號類型,應將其設置為“假”。 o??????? my_bool error 對于輸出,該成員用于通報數據截短錯誤。必須通過調用帶有MYSQL_REPORT_DATA_TRUNCATION選項的mysql_options(),啟用截短通報功能。允許該功能后,mysql_stmt_fetch()返回MYSQL_DATA_TRUNCATED,而且對于出現截短情況的參數,在MYSQL_BIND結構中,錯誤標志為“真”。截短指明丟失了符號或有效位數,或字符串過長以至于無法容納在1列中。 要想使用MYSQL_BIND結構,應將其內容置為0以便初始化它,然后對其進行設置,恰當地描述它。例如,要想聲明并初始化三個MYSQL_BIND結構的數組,可使用下述代碼: ~~~ MYSQL_BIND??? bind[3]; ~~~ ~~~ memset(bind, 0, sizeof(bind)); ~~~ ·???????? MYSQL_TIME 該結構用于將DATE、TIME、DATETIME和TIMESTAMP數據直接發送到服務器,或從服務器直接接收這類數據。將MYSQL_BIND結構的buffer_type成員設置為臨時值之一,并將buffer成員設置為指向MYSQL_TIME結構,即可實現該點。 MYSQL_TIME結構包含下述成員: o??????? unsigned int year 年份 o??????? unsigned int month 月份 o??????? unsigned int day 天 o??????? unsigned int hour 小時 o??????? unsigned int minute 分鐘 o??????? unsigned int second 秒 o??????? my_bool neg 布爾標志,用于指明時間是否為負數。 o??????? unsigned long second_part 秒的分數部分。該成員目前不使用。 僅使用施加在給定臨時類型值上的MYSQL_TIME結構的部分:用于DATE、DATETIME和TIMESTAMP的年、月、日部分。用于TIME、DATETIME和TIMESTAMP值的小時、分鐘、秒部分。請參見[25.2.10節,“日期和時間值的C API處理”](# "25.2.10.?C API Handling of Date and Time Values")。 在下面的表格中,給出了可在MYSQL_BIND結構的buffer_type成員中指定的允許值。在該表中,還給出了與每個buffer_type值最接近的對應SQL類型,對于數值和臨時類型,給出了對應的C類型。 <table border="1" cellpadding="0" id="table11"><tr><td> <p> <span>buffer_type</span><strong><span>值</span></strong></p></td> <td> <p><strong> <span>SQL</span><span>類型</span></strong></p></td> <td> <p><strong> <span>C</span><span>類型</span></strong></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TINY</span></p></td> <td> <p> <span>TINYINT</span></p></td> <td> <p> <span>char</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_SHORT</span></p></td> <td> <p> <span>SMALLINT</span></p></td> <td> <p> <span>short int</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_LONG</span></p></td> <td> <p> <span>INT</span></p></td> <td> <p> <span>int</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_LONGLONG</span></p></td> <td> <p> <span>BIGINT</span></p></td> <td> <p> <span>long long int</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_FLOAT</span></p></td> <td> <p> <span>FLOAT</span></p></td> <td> <p> <span>float</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DOUBLE</span></p></td> <td> <p> <span>DOUBLE</span></p></td> <td> <p> <span>double</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TIME</span></p></td> <td> <p> <span>TIME</span></p></td> <td> <p> <span>MYSQL_TIME</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DATE</span></p></td> <td> <p> <span>DATE</span></p></td> <td> <p> <span>MYSQL_TIME</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DATETIME</span></p></td> <td> <p> <span>DATETIME</span></p></td> <td> <p> <span>MYSQL_TIME</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TIMESTAMP</span></p></td> <td> <p> <span>TIMESTAMP</span></p></td> <td> <p> <span>MYSQL_TIME</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_STRING</span></p></td> <td> <p> <span>CHAR</span></p></td> <td> <p><span>?</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_VAR_STRING</span></p></td> <td> <p> <span>VARCHAR</span></p></td> <td> <p><span>?</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TINY_BLOB</span></p></td> <td> <p> <span>TINYBLOB/TINYTEXT</span></p></td> <td> <p><span>?</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_BLOB</span></p></td> <td> <p> <span>BLOB/TEXT</span></p></td> <td> <p><span>?</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_MEDIUM_BLOB</span></p></td> <td> <p> <span>MEDIUMBLOB/MEDIUMTEXT</span></p></td> <td> <p><span>?</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_LONG_BLOB</span></p></td> <td> <p> <span>LONGBLOB/LONGTEXT</span></p></td> <td> <p><span>?</span></p></td> </tr></table> 隱式類型轉換可沿兩個方向執行。 ### 25.2.6.?C API預處理語句函數概述 在此歸納了預處理語句處理功能可使用的函數,并在后面的章節中詳細介紹了它。請參見[25.2.7節,“C API預處理語句函數描述”](# "25.2.7.?C API Prepared Statement Function Descriptions")。 <table border="1" cellpadding="0" id="table12"><tr><td> <p><strong><span> 函數</span></strong></p></td> <td> <p><strong><span> 描述</span></strong></p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_affected_rows()</span></strong></p></td> <td> <p>返回由預處理語句<span>UPDATE</span>、<span>DELETE</span>或<span>INSERT</span>變更、刪除或插入的行數目。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_attr_get()</span></strong></p></td> <td> <p>獲取預處理語句屬性的值。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_attr_set()</span></strong></p></td> <td> <p>設置預處理語句的屬性。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_bind_param()</span></strong></p></td> <td> <p>將應用程序數據緩沖與預處理<span>SQL</span>語句中的參數標記符關聯起來。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_bind_result()</span></strong></p></td> <td> <p>將應用程序數據緩沖與結果集中的列關聯起來。</p></td> </tr><tr><td> <p><strong> <span>mysql_stmt_close()</span></strong></p></td> <td> <p>釋放預處理語句使用的內存。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_data_seek()</span></strong></p></td> <td> <p>尋找語句結果集中的任意行編號。</p></td> </tr><tr><td> <p><strong> <span>mysql_stmt_errno()</span></strong></p></td> <td> <p>返回上次語句執行的錯誤編號。</p></td> </tr><tr><td> <p><strong> <span>mysql_stmt_error()</span></strong></p></td> <td> <p>返回上次語句執行的錯誤消息。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_execute()</span></strong></p></td> <td> <p>執行預處理語句。</p></td> </tr><tr><td> <p><strong> <span>mysql_stmt_fetch()</span></strong></p></td> <td> <p>從結果集獲取數據的下一行,并返回所有綁定列的數據。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_fetch_column()</span></strong></p></td> <td> <p>獲取結果集當前行中某列的數據。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_field_count()</span></strong></p></td> <td> <p>對于最近的語句,返回結果行的數目。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_free_result()</span></strong></p></td> <td> <p>釋放分配給語句句柄的資源。</p></td> </tr><tr><td> <p><strong> <span>mysql_stmt_init()</span></strong></p></td> <td> <p><span>為<span>MYSQL_STMT</span>結構分配內存并初始化它</span>。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_insert_id()</span></strong></p></td> <td> <p>對于預處理語句的<span><span>AUTO_INCREMENT</span>列,</span>返回生成的<span>ID</span>。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_num_rows()</span></strong></p></td> <td> <p>從語句緩沖結果集返回總行數。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_param_count()</span></strong></p></td> <td> <p>返回預處理<span>SQL</span>語句中的參數數目。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_param_metadata()</span></strong></p></td> <td> <p>返回結果集的參數元數據。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_prepare()</span></strong></p></td> <td> <p>為執行操作準備<span>SQL</span>字符串。</p></td> </tr><tr><td> <p><strong> <span>mysql_stmt_reset()</span></strong></p></td> <td> <p>復位服務器中的語句緩沖區。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_result_metadata()</span></strong></p></td> <td> <p>以結果集形式返回預處理語句元數據。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_row_seek()</span></strong></p></td> <td> <p>使用從<span><span>mysql_stmt_row_tell()</span>返回的值,查找語句結果集中的行偏移。</span></p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_row_tell()</span></strong></p></td> <td> <p>返回語句行光標位置。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_send_long_data()</span></strong></p></td> <td> <p>將程序塊中的長數據發送到服務器。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_sqlstate()</span></strong></p></td> <td> <p>返回關于上次語句執行的<span>SQLSTATE</span>錯誤代碼。</p></td> </tr><tr><td> <p><strong> <span> mysql_stmt_store_result()</span></strong></p></td> <td> <p>將完整的結果集檢索到客戶端。</p></td> </tr></table> 調用mysql_stmt_init()以創建語句句柄,然后調用mysql_stmt_prepare準備語句,調用mysql_stmt_bind_param()提供參數數據,并調用mysql_stmt_execute()執行語句。通過更改mysql_stmt_bind_param()提供的相應緩沖區中的參數值,可重復執行mysql_stmt_execute()。 如果語句是SELECT或任何其他能生成結果集的語句,mysql_stmt_prepare()也會通過mysql_stmt_result_metadata()以MYSQL_RES結果集的形式返回結果集元數據信息。 你可以使用mysql_stmt_bind_result()提供結果緩沖,以便mysql_stmt_fetch()能自動將數據返回給這些緩沖。這是一種按行獲取方式。 此外,你也能使用mysql_stmt_send_long_data()將程序塊中的文本或二進制數據發送到服務器。請參見[25.2.7.25節,“mysql_stmt_send_long_data()”](# "25.2.7.25.?mysql_stmt_send_long_data()")。 完成語句執行后,必須使用mysql_stmt_close()關閉語句句柄,以便與之相關的所有資源均能被釋放。 如果通過調用mysql_stmt_result_metadata()獲得了SELECT語句的結果集元數據,也應使用mysql_free_result()釋放元數據。 **執行步驟** 要想準備和執行語句,應用程序必須采取下述步驟: 1.??? 用msyql_stmt_init()創建預處理語句句柄。要想在服務器上準備預處理語句,可調用mysql_stmt_prepare(),并為其傳遞包含SQL語句的字符串。 2.??? 如果語句生成了結果集,調用mysql_stmt_result_metadata()以獲得結果集元數據。雖然與包含查詢返回列的結果集不同,該元數據本身也采用了結果集的形式。元數據結果集指明了結果中包含多少列,并包含每一列的信息。 3.??? 使用mysql_stmt_bind_param()設置任何參數的值。必須設置所有參數。否則,語句執行將返回錯誤,或生成無法預料的結果。 4.??? 調用mysql_stmt_execute()執行語句。 5.??? 如果語句生成了結果集,捆綁數據緩沖,通過調用mysql_stmt_bind_result(),檢索行值。 6.??? 通過重復調用mysql_stmt_fetch(),按行將數據提取到緩沖區,直至未發現更多行為止。 7.??? 通過更改參數值并再次執行語句,重復步驟3到步驟6。 調用mysql_stmt_prepare()時,MySQL客戶端/服務器協議將執行下述動作: ·???????? 服務器解析語句,并通過賦值語句ID將OK狀態發回客戶端。此外,如果它是面向結果集的語句,還將發送總的參數數目,列計數和元數據。在此調用過程中,服務器將檢查語句的所有語法和語義。 ·???????? 客戶端采用該語句ID用于進一步操作,以便服務器能從其語句池中識別語句。 調用mysql_stmt_execute()時,MySQL客戶端/服務器協議將執行下述動作: ·???????? 客戶端使用語句句柄,并將參數數據發送到服務器。 ·???????? 服務器使用由客戶端提供的ID來識別語句,用新提供的數據替換參數標記符,并執行語句。如果語句生成了結果集,服務器將數據發回客戶端。否則,服務器會將發送OK狀態,以及總的變更、刪除和插入行數。 調用mysql_stmt_fetch()時,MySQL客戶端/服務器協議將執行下述動作: ·???????? 客戶端按行從信息包讀取數據,并通過執行必要的轉換操作將其放入應用程序數據緩沖中。如果應用程序的緩沖類型與服務器返回的字段類型相同,轉換十分簡明。 如果出現了錯誤,可分別使用mysql_stmt_errno()、mysql_stmt_error()和mysql_stmt_sqlstate()獲取語句錯誤代碼、錯誤消息和SQLSTATE值。 **預處理語句日志功能** 對于與mysql_stmt_prepare()和mysql_stmt_execute() C API函數一起執行的預處理語句,服務器會將“準備”和“執行”行寫入一般查詢日志,以便你能了解語句是在何時準備和執行的。 假定按下述方式準備和執行了語句: 1.??? 調用mysql_stmt_prepare()以準備語句字符串"SELECT ?"。 2.??? 調用mysql_stmt_bind_param()將值“3”綁定到預處理語句中的參數。 3.??? 調用mysql_stmt_execute(),執行預處理語句。 上述調用的結果是,服務器將下述行寫入一般查詢日志: ~~~ Prepare? [1] SELECT ? ~~~ ~~~ Execute? [1] SELECT 3 ~~~ 日志中的每個“準備”和“執行”行均具有[*n*]語句ID標識,這樣,你就能跟蹤已記錄的預處理語句。*N*是正整數。對于客戶端,如果同時有多個活動的預處理語句,*n*可能會大于1。替換了“?”參數的數據值后,每個“執行”行將顯示一條預處理語句。 版本說明:在MySQL 4.1.10之前,顯示的“準備”行無[*n*]標識。在MySQL 4.1.10之前,不顯示“執行”行。 ### 25.2.7.?C API預處理語句函數描述 [25.2.7.1. mysql_stmt_affected_rows()](#)[25.2.7.2. mysql_stmt_attr_get()](#)[25.2.7.3. mysql_stmt_attr_set()](#)[25.2.7.4. mysql_stmt_bind_param()](#)[25.2.7.5. mysql_stmt_bind_result()](#)[25.2.7.6. mysql_stmt_close()](#)[25.2.7.7. mysql_stmt_data_seek()](#)[25.2.7.8. mysql_stmt_errno()](#)[25.2.7.9. mysql_stmt_error()](#)[25.2.7.10. mysql_stmt_execute()](#)[25.2.7.11. mysql_stmt_fetch()](#)[25.2.7.12. mysql_stmt_fetch_column()](#)[25.2.7.13. mysql_stmt_field_count()](#)[25.2.7.14. mysql_stmt_free_result()](#)[25.2.7.15. mysql_stmt_init()](#)[25.2.7.16. mysql_stmt_insert_id()](#)[25.2.7.17. mysql_stmt_num_rows()](#)[25.2.7.18. mysql_stmt_param_count()](#)[25.2.7.19. mysql_stmt_param_metadata()](#)[25.2.7.20. mysql_stmt_prepare()](#)[25.2.7.21. mysql_stmt_reset()](#)[25.2.7.22. mysql_stmt_result_metadata()](#)[25.2.7.23. mysql_stmt_row_seek()](#)[25.2.7.24. mysql_stmt_row_tell()](#)[25.2.7.25. mysql_stmt_send_long_data()](#)[25.2.7.26. mysql_stmt_sqlstate()](#)[25.2.7.27. mysql_stmt_store_result()](#) 為了準備和執行查詢,請使用下述部分詳細介紹的函數。 注意,與MYSQL_STMT結構一起使用的所有函數均以前綴mysql_stmt_開始。 要想創建MYSQL_STMT句柄,請使用mysql_stmt_init()函數。 #### 25.2.7.1.?mysql_stmt_affected_rows() my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt) **描述** 返回上次執行語句更改、刪除或插入的總行數。對于UPDATE、DELETE或INSERT語句,可在mysql_stmt_execute()之后立刻調用它們。對于SELECT語句,mysql_stmt_affected_rows()的工作方式類似于mysql_num_rows()。 **返回值** 大于0的整數指明了受影響或檢索的行數。對于UPDATE語句,“0”表明未更新任何記錄,在查詢中沒有與WHERE子句匹配的行,或尚未執行任何查詢。“-1”表明返回了錯誤,或對SELECT查詢,在調用mysql_stmt_store_result()之前調用了mysql_stmt_affected_rows()。由于mysql_stmt_affected_rows()返回無符號值,可通過比較返回值和“(my_ulonglong)-1”(或等效的“(my_ulonglong)~0”),檢查“-1”。 關于返回值的額外信息,請參見[25.2.3.1節,“mysql_affected_rows()”](# "25.2.3.1.?mysql_affected_rows()")。 **錯誤** 無。 **示例:** 關于mysql_stmt_affected_rows()的用法,請參閱[25.2.7.10節,“mysql_stmt_execute()”](# "25.2.7.10.?mysql_stmt_execute()")中給出的示例。 #### 25.2.7.2.?mysql_stmt_attr_get() int mysql_stmt_attr_get(MYSQL_STMT *stmt, enum enum_stmt_attr_type option, void *arg) **描述** 可用于獲得語句屬性的當前值。 “option”參量是希望獲取的選項,“arg”應指向包含選項值的變量。如果“option”是整數,那么“arg”應指向整數的值。 關于選項和選項類型的清單,請參見[25.2.7.3節,“mysql_stmt_attr_set()”](# "25.2.7.3.?mysql_stmt_attr_set()")。 **返回值** 如果OK,返回0。如果選項未知,返回非0值。 **錯誤** 無。 #### 25.2.7.3.?mysql_stmt_attr_set() int mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type option, const void *arg) **描述** 可用于影響預處理語句的行為。可多次調用該函數來設置多個選項。 “option”參量是希望設置的選項,“arg”參量是選項的值。如果“option”是整數,那么“arg”應指向整數的值。 可能的選項值: <table border="1" cellpadding="0" id="table13"><tr><td> <p><strong> <span>選項</span></strong></p></td> <td> <p><strong> <span>參量類型</span></strong></p></td> <td> <p><strong> <span>功能</span></strong></p></td> </tr><tr><td> <p> <span>STMT_ATTR_UPDATE_MAX_LENGTH</span></p></td> <td> <p> <span>my_bool *</span></p></td> <td> <p>如果設為<span>1</span>:更新<span><span>mysql_stmt_store_result()</span>中的</span>元數據<span>MYSQL_FIELD-&gt;max_length</span>。</p></td> </tr><tr><td> <p> <span>STMT_ATTR_CURSOR_TYPE</span></p></td> <td> <p> <span>unsigned long *</span></p></td> <td> <p>調用<span><span>mysql_stmt_execute()</span>時,語句將打開的光標類型。<span>*arg</span>可以是<span>CURSOR_TYPE_NO_CURSOR</span>(默認值)或<span>CURSOR_TYPE_READ_ONLY</span></span>。</p></td> </tr><tr><td> <p> <span>STMT_ATTR_PREFETCH_ROWS</span></p></td> <td> <p> <span>unsigned long *</span></p></td> <td> <p>使用光標時,一次從服務器獲取的行數。<span><span>*arg</span>的范圍從<span>1</span>到<span>unsigned long</span>的最大值。默認值為<span>1</span>。</span></p></td> </tr></table> 如果與CURSOR_TYPE_READ_ONLY一起使用了STMT_ATTR_CURSOR_TYPE選項,當調用了mysql_stmt_execute()時,將為語句打開光標。如果存在由前一個mysql_stmt_execute()調用打開的光標,在打開新的光標前,將關閉該光標。此外,為再執行而準備語句之前,mysql_stmt_reset()還將關閉任何打開的光標。mysql_stmt_free_result()將關閉任何打開的光標。 如果為預處理語句打開了光標,沒必要調用mysql_stmt_store_result(),這是因為,該函數會導致在客戶端一側對結果集進行緩沖處理。 在MySQL 5.0.2中增加了STMT_ATTR_CURSOR_TYPE選項。在MySQL 5.0.6中,增加了STMT_ATTR_PREFETCH_ROWS選項。 **返回值** 如果OK,返回0。如果選項未知,返回非0值。 **錯誤** 無。 **示例:** 在下述示例中,為預處理語句打開了1個光標,并將每次獲取的行數設為5: ~~~ MYSQL_STMT *stmt; ~~~ ~~~ int rc; ~~~ ~~~ unsigned long type; ~~~ ~~~ unsigned long prefetch_rows = 5; ~~~ ~~~ ? ~~~ ~~~ stmt = mysql_stmt_init(mysql); ~~~ ~~~ type = (unsigned long) CURSOR_TYPE_READ_ONLY; ~~~ ~~~ rc = mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type); ~~~ ~~~ /* ... check return value ... */ ~~~ ~~~ rc = mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, ~~~ ~~~ ????????????????????????????????????? ? (void*) &prefetch_rows); ~~~ ~~~ /* ... check return value ... */ ~~~ #### 25.2.7.4.?mysql_stmt_bind_param() my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind) **描述** mysql_stmt_bind_param()用于為SQL語句中的參數標記符綁定數據,以傳遞給mysql_stmt_prepare()。它使用MYSQL_BIND結構來提供數據。“bind”是MYSQL_BIND結構的某一數組的地址。按照客戶端庫的預期,對于查詢中出現的每個“?”參數標記符,數組中均包含1個元素。 假定你準備了下述語句: ~~~ INSERT INTO mytbl VALUES(?,?,?) ~~~ 綁定參數時,MYSQL_BIND結構的數組包含3個元素,并能聲明如下: ~~~ MYSQL_BIND bind[3]; ~~~ 在[25.2.5節,“C API預處理語句的數據類型”](# "25.2.5.?C API Prepared Statement Data types")中,介紹了應設置的每個MYSQL_BIND元素的成員。 **返回值** 如果綁定成功,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_INVALID_BUFFER_USE 指明“bind”(綁定)是否將提供程序塊中的長數據,以及緩沖類型是否為非字符串或二進制類型。 ·???????? CR_UNSUPPORTED_PARAM_TYPE 不支持該轉換。或許buffer_type值是非法的,或不是所支持的類型之一。 ·???????? CR_OUT_OF_MEMORY 內存溢出。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 **示例:** 關于mysql_stmt_bind_param()的用法,請參見[25.2.7.10節,“mysql_stmt_execute()”](# "25.2.7.10.?mysql_stmt_execute()")給出的示例。 #### 25.2.7.5.?mysql_stmt_bind_result() my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) **描述** mysql_stmt_bind_result()用于將結果集中的列與數據緩沖和長度緩沖關聯(綁定)起來。當調用mysql_stmt_fetch()以獲取數據時,MySQL客戶端/服務器協議會將綁定列的數據置于指定的緩沖區內。 調用mysql_stmt_fetch()之前,必須將所有列綁定到緩沖。“bind”是MYSQL_BIND結構某一數組的地址。按照客戶端庫的預期,對于結果集中的每一列,數組應包含相應的元素。如果未將列綁定到MYSQL_BIND結構,mysql_stmt_fetch()將簡單地忽略數據獲取操作。緩沖區應足夠大,足以容納數據值,這是因為協議不返回成塊的數據值。 可以在任何時候綁定或再綁定列,即使已部分檢索了結果集后也同樣。新的綁定將在下一次調用mysql_stmt_fetch()時起作用。假定某一應用程序綁定了結果集中的列,并調用了mysql_stmt_fetch()。客戶端/服務器協議將返回綁定緩沖區中的數據。接下來,假定應用程序將多個列綁定到不同的緩沖。該協議不會將數據置于新綁定的緩沖區,直至下次調用mysql_stmt_fetch()為止。 要想綁定列,應用程序將調用mysql_stmt_bind_result(),并傳遞類型、地址、以及長度緩沖的地址。在[25.2.5節,“C API預處理語句的數據類型”](# "25.2.5.?C API Prepared Statement Data types")中,介紹了應設置的各MYSQL_BIND元素的成員。 **返回值** 如果綁定成功,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_UNSUPPORTED_PARAM_TYPE 不支持該轉換。或許buffer_type值是非法的,或不是所支持的類型之一。 ·???????? CR_OUT_OF_MEMORY 內存溢出。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 **示例:** 關于mysql_stmt_bind_result()的用法,請參見[25.2.7.11節,“mysql_stmt_fetch()”](# "25.2.7.11.?mysql_stmt_fetch()")中給出的示例。 #### 25.2.7.6.?mysql_stmt_close() my_bool mysql_stmt_close(MYSQL_STMT *) **描述** 關閉預處理語句。此外,mysql_stmt_close()還會取消由“stmt”指向的語句句柄分配。 如果當前語句已掛起或未讀取結果,該函數將取消它們,以便能執行下一個查詢, **返回值** 如果成功釋放了語句,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 **示例:** 關于mysql_stmt_close()的用法,請參見[25.2.7.10節,“mysql_stmt_execute()”](# "25.2.7.10.?mysql_stmt_execute()")中給出的示例。 #### 25.2.7.7.?mysql_stmt_data_seek() void mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset) **描述** 查找語句結果集中的任意行。偏移量為行編號,應位于從0到mysql_stmt_num_rows(stmt)-1的范圍內。 該函數要求語句結果集結構包含上次執行查詢的全部結果,這樣,mysql_stmt_data_seek()就能與mysql_stmt_store_result()一起使用。 **返回值** 無。 **錯誤** 無。 #### 25.2.7.8.?mysql_stmt_errno() unsigned int mysql_stmt_errno(MYSQL_STMT *stmt) **描述** 對于由stmt指定的語句,mysql_stmt_errno()將返回最近調用的語句API函數的錯誤代碼,該函數或成功或失敗。“0”返回值表示未出現錯誤。在MySQL errmsg.h頭文件中列出了客戶端錯誤消息編號。在mysqld_error.h中,列出了服務器錯誤消息。此外,在[附錄B:](#)[*錯誤代碼和消息*](# "Appendix?B.?Error Codes and Messages")中,也列出了錯誤消息。 **返回值** 錯誤代碼值。如果未出現錯誤,返回0。 **錯誤** 無。 #### 25.2.7.9.?mysql_stmt_error() const char *mysql_stmt_error(MYSQL_STMT *stmt) **描述** 對于由stmt指定的語句,mysql_stmt_error()返回由Null終結的字符串,該字符串包含最近調用的語句API函數的錯誤消息,該函數或成功或失敗。如果未出現錯誤,返回空字符串("")。這意味著下述兩個測試是等效的: ~~~ ? ~~~ ~~~ if (mysql_stmt_errno(stmt)) ~~~ ~~~ { ~~~ ~~~ ? // an error occurred ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ if (mysql_stmt_error(stmt)[0]) ~~~ ~~~ { ~~~ ~~~ ? // an error occurred ~~~ ~~~ } ~~~ 通過重新編譯MySQL客戶端庫,可更改客戶端錯誤消息的語言。目前,能夠選擇數種語言之一顯示錯誤消息。 **返回值** 描述了錯誤的字符串。如果未出現錯誤,返回空字符串。 **錯誤** 無。 #### 25.2.7.10.?mysql_stmt_execute() int mysql_stmt_execute(MYSQL_STMT *stmt) **描述** mysql_stmt_execute()執行與語句句柄相關的預處理查詢。在該調用期間,將當前綁定的參數標記符的值發送到服務器,服務器用新提供的數據替換標記符。 如果語句是UPDATE、DELETE或INSERT,通過調用mysql_stmt_affected_rows(),可發現更改、刪除或插入的總行數。如果這是諸如SELECT等能生成結果集的語句,調用任何其他能導致查詢處理的函數之前,必須調用mysql_stmt_fetch()來獲取數據。關于如何獲取結果的更多信息,請參見[25.2.7.11節,“mysql_stmt_fetch()”](# "25.2.7.11.?mysql_stmt_fetch()")。 對于生成結果集的語句,執行語句之前,可通過調用mysql_stmt_attr_set(),請求mysql_stmt_execute()為語句打開光標。如果多次執行某一語句,在打開新的光標前,mysql_stmt_execute()將關閉任何已打開的光標。 **返回值** 如果執行成功,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_OUT_OF_MEMORY 內存溢出。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 **示例:** 在下面的示例中,介紹了使用mysql_stmt_init()、mysql_stmt_prepare()、mysql_stmt_param_count()、mysql_stmt_bind_param()、mysql_stmt_execute()、以及mysql_stmt_affected_rows()創建和填充表的方法。假定mysql變量具有有效的連接句柄。 ~~~ #define STRING_SIZE 50 ~~~ ~~~ ? ~~~ ~~~ #define DROP_SAMPLE_TABLE "DROP TABLE IF EXISTS test_table" ~~~ ~~~ #define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT,\ ~~~ ~~~ ???????????????????????????????????????????????? col2 VARCHAR(40),\ ~~~ ~~~ ???????????????????????????????????????????????? col3 SMALLINT,\ ~~~ ~~~ ???????????????????????????????????????????????? col4 TIMESTAMP)" ~~~ ~~~ #define INSERT_SAMPLE "INSERT INTO test_table(col1,col2,col3) VALUES(?,?,?)" ~~~ ~~~ ? ~~~ ~~~ MYSQL_STMT??? *stmt; ~~~ ~~~ MYSQL_BIND??? bind[3]; ~~~ ~~~ my_ulonglong? affected_rows; ~~~ ~~~ int?????????? param_count; ~~~ ~~~ short???????? small_data; ~~~ ~~~ int?????????? int_data; ~~~ ~~~ char????????? str_data[STRING_SIZE]; ~~~ ~~~ unsigned long str_length; ~~~ ~~~ my_bool?????? is_null; ~~~ ~~~ ? ~~~ ~~~ if (mysql_query(mysql, DROP_SAMPLE_TABLE)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " DROP TABLE failed\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_error(mysql)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ if (mysql_query(mysql, CREATE_SAMPLE_TABLE)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " CREATE TABLE failed\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_error(mysql)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Prepare an INSERT query with 3 parameters */ ~~~ ~~~ /* (the TIMESTAMP column is not named; the server */ ~~~ ~~~ /*? sets it to the current date and time) */ ~~~ ~~~ stmt = mysql_stmt_init(mysql); ~~~ ~~~ if (!stmt) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_init(), out of memory\n"); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ if (mysql_stmt_prepare(stmt, INSERT_SAMPLE, strlen(INSERT_SAMPLE))) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_prepare(), INSERT failed\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ fprintf(stdout, " prepare, INSERT successful\n"); ~~~ ~~~ ? ~~~ ~~~ /* Get the parameter count from the statement */ ~~~ ~~~ param_count= mysql_stmt_param_count(stmt); ~~~ ~~~ fprintf(stdout, " total parameters in INSERT: %d\n", param_count); ~~~ ~~~ ? ~~~ ~~~ if (param_count != 3) /* validate parameter count */ ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " invalid parameter count returned by MySQL\n"); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Bind the data for all 3 parameters */ ~~~ ~~~ ? ~~~ ~~~ memset(bind, 0, sizeof(bind)); ~~~ ~~~ ? ~~~ ~~~ /* INTEGER PARAM */ ~~~ ~~~ /* This is a number type, so there is no need to specify buffer_length */ ~~~ ~~~ bind[0].buffer_type= MYSQL_TYPE_LONG; ~~~ ~~~ bind[0].buffer= (char *)&int_data; ~~~ ~~~ bind[0].is_null= 0; ~~~ ~~~ bind[0].length= 0; ~~~ ~~~ ? ~~~ ~~~ /* STRING PARAM */ ~~~ ~~~ bind[1].buffer_type= MYSQL_TYPE_STRING; ~~~ ~~~ bind[1].buffer= (char *)str_data; ~~~ ~~~ bind[1].buffer_length= STRING_SIZE; ~~~ ~~~ bind[1].is_null= 0; ~~~ ~~~ bind[1].length= &str_length; ~~~ ~~~ ? ~~~ ~~~ /* SMALLINT PARAM */ ~~~ ~~~ bind[2].buffer_type= MYSQL_TYPE_SHORT; ~~~ ~~~ bind[2].buffer= (char *)&small_data; ~~~ ~~~ bind[2].is_null= &is_null; ~~~ ~~~ bind[2].length= 0; ~~~ ~~~ ? ~~~ ~~~ /* Bind the buffers */ ~~~ ~~~ if (mysql_stmt_bind_param(stmt, bind)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_bind_param() failed\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Specify the data values for the first row */ ~~~ ~~~ int_data= 10;???????????? /* integer */ ~~~ ~~~ strncpy(str_data, "MySQL", STRING_SIZE); /* string? */ ~~~ ~~~ str_length= strlen(str_data); ~~~ ~~~ ? ~~~ ~~~ /* INSERT SMALLINT data as NULL */ ~~~ ~~~ is_null= 1; ~~~ ~~~ ? ~~~ ~~~ /* Execute the INSERT statement - 1*/ ~~~ ~~~ if (mysql_stmt_execute(stmt)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_execute(), 1 failed\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Get the total number of affected rows */ ~~~ ~~~ affected_rows= mysql_stmt_affected_rows(stmt); ~~~ ~~~ fprintf(stdout, " total affected rows(insert 1): %lu\n", ~~~ ~~~ ??????????????? (unsigned long) affected_rows); ~~~ ~~~ ? ~~~ ~~~ if (affected_rows != 1) /* validate affected rows */ ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " invalid affected rows by MySQL\n"); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Specify data values for second row, then re-execute the statement */ ~~~ ~~~ int_data= 1000; ~~~ ~~~ strncpy(str_data, "The most popular Open Source database", STRING_SIZE); ~~~ ~~~ str_length= strlen(str_data); ~~~ ~~~ small_data= 1000;???????? /* smallint */ ~~~ ~~~ is_null= 0;?????????????? /* reset */ ~~~ ~~~ ? ~~~ ~~~ /* Execute the INSERT statement - 2*/ ~~~ ~~~ if (mysql_stmt_execute(stmt)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_execute, 2 failed\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Get the total rows affected */ ~~~ ~~~ affected_rows= mysql_stmt_affected_rows(stmt); ~~~ ~~~ fprintf(stdout, " total affected rows(insert 2): %lu\n", ~~~ ~~~ ??????????????? (unsigned long) affected_rows); ~~~ ~~~ ? ~~~ ~~~ if (affected_rows != 1) /* validate affected rows */ ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " invalid affected rows by MySQL\n"); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Close the statement */ ~~~ ~~~ if (mysql_stmt_close(stmt)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " failed while closing the statement\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ **注釋**:關于使用預處理語句函數的完整示例,請參見文件tests/mysql_client_test.c。該文件可從MySQL源碼分發版獲得,或從BitKeeper源碼倉庫獲得。 #### 25.2.7.11.?mysql_stmt_fetch() int mysql_stmt_fetch(MYSQL_STMT *stmt) **描述** mysql_stmt_fetch()返回結果集中的下一行。僅能當結果集存在時調用它,也就是說,調用了能創建結果集的mysql_stmt_execute()之后,或當mysql_stmt_execute()對整個結果集即行緩沖處理后調用了mysql_stmt_store_result()。 使用mysql_stmt_bind_result()綁定的緩沖,mysql_stmt_fetch()返回行數據。對于當前列集合中的所有列,它將返回緩沖內的數據,并將長度返回到長度指針。 調用mysql_stmt_fetch()之前,應用程序必須綁定所有列。 如果獲取的數據值是NULL值,對應MYSQL_BIND結構的*is_null值將包含TRUE (1)。否則,將根據應用程序指定的緩沖類型,在*buffer和*length內返回數據及其長度。每個數值類型和臨時類型都有固定的長度,請參見下面的表格。字符串類型的長度取決于由data_length指明的實際數據值的長度。 <table border="1" cellpadding="0" id="table14"><tr><td> <p><strong> <span>類型</span></strong></p></td> <td> <p><strong> <span>長度</span></strong></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TINY</span></p></td> <td> <p><span>1</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_SHORT</span></p></td> <td> <p><span>2</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_LONG</span></p></td> <td> <p><span>4</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_LONGLONG</span></p></td> <td> <p><span>8</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_FLOAT</span></p></td> <td> <p><span>4</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DOUBLE</span></p></td> <td> <p><span>8</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_TIME</span></p></td> <td> <p> <span>sizeof(MYSQL_TIME)</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DATE</span></p></td> <td> <p> <span>sizeof(MYSQL_TIME)</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_DATETIME</span></p></td> <td> <p> <span>sizeof(MYSQL_TIME)</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_STRING</span></p></td> <td> <p> <span>data length</span></p></td> </tr><tr><td> <p> <span>MYSQL_TYPE_BLOB</span></p></td> <td> <p> <span>data_length</span></p></td> </tr></table> **返回值** <table border="1" cellpadding="0" id="table15"><tr><td> <p><strong> <span>返回值</span></strong></p></td> <td> <p><strong> <span>描述</span></strong></p></td> </tr><tr><td> <p><span>0</span></p></td> <td> <p>成功,數據被提取到應用程序數據緩沖區。</p></td> </tr><tr><td> <p><span>1</span></p></td> <td> <p>出現錯誤。通過調用<span>mysql_stmt_errno()</span>和<span><span>mysql_stmt_error()</span>,可獲取錯誤代碼和錯誤消息。</span></p></td> </tr><tr><td> <p> <span>MYSQL_NO_DATA</span></p></td> <td> <p>不存在行/數據。</p></td> </tr><tr><td> <p> <span>MYSQL_DATA_TRUNCATED</span></p></td> <td> <p>出現數據截短。</p></td> </tr></table> 不返回MYSQL_DATA_TRUNCATED,除非用mysql_options()啟用了截短通報功能。返回該值時,為了確定截短的參數是哪個,可檢查MYSQL_BIND參數結構的錯誤成員。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_OUT_OF_MEMORY 內存溢出。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 ·???????? CR_UNSUPPORTED_PARAM_TYPE 緩沖類型為MYSQL_TYPE_DATE、MYSQL_TYPE_TIME、MYSQL_TYPE_DATETIME、或MYSQL_TYPE_TIMESTAMP,但數據類型不是DATE、TIME、DATETIME、或TIMESTAMP。 ·???????? 從mysql_stmt_bind_result()返回所有其他不支持的轉換錯誤。 **示例:** 在下面的示例中,介紹了使用mysql_stmt_result_metadata()、mysql_stmt_bind_result()和mysql_stmt_fetch()從表中獲取數據的方法。(在本示例中,將檢索在[25.2.7.10節,“mysql_stmt_execute()”](# "25.2.7.10.?mysql_stmt_execute()")一節的示例中插入的兩行內容)。假定mysql變量具有有效的連接句柄。 ~~~ #define STRING_SIZE 50 ~~~ ~~~ ? ~~~ ~~~ #define SELECT_SAMPLE "SELECT col1, col2, col3, col4 FROM test_table" ~~~ ~~~ ? ~~~ ~~~ MYSQL_STMT??? *stmt; ~~~ ~~~ MYSQL_BIND??? bind[4]; ~~~ ~~~ MYSQL_RES???? *prepare_meta_result; ~~~ ~~~ MYSQL_TIME??? ts; ~~~ ~~~ unsigned long length[4]; ~~~ ~~~ int?????????? param_count, column_count, row_count; ~~~ ~~~ short???????? small_data; ~~~ ~~~ int?????????? int_data; ~~~ ~~~ char????????? str_data[STRING_SIZE]; ~~~ ~~~ my_bool?????? is_null[4]; ~~~ ~~~ ? ~~~ ~~~ /* Prepare a SELECT query to fetch data from test_table */ ~~~ ~~~ stmt = mysql_stmt_init(mysql); ~~~ ~~~ if (!stmt) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_init(), out of memory\n"); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ if (mysql_stmt_prepare(stmt, SELECT_SAMPLE, strlen(SELECT_SAMPLE))) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_prepare(), SELECT failed\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ fprintf(stdout, " prepare, SELECT successful\n"); ~~~ ~~~ ? ~~~ ~~~ /* Get the parameter count from the statement */ ~~~ ~~~ param_count= mysql_stmt_param_count(stmt); ~~~ ~~~ fprintf(stdout, " total parameters in SELECT: %d\n", param_count); ~~~ ~~~ ? ~~~ ~~~ if (param_count != 0) /* validate parameter count */ ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " invalid parameter count returned by MySQL\n"); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Fetch result set meta information */ ~~~ ~~~ prepare_meta_result = mysql_stmt_result_metadata(stmt); ~~~ ~~~ if (!prepare_meta_result) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, ~~~ ~~~ ???????? " mysql_stmt_result_metadata(), returned no meta information\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Get total columns in the query */ ~~~ ~~~ column_count= mysql_num_fields(prepare_meta_result); ~~~ ~~~ fprintf(stdout, " total columns in SELECT statement: %d\n", column_count); ~~~ ~~~ ? ~~~ ~~~ if (column_count != 4) /* validate column count */ ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " invalid column count returned by MySQL\n"); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Execute the SELECT query */ ~~~ ~~~ if (mysql_stmt_execute(stmt)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_execute(), failed\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Bind the result buffers for all 4 columns before fetching them */ ~~~ ~~~ ? ~~~ ~~~ memset(bind, 0, sizeof(bind)); ~~~ ~~~ ? ~~~ ~~~ /* INTEGER COLUMN */ ~~~ ~~~ bind[0].buffer_type= MYSQL_TYPE_LONG; ~~~ ~~~ bind[0].buffer= (char *)&int_data; ~~~ ~~~ bind[0].is_null= &is_null[0]; ~~~ ~~~ bind[0].length= &length[0]; ~~~ ~~~ ? ~~~ ~~~ /* STRING COLUMN */ ~~~ ~~~ bind[1].buffer_type= MYSQL_TYPE_STRING; ~~~ ~~~ bind[1].buffer= (char *)str_data; ~~~ ~~~ bind[1].buffer_length= STRING_SIZE; ~~~ ~~~ bind[1].is_null= &is_null[1]; ~~~ ~~~ bind[1].length= &length[1]; ~~~ ~~~ ? ~~~ ~~~ /* SMALLINT COLUMN */ ~~~ ~~~ bind[2].buffer_type= MYSQL_TYPE_SHORT; ~~~ ~~~ bind[2].buffer= (char *)&small_data; ~~~ ~~~ bind[2].is_null= &is_null[2]; ~~~ ~~~ bind[2].length= &length[2]; ~~~ ~~~ ? ~~~ ~~~ /* TIMESTAMP COLUMN */ ~~~ ~~~ bind[3].buffer_type= MYSQL_TYPE_TIMESTAMP; ~~~ ~~~ bind[3].buffer= (char *)&ts; ~~~ ~~~ bind[3].is_null= &is_null[3]; ~~~ ~~~ bind[3].length= &length[3]; ~~~ ~~~ ? ~~~ ~~~ /* Bind the result buffers */ ~~~ ~~~ if (mysql_stmt_bind_result(stmt, bind)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_bind_result() failed\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Now buffer all results to client */ ~~~ ~~~ if (mysql_stmt_store_result(stmt)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_store_result() failed\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Fetch all rows */ ~~~ ~~~ row_count= 0; ~~~ ~~~ fprintf(stdout, "Fetching results ...\n"); ~~~ ~~~ while (!mysql_stmt_fetch(stmt)) ~~~ ~~~ { ~~~ ~~~ ? row_count++; ~~~ ~~~ ? fprintf(stdout, "? row %d\n", row_count); ~~~ ~~~ ? ~~~ ~~~ ? /* column 1 */ ~~~ ~~~ ? fprintf(stdout, "?? column1 (integer)? : "); ~~~ ~~~ ? if (is_null[0]) ~~~ ~~~ ??? fprintf(stdout, " NULL\n"); ~~~ ~~~ ? else ~~~ ~~~ ??? fprintf(stdout, " %d(%ld)\n", int_data, length[0]); ~~~ ~~~ ? ~~~ ~~~ ? /* column 2 */ ~~~ ~~~ ? fprintf(stdout, "?? column2 (string)?? : "); ~~~ ~~~ ? if (is_null[1]) ~~~ ~~~ ??? fprintf(stdout, " NULL\n"); ~~~ ~~~ ? else ~~~ ~~~ ??? fprintf(stdout, " %s(%ld)\n", str_data, length[1]); ~~~ ~~~ ? ~~~ ~~~ ? /* column 3 */ ~~~ ~~~ ? fprintf(stdout, "?? column3 (smallint) : "); ~~~ ~~~ ? if (is_null[2]) ~~~ ~~~ ??? fprintf(stdout, " NULL\n"); ~~~ ~~~ ? else ~~~ ~~~ ??? fprintf(stdout, " %d(%ld)\n", small_data, length[2]); ~~~ ~~~ ? ~~~ ~~~ ? /* column 4 */ ~~~ ~~~ ? fprintf(stdout, "?? column4 (timestamp): "); ~~~ ~~~ ? if (is_null[3]) ~~~ ~~~ ??? fprintf(stdout, " NULL\n"); ~~~ ~~~ ? else ~~~ ~~~ ??? fprintf(stdout, " %04d-%02d-%02d %02d:%02d:%02d (%ld)\n", ~~~ ~~~ ???????????????????? ts.year, ts.month, ts.day, ~~~ ~~~ ???????????????????? ts.hour, ts.minute, ts.second, ~~~ ~~~ ???????????????????? length[3]); ~~~ ~~~ ? fprintf(stdout, "\n"); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Validate rows fetched */ ~~~ ~~~ fprintf(stdout, " total rows fetched: %d\n", row_count); ~~~ ~~~ if (row_count != 2) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " MySQL failed to return all rows\n"); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Free the prepared result metadata */ ~~~ ~~~ mysql_free_result(prepare_meta_result); ~~~ ~~~ ? ~~~ ~~~ ? ~~~ ~~~ /* Close the statement */ ~~~ ~~~ if (mysql_stmt_close(stmt)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " failed while closing the statement\n"); ~~~ ~~~ ? fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ #### 25.2.7.12.?mysql_stmt_fetch_column() int mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, unsigned int column, unsigned long offset) **描述** 從當前結果集行獲取1列。“bind”提供了應將數據置于其中的緩沖。其設置方法應與設置mysql_stmt_bind_result()的相同。“column”指明了將獲取哪個列。第1列編號為0。“offset”是數據值內的偏移量,將從該處開始檢索數據。可將其用于獲取碎片形式的數據值。值開始部分的偏移量為0。 **返回值** 如果成功獲取了值,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_INVALID_PARAMETER_NO Invalid column number. ·???????? CR_NO_DATA 已抵達結果集的末尾。 #### 25.2.7.13.?mysql_stmt_field_count() unsigned int mysql_stmt_field_count(MYSQL_STMT *stmt) **描述** 為語句處理程序返回關于最近語句的行數。對于諸如INSERT或DELETE等不生成結果集的語句,該值為0。 通過調用mysql_stmt_prepare()準備好了語句后,可調用mysql_stmt_field_count()。 **返回值** 表示結果集中行數的無符號整數。 **錯誤** 無。 #### 25.2.7.14.?mysql_stmt_free_result() my_bool mysql_stmt_free_result(MYSQL_STMT *stmt) **描述** 釋放與執行預處理語句生成的結果集有關的內存。對于該語句,如果存在打開的光標,mysql_stmt_free_result()將關閉它。 **返回值** 如果成功釋放了結果集,返回0。如果出現錯誤,返回非0值。 **錯誤** #### 25.2.7.15.?mysql_stmt_init() MYSQL_STMT *mysql_stmt_init(MYSQL *mysql) **描述** 創建MYSQL_STMT句柄。對于該句柄,應使用mysql_stmt_close(MYSQL_STMT *)釋放。 **返回值** 成功時,返回指向MYSQL_STMT結構的指針。如果內存溢出,返回NULL。 **錯誤** ·???????? CR_OUT_OF_MEMORY 內存溢出。 #### 25.2.7.16.?mysql_stmt_insert_id() my_ulonglong mysql_stmt_insert_id(MYSQL_STMT *stmt) **描述** 返回預處理INSERT或UPDATE語句為AUTO_INCREMENT列生成的值。在包含AUTO_INCREMENT字段的表上執行了預處理INSERT語句后,使用該函數。 更多信息,請參見[25.2.3.36節,“mysql_insert_id()”](# "25.2.3.36.?mysql_insert_id()")。 **返回值** 為在執行預處理語句期間自動生成或明確設置的AUTO_INCREMENT列返回值,或由LAST_INSERT_ID(*expr*)函數生成的值。如果語句未設置AUTO_INCREMENT值,返回值不確定。 **錯誤** 無。 #### 25.2.7.17.?mysql_stmt_num_rows() my_ulonglong mysql_stmt_num_rows(MYSQL_STMT *stmt) **描述** 返回結果集中的行數。 mysql_stmt_num_rows()的用法取決于是否使用了mysql_stmt_store_result()來對語句句柄中的全部結果集進行了緩沖處理。 如果使用了mysql_stmt_store_result(),可立刻調用mysql_stmt_num_rows()。 **返回值** 結果集中的行數。 **錯誤** 無。 #### 25.2.7.18.?mysql_stmt_param_count() unsigned long mysql_stmt_param_count(MYSQL_STMT *stmt) **描述** 返回預處理語句中參數標記符的數目。 **返回值** 表示語句中參數數目的無符號長整數。 **錯誤** 無。 **示例:** 關于mysql_stmt_param_count()的用法,請參見[25.2.7.10節,“mysql_stmt_execute()”](# "25.2.7.10.?mysql_stmt_execute()")中給出的示例。 #### 25.2.7.19.?mysql_stmt_param_metadata() MYSQL_RES *mysql_stmt_param_metadata(MYSQL_STMT *stmt) 該函數目前不做任何事。 **描述** **返回值** **錯誤** #### 25.2.7.20.?mysql_stmt_prepare() int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length) **描述** 給定mysql_stmt_init()返回的語句句柄,準備字符串查詢指向的SQL語句,并返回狀態值。字符串長度應由“length”參量給出。字符串必須包含1條SQL語句。不應為語句添加終結用分號(‘;’)或\g。 通過將問號字符“?”嵌入到SQL字符串的恰當位置,應用程序可包含SQL語句中的一個或多個參數標記符。 標記符僅在SQL語句中的特定位置時才是合法的。例如,它可以在INSERT語句的VALUES()列表中(為行指定列值),或與WHERE子句中某列的比較部分(用以指定比較值)。但是,對于ID(例如表名或列名),不允許使用它們,不允許指定二進制操作符(如等于號“=”)的操作數。后一個限制是有必要的,原因在于,無法確定參數類型。一般而言,參數僅在DML(數據操作語言)語句中才是合法的,在DDL(數據定義語言)語句中不合法。 執行語句之前,必須使用mysql_stmt_bind_param(),將參數標記符與應用程序變量綁定在一起。 **返回值** 如果成功處理了語句,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_OUT_OF_MEMORY 內存溢出。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 如果準備操作失敗(即mysql_stmt_prepare()返回非0值),可通過調用mysql_stmt_error()獲取錯誤消息。 **示例:** 關于mysql_stmt_prepare()的用法,請參見[25.2.7.10節,“mysql_stmt_execute()”](# "25.2.7.10.?mysql_stmt_execute()")中給出的示例。 #### 25.2.7.21.?mysql_stmt_reset() my_bool mysql_stmt_reset(MYSQL_STMT *stmt) **描述** 在客戶端和服務器上,將預處理語句復位為完成準備后的狀態。主要用于復位用mysql_stmt_send_long_data()發出的數據。對于語句,任何已打開的光標將被關閉。 要想重新準備用于另一查詢的語句,可使用mysql_stmt_prepare()。 **返回值** 如果語句成功復位,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 #### 25.2.7.22.?mysql_stmt_result_metadata() MYSQL_RES *mysql_stmt_result_metadata(MYSQL_STMT *stmt) **描述** 如果傳遞給mysql_stmt_prepare()的語句能夠成生結果集,mysql_stmt_result_metadata()將以指針的形式返回結果集元數據,該指針指向MYSQL_RES結構,可用于處理元信息,如總的字段數以及單獨的字段信息。該結果集指針可作為參量傳遞給任何基于字段且用于處理結果集元數據的API函數,如: ·???????? mysql_num_fields() ·???????? mysql_fetch_field() ·???????? mysql_fetch_field_direct() ·???????? mysql_fetch_fields() ·???????? mysql_field_count() ·???????? mysql_field_seek() ·???????? mysql_field_tell() ·???????? mysql_free_result() 完成操作后,應釋放結果集結構,可通過將其傳遞給mysql_free_result()完成。它與釋放通過mysql_store_result()調用獲得的結果集的方法類似。 mysql_stmt_result_metadata()返回的結果集僅包含元數據。不含任何行結果。與mysql_stmt_fetch()一起使用語句句柄,可獲取行。 **返回值** MYSQL_RES結果結構。如果不存在關于預處理查詢的任何元信息,返回NULL。 **錯誤** ·???????? CR_OUT_OF_MEMORY 內存溢出。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 **示例:** 關于mysql_stmt_result_metadata()的用法,請參見[25.2.7.11節,“mysql_stmt_fetch()”](# "25.2.7.11.?mysql_stmt_fetch()")中給出的示例。 #### 25.2.7.23.?mysql_stmt_row_seek() MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset) **描述** 將行光標設置到語句結果集中的任意行。“offset”值是行偏移的值,行偏移應是從mysql_stmt_row_tell()或mysql_stmt_row_seek()返回的值。該值不是行編號,如果打算按編號查找結果集中的行,可使用mysql_stmt_data_seek()取而代之。 該函數要求結果集結構包含查詢的全部結果,以便mysql_stmt_row_seek()能夠僅與mysql_stmt_store_result()一起使用。 **返回值** 行光標的前一個值。可以將該值換遞給后續的mysql_stmt_row_seek()調用。 **錯誤** 無。 #### 25.2.7.24.?mysql_stmt_row_tell() MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT *stmt) **描述** 返回針對前一個mysql_stmt_fetch()的行光標的當前位置。該值可用作mysql_stmt_row_seek()的參量。 僅應在mysql_stmt_store_result()之后使用mysql_stmt_row_tell()。 **返回值** 行光標的當前偏移量。 **錯誤** 無。 #### 25.2.7.25.?mysql_stmt_send_long_data() my_bool mysql_stmt_send_long_data(MYSQL_STMT *stmt, unsigned int parameter_number, const char *data, unsigned long length) **描述** 允許應用程序分段地(分塊)將參數數據發送到服務器。可以多次調用該函數,以便發送關于某一列的字符或二進制數據的不同部分,列必須是TEXT或BLOB數據類型之一。 “parameter_number”指明了與數據關聯的參數。參數從0開始編號。“data”是指向包含將要發送的數據的緩沖區的指針,“length”指明了緩沖區內的字節數。 **注釋:**自上一個mysql_stmt_execute()或mysql_stmt_reset()后,對于與mysql_stmt_send_long_data()一起使用的所有參數,下一個mysql_stmt_execute()調用將忽略綁定緩沖。 如果希望復位/忽略已發送的數據,可使用mysql_stmt_reset()。請參見[25.2.7.21節,“mysql_stmt_reset()”](# "25.2.7.21.?mysql_stmt_reset()")。 **返回值** 如果成功地將數據發送到服務器,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_OUT_OF_MEMORY 內存溢出。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 **示例:** 在下面的示例中,介紹了以信息塊形式為TEXT列發送數據的方法。它會將數據值“MySQL,最流行的開放源碼數據庫”插入到text_column列中。假定mysql變量具有有效的連接句柄。 ~~~ #define INSERT_QUERY "INSERT INTO test_long_data(text_column) VALUES(?)" ~~~ ~~~ ? ~~~ ~~~ MYSQL_BIND bind[1]; ~~~ ~~~ long?????? length; ~~~ ~~~ ? ~~~ ~~~ smtt = mysql_stmt_init(mysql); ~~~ ~~~ if (!stmt) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, " mysql_stmt_init(), out of memory\n"); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ if (mysql_stmt_prepare(stmt, INSERT_QUERY, strlen(INSERT_QUERY))) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed"); ~~~ ~~~ ? fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ memset(bind, 0, sizeof(bind)); ~~~ ~~~ bind[0].buffer_type= MYSQL_TYPE_STRING; ~~~ ~~~ bind[0].length= &length; ~~~ ~~~ bind[0].is_null= 0; ~~~ ~~~ ? ~~~ ~~~ /* Bind the buffers */ ~~~ ~~~ if (mysql_stmt_bind_param(stmt, bind)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, "\n param bind failed"); ~~~ ~~~ ? fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Supply data in chunks to server */ ~~~ ~~~ if (!mysql_stmt_send_long_data(stmt,0,"MySQL",5)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, "\n send_long_data failed"); ~~~ ~~~ ? fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Supply the next piece of data */ ~~~ ~~~ if (mysql_stmt_send_long_data(stmt,0," - The most popular Open Source database",40)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, "\n send_long_data failed"); ~~~ ~~~ ? fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ ~~~ ? ~~~ ~~~ /* Now, execute the query */ ~~~ ~~~ if (mysql_stmt_execute(stmt)) ~~~ ~~~ { ~~~ ~~~ ? fprintf(stderr, "\n mysql_stmt_execute failed"); ~~~ ~~~ ? fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); ~~~ ~~~ ? exit(0); ~~~ ~~~ } ~~~ #### 25.2.7.26.?mysql_stmt_sqlstate() const char *mysql_stmt_sqlstate(MYSQL_STMT *stmt) **描述** 對于由stmt指定的語句,mysql_stmt_sqlstate()返回由Null終結的字符串,該字符串包含針對最近調用預處理語句API函數的SQLSTATE錯誤代碼,該函數或成功或失敗。錯誤代碼由5個字符構成。"00000"表示“無錯誤”。這些值由ANSI SQL和ODBC指定。關于可能值的列表,請參見[附錄B:錯誤代碼和消息](# "Appendix?B.?Error Codes and Messages")。 注意,并非所有的MySQL錯誤均會被映射到SQLSTATE代碼。值"HY000"(一般錯誤)用于未映射的錯誤。 **返回值** 包含SQLSTATE錯誤代碼、由Null終結的字符串。 #### 25.2.7.27.?mysql_stmt_store_result() int mysql_stmt_store_result(MYSQL_STMT *stmt) **描述** 對于成功生成結果集的所有語句(SELECT、SHOW、DESCRIBE、EXPLAIN),而且僅當你打算對客戶端的全部結果集進行緩沖處理時,必須調用mysql_stmt_store_result(),以便后續的mysql_stmt_fetch()調用能返回緩沖數據。 對于其他語句,沒有必要調用mysql_stmt_store_result(),但如果調用了它,也不會造成任何傷害或導致任何性能問題。通過檢查mysql_stmt_result_metadata()是否返回NULL,可檢測語句是否生成了結果集。更多信息,請參見[25.2.7.22節,“mysql_stmt_result_metadata()”](# "25.2.7.22.?mysql_stmt_result_metadata()")。 **注釋:默認情況下,對于**mysql_stmt_store_result()中的所有列,MySQL不計算MYSQL_FIELD->max_length,這是因為,計算它會顯著降低mysql_stmt_store_result()的性能,而且大多數應用程序不需要max_length。如果打算更新max_length,可通過調用mysql_stmt_attr_set(MYSQL_STMT, STMT_ATTR_UPDATE_MAX_LENGTH, &flag)啟用它。請參見[25.2.7.3節,“mysql_stmt_attr_set()”](# "25.2.7.3.?mysql_stmt_attr_set()")。 **返回值** 如果成功完成了對結果的緩沖處理,返回0。如果出現錯誤,返回非0值。 **錯誤** ·???????? CR_COMMANDS_OUT_OF_SYNC 以不恰當的順序執行了命令。 ·???????? CR_OUT_OF_MEMORY 內存溢出。 ·???????? CR_SERVER_GONE_ERROR MySQL服務器不可用。 ·???????? CR_SERVER_LOST 在查詢過程中,與服務器的連接丟失。 ·???????? CR_UNKNOWN_ERROR 出現未知錯誤。 ### 25.2.8.?C API預處理語句方面的問題 下面列出了一些目前已知的與預處理語句有關的問題: ·???????? TIME、TIMESTAMP和DATETIME不支持秒部分,例如來自DATE_FORMAT()的秒部分。 ·???????? 將整數轉換為字符串時,在某些情況下,當MySQL不打印前導0時,可與預處理語句一起使用ZEROFILL。例如,與MIN(number-with-zerofill)一起。 ·???????? 將浮點數轉換為客戶端中的字符串時,被轉換值最右側的位可能會與原始值的有所不同。 ·???????? * 預處理語句不使用查詢高速緩沖,即使當查詢不含任何占位符時也同樣。。*請參見[5.13.1節,“查詢高速緩沖如何工作”](# "5.13.1.?How the Query Cache Operates")。 ### 25.2.9.?多查詢執行的C API處理 MySQL 5.1支持在單個查詢字符串中指定的多語句的執行。要想與給定的連接一起使用該功能,打開連接時,必須將標志參數中的CLIENT_MULTI_STATEMENTS選項指定給mysql_real_connect()。也可以通過調用mysql_set_server_option(MYSQL_OPTION_MULTI_STATEMENTS_ON),為已有的連接設置它。 在默認情況下,mysql_query()和mysql_real_query()僅返回第1個查詢的狀態,并能使用mysql_more_results()和mysql_next_result()對后續查詢的狀態進行處理。 ~~~ /* Connect to server with option CLIENT_MULTI_STATEMENTS */ ~~~ ~~~ mysql_real_connect(..., CLIENT_MULTI_STATEMENTS); ~~~ ~~~ ? ~~~ ~~~ /* Now execute multiple queries */ ~~~ ~~~ mysql_query(mysql,"DROP TABLE IF EXISTS test_table;\ ~~~ ~~~ ?????????????????? CREATE TABLE test_table(id INT);\ ~~~ ~~~ ?????????????????? INSERT INTO test_table VALUES(10);\ ~~~ ~~~ ?????????????????? UPDATE test_table SET id=20 WHERE id=10;\ ~~~ ~~~ ?????????????????? SELECT * FROM test_table;\ ~~~ ~~~ ??????????????? ???DROP TABLE test_table"); ~~~ ~~~ do ~~~ ~~~ { ~~~ ~~~ ? /* Process all results */ ~~~ ~~~ ? ... ~~~ ~~~ ? printf("total affected rows: %lld", mysql_affected_rows(mysql)); ~~~ ~~~ ? ... ~~~ ~~~ ? if (!(result= mysql_store_result(mysql))) ~~~ ~~~ ? { ~~~ ~~~ ???? printf(stderr, "Got fatal error processing query\n"); ~~~ ~~~ ???? exit(1); ~~~ ~~~ ? } ~~~ ~~~ ? process_result_set(result); /* client function */ ~~~ ~~~ ? mysql_free_result(result); ~~~ ~~~ } while (!mysql_next_result(mysql)); ~~~ 多語句功能可與mysql_query()或mysql_real_query()一起使用。它不能與預處理語句接口一起使用。按照定義,預處理語句僅能與包含單個語句的字符串一起使用。 ### 25.2.10.?日期和時間值的C API處理 二進制協議允許你使用MYSQL_TIME結構發送和接受日期和時間值(DATE、TIME、DATETIME和TIMESTAMP)。在[25.2.5節,“C API預處理語句的數據類型”](# "25.2.5.?C API Prepared Statement Data types")中,介紹了該結構的成員。 要想發送臨時數據值,可使用mysql_stmt_prepare()創建預處理語句。然后,在調用mysql_stmt_execute()執行語句之前,可采用下述步驟設置每個臨時參數: 1.??? 在與數據值相關的MYSQL_BIND結構中,將buffer_type成員設置為相應的類型,該類型指明了發送的臨時值類型。對于DATE、TIME、DATETIME或TIMESTAMP值,將buffer_type分別設置為MYSQL_TYPE_DATE、MYSQL_TYPE_TIME、MYSQL_TYPE_DATETIME或MYSQL_TYPE_TIMESTAMP。 2.??? 將MYSQL_BIND結構的緩沖成員設置為用于傳遞臨時值的MYSQL_TIME結構的地址。 3.??? 填充MYSQL_TIME結構的成員,使之與打算傳遞的臨時支的類型相符。 使用mysql_stmt_bind_param()將參數數據綁定到語句。然后可調用mysql_stmt_execute()。 要想檢索臨時值,可采用類似的步驟,但應將buffer_type成員設置為打算接受的值的類型,并將緩沖成員設為應將返回值置于其中的MYSQL_TIME結構的地址。調用mysql_stmt_execute()之后,并在獲取結果之前,使用mysql_bind_results()將緩沖綁定到語句上。 下面給出了一個插入DATE、TIME和TIMESTAMP數據的簡單示例。假定mysql變量具有有效的連接句柄。 ~~~ MYSQL_TIME ts; MYSQL_BIND bind[3]; MYSQL_STMT *stmt; strmov(query, "INSERT INTO test_table(date_field, time_field, timestamp_field) VALUES(?,?,?"); stmt = mysql_stmt_init(mysql); if (!stmt) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); exit(0); } if (mysql_stmt_prepare(mysql, query, strlen(query))) { fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); } /* set up input buffers for all 3 parameters */ bind[0].buffer_type= MYSQL_TYPE_DATE; bind[0].buffer= (char *)&ts; bind[0].is_null= 0; bind[0].length= 0; ... bind[1]= bind[2]= bind[0]; ... mysql_stmt_bind_param(stmt, bind); /* supply the data to be sent in the ts structure */ ts.year= 2002; ts.month= 02; ts.day= 03; ts.hour= 10; ts.minute= 45; ts.second= 20; mysql_stmt_execute(stmt); .. ~~~ ### 25.2.11.?C API線程函數介紹 [25.2.11.1. my_init()](#)[25.2.11.2. mysql_thread_init()](#)[25.2.11.3. mysql_thread_end()](#)[25.2.11.4. mysql_thread_safe()](#) 當你打算創建線程客戶端時,需要使用下述函數。請參見[25.2.15節,“如何生成線程式客戶端”](# "25.2.15.?How to Make a Threaded Client")。 #### 25.2.11.1.?my_init() void my_init(void) **描述** 調用任何MySQL函數之前,需要在程序中調用該函數。它將初始化MySQL所需的某些全局變量。如果你正在使用線程安全客戶端庫,它還能為該線程調用mysql_thread_init()。 通過mysql_init()、mysql_library_init()、mysql_server_init()和mysql_connect(),可自動調用該函數。 **返回值** 無。 #### 25.2.11.2.?mysql_thread_init() my_bool mysql_thread_init(void) **描述** 對于每個創建的線程,需要調用該函數來初始化與線程相關的變量。 它可由my_init()和mysql_connect()自動調用。 **返回值** 如果成功,返回0,如果出現錯誤,返回非0值。 #### 25.2.11.3.?mysql_thread_end() void mysql_thread_end(void) **描述** 調用pthread_exit()來釋放mysql_thread_init()分配的內存之前,需要調用該函數。 注意,該函數不會被客戶端庫自動調用。必須明確調用它以避免內存泄漏。 **返回值** 無。 #### 25.2.11.4.?mysql_thread_safe() unsigned int mysql_thread_safe(void) **描述** 該函數指明了客戶端是否編譯為線程安全的。 **返回值** 如果客戶端是線程安全的,返回1,否則返回0。 ### 25.2.12.?C API嵌入式服務器函數介紹 [25.2.12.1. mysql_server_init()](#)[25.2.12.2. mysql_server_end()](#) 如果希望允許應用程序鏈接到嵌入式MySQL服務器庫,必須使用mysql_server_init()和mysql_server_end()函數。請參見[25.1節,“libmysqld,嵌入式MySQL服務器庫”](# "25.1.?libmysqld, the Embedded MySQL Server Library")。 但是,要想提供改進的內存管理,即使是對與“-lmysqlclient”而不是與“-lmysqld”鏈接的程序,也應包含啟用和結束庫使用的調用。mysql_library_init()和mysql_library_end()函數可用于該目的。它們實際上是使其等效于mysql_server_init()和mysql_server_end()的#define符號,但它們的名稱更清楚地指明,無論應用程序使用的是libmysqlclient或libmysqld,開始使用或結束MySQL C API庫的使用時,應調用它們。關于更多信息,請參見[25.2.2節,“C API函數概述”](# "25.2.2.?C API Function Overview")。 #### 25.2.12.1.?mysql_server_init() int mysql_server_init(int argc, char **argv, char **groups) **描述** 調用任何其他MySQL函數之前,必須在使用嵌入式服務器的程序中調用該函數。它將啟動服務器,并初始化服務器使用的任何子系統(mysys、InnoDB等)。如果未調用該函數,對mysql_init()的下一次調用將執行mysql_server_init()。如果你正在使用與MySQL一起提供的DBUG軟件包,應在調用了my_init()之后調用它。 對于main()的參量,argc和argv是類似的參量。argv的第1個元素將被忽略(典型情況下,它包含程序名)。為了方便起見,如果沒有針對服務器的命令行參量,argc可以是0。mysql_server_init()將復制參量,以便能夠在調用之后安全地摧毀argv或groups。 如果打算連接到外部服務器而不啟動嵌入式服務器,應為argc指定負值。 “groups”中以Null終結的字符串列表選擇了選項文件中的活動“groups”。請參見[4.3.2節,“使用選項文件”](# "4.3.2.?Using Option Files")。為了方便起見,groups可以是NULL,在該情況下,[server]和[embedded]組是活動的。 **示例:** ~~~ #include <mysql.h> ~~~ ~~~ #include <stdlib.h> ~~~ ~~~ ? ~~~ ~~~ static char *server_args[] = { ~~~ ~~~ ? "this_program",?????? /* this string is not used */ ~~~ ~~~ ? "--datadir=.", ~~~ ~~~ ? "--key_buffer_size=32M" ~~~ ~~~ }; ~~~ ~~~ static char *server_groups[] = { ~~~ ~~~ ? "embedded", ~~~ ~~~ ? "server", ~~~ ~~~ ? "this_program_SERVER", ~~~ ~~~ ? (char *)NULL ~~~ ~~~ }; ~~~ ~~~ ? ~~~ ~~~ int main(void) { ~~~ ~~~ ? if (mysql_server_init(sizeof(server_args) / sizeof(char *), ~~~ ~~~ ??????????????????????? server_args, server_groups)) ~~~ ~~~ ??? exit(1); ~~~ ~~~ ? ~~~ ~~~ ? /* Use any MySQL API functions here */ ~~~ ~~~ ? ~~~ ~~~ ? mysql_server_end(); ~~~ ~~~ ? ~~~ ~~~ ? return EXIT_SUCCESS; ~~~ ~~~ } ~~~ **返回值** 如果OK,返回0。如果出現錯誤,返回1。 #### 25.2.12.2.?mysql_server_end() void mysql_server_end(void) **描述** 在所有其他MySQL函數后,在程序中必須調用該函數一次。它將關閉嵌入式服務器。 **返回值** 無。 ### 25.2.13.?使用C API時的常見問題 [ 25.2.13.1. 為什么在mysql_query()返回成功后,mysql_store_result()有時會返回NULL``](#)[25.2.13.2. What Results You Can Get from a Query](#)[ 25.2.13.3. 如何獲得上次插入行的唯一ID](#)[ 25.2.13.4. 與C API有關的問題](#) #### 25.2.13.1.?為什么在mysql_query()返回成功后,mysql_store_result()有時會返回NULL`` 成功調用mysql_query()后,mysql_store_result()能夠返回NULL。出現該情況時,表明出現了下述條件之一: ·???????? 出現了malloc()故障(例如,如果結果集過大)。 ·???????? 無法讀取數據(在連接上出現了錯誤)。 ·???????? 查詢未返回數據(例如,它是INSERT、UPDATE或DELETE)。 通過調用mysql_field_count(),始終能檢查語句是否應生成非空結果。如果mysql_field_count()返回0,結果為空,而且上一個查詢是未返回值的語句(例如INSERT或DELETE)。如果mysql_field_count()返回非0值,語句應生成非空結果。關于這方面的示例,請參見mysql_field_count()函數介紹。 通過調用mysql_error()或mysql_errno(),可測試是否出現了錯誤。 #### 25.2.13.2.?What Results You Can Get from a Query 除了查詢返回的結果集外,還能獲取下述信息: ·???????? 執行INSERT、UPDATE或DELETE時,mysql_affected_rows()返回上次查詢影響的行數。 對于快速在創建,請使用TRUNCATE TABLE。 ·???????? mysql_num_rows()返回結果集中的行數。使用mysql_store_result(),一旦mysql_store_result()返回,就能調用mysql_num_rows()。使用mysql_use_result(),僅當用mysql_fetch_row()獲取了所有行后,才能調用mysql_num_rows()。 ·???????? mysql_insert_id()返回上次查詢生成的ID,該查詢使用AUTO_INCREMENT索引將行插入到表內。請參見[25.2.3.36節,“mysql_insert_id()”](# "25.2.3.36.?mysql_insert_id()")。 ·???????? 某些查詢(LOAD DATA INFILE ...、INSERT INTO ... SELECT ...、UPDATE)將返回額外信息。結果由mysql_info()返回。關于它返回的字符串格式,請參見關于mysql_info()的介紹。如果沒有額外信息,mysql_info()將返回NULL指針。 #### 25.2.13.3.?如何獲得上次插入行的唯一ID 如果將記錄插入包含AUTO_INCREMENT列的表中,通過調用mysql_insert_id()函數,可獲取保存在該列中的值。 通過執行下述代碼,可從C應用程序檢查某一值是否保存在AUTO_INCREMENT列中(假定該語句已成功執行)。它能確定查詢是否是具有AUTO_INCREMENT索引的INSERT: ~~~ if ((result = mysql_store_result(&mysql)) == 0 && ~~~ ~~~ ? ??mysql_field_count(&mysql) == 0 && ~~~ ~~~ ??? mysql_insert_id(&mysql) != 0) ~~~ ~~~ { ~~~ ~~~ ??? used_id = mysql_insert_id(&mysql); ~~~ ~~~ } ~~~ 關于更多信息,請參見[25.2.3.36節,“mysql_insert_id()”](# "25.2.3.36.?mysql_insert_id()")。 生成新的AUTO_INCREMENT值時,也能與mysql_query()一起通過執行SELECT LAST_INSERT_ID()語句獲得它,并從該語句返回的結果集檢索該值。 對于LAST_INSERT_ID(),最近生成的ID是在服務器上按連接維護的。它不會被另一個客戶端改變。即使用non-magic值(即非Null非0值)更新了另一個AUTO_INCREMENT列,也不會更改它。 如果打算使用從某一表生成的ID,并將其插入到第2個表中,可使用如下所示的SQL語句: ~~~ INSERT INTO foo (auto,text) ~~~ ~~~ ??? VALUES(NULL,'text');????????????? # generate ID by inserting NULL ~~~ ~~~ INSERT INTO foo2 (id,text) ~~~ ~~~ ??? VALUES(LAST_INSERT_ID(),'text');? # use ID in second table ~~~ 注意,mysql_insert_id()返回保存在AUTO_INCREMENT列中的值,無論該值是因存儲NULL或0而自動生成的,或是明確指定的,均如此。LAST_INSERT_ID()僅返回自動生成的AUTO_INCREMENT值。如果你保存了除NULL或0之外的確切值,不會影響LAST_INSERT_ID()返回的值。 #### 25.2.13.4.?與C API有關的問題 與C API鏈接時,在某些系統上可能出現下述錯誤: ~~~ gcc -g -o client test.o -L/usr/local/lib/mysql -lmysqlclient -lsocket -lnsl ~~~ ~~~ ? ~~~ ~~~ Undefined??????? first referenced ~~~ ~~~ symbol????????? in file ~~~ ~~~ floor??????????? /usr/local/lib/mysql/libmysqlclient.a(password.o) ~~~ ~~~ ld: fatal: Symbol referencing errors. No output written to client ~~~ 如果在你的系統上出現了該情況,必須在編譯/鏈接行的末尾增加“-lm”,通過該方式包含數學庫。 ### 25.2.14.?創建客戶端程序 如果你編譯了自己編寫的MySQL客戶端,或編譯了從第三方獲取的MySQL客戶端,必須在鏈接命令中使用“-lmysqlclient -lz”選項鏈接它們。你或許還應指定“-L”選項,通知鏈接程序到哪里找到庫。例如,如果將庫安裝到了/usr/local/mysql/lib,可在鏈接命令中使用sr/local/mysql/lib -lmysqlclient –lz。 對于使用MySQL頭文件的客戶端,編譯它們時還須指定“-I”選項(例如,-I/usr/local/mysql/include),以便編譯器能找到頭文件。 為了使在Unix平臺上編譯MySQL程序變得簡單,提供了**mysql_config**腳本。請參見[25.9.2節,“mysql_config:獲取編譯客戶端的編譯選項”](# "25.9.2.?mysql_config — Get Compile Options for Compiling Clients")。 你也可以使用它來編譯MySQL客戶端,如下所述: ~~~ CFG=/usr/local/mysql/bin/mysql_config ~~~ ~~~ sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`" ~~~ 需要使用“sh –c”,使得shell不將**mysql_config**的輸出當作1個詞對待。 ### 25.2.15.?如何生成線程式客戶端 客戶端庫總是線程安全的。最大的問題在于從套接字讀取的net.c中的子程序并不是中斷安全的。或許你可能希望用自己的告警中斷對服務器的長時間讀取,以此來解決問題。如果為SIGPIPE中斷安裝了中斷處理程序,套接字處理功能應是線程安全的。 為了避免連接中斷時放棄程序,MySQL將在首次調用mysql_server_init()、mysql_init()或mysql_connect()時屏蔽SIGPIPE。如果你打算使用自己的SIGPIPE處理程序,首先應調用mysql_server_init(),然后安裝你的處理程序, 在較舊的發布在我方網站上([http://www.mysql.com/](http://www.mysql.com/))的二進制版本中,未用線程安全的選項對客戶端庫進行正常編譯(默認情況下,編譯的Windows二進制版本是線程安全的)。較新的二進制分發版應是正常的和線程安全的客戶端庫。 為了獲得能從其他線程中斷客戶端的線程式客戶端,并在與MySQL服務器通信時設置超時,應使用“-lmysys”、“-lmystrings”和“-ldbug”庫,以及服務器使用的net_serv.o代碼。 如果你不需要使用中斷或超時,可編譯線程安全客戶端庫(mysqlclient_r)并使用它。。請參見[25.2節,“MySQL C API”](# "25.2.?MySQL C API")。在該情況下,不必擔心net_serv.o對象文件或其他MySQL庫。 使用線程式客戶端并打算使用超時或中斷時,可更好地利用thr_alarm.c文件中的子程序。如果你正在使用來自mysys庫的子程序,唯一需要記住的事是首先調用my_init()!請參見[25.2.11節,“C API線程函數介紹”](# "25.2.11.?C API Threaded Function Descriptions")。 對于除mysql_real_connect()外的所有函數,在默認情況下它們均是線程安全的。在下面的說明中,介紹了編譯線程安全客戶端庫的方法,以及以線程安全方式使用它的方法。(下面關于mysql_real_connect()的說明實際上也適用于mysql_connect(),但由于mysql_connect()已不再被重視,總應盡量使用mysql_real_connect())。 要想使mysql_real_connect()成為線程安全的,必須用下述命令再次編譯客戶端庫: ~~~ shell> ./configure --enable-thread-safe-client ~~~ 它創建了線程安全客戶端庫libmysqlclient_r。(假定你的操作系統有線程安全的gethostbyname_r()函數)。按照連接,該庫是線程安全的。可遵循下述警告,使兩個線程共享相同的連接: ·???????? 在相同的連接上,兩個線程不能同時將查詢發送到MySQL服務器。尤其是,必須確保在mysql_query()和mysql_store_result()之間,沒有使用相同連接的其他線程。 ·???????? 很多線程均能訪問由mysql_store_result()檢索的不同結果集。 ·???????? 如果使用了mysql_use_result,務必確保無其他線程正在使用相同的連接,直至關閉了結果集為止。然而,對于線程式客戶端,最好是共享相同的連接以使用mysql_store_result()。 ·???????? 如果打算在相同的連接上使用多個線程,必須在mysql_query()和mysql_store_result()調用組合上擁有互斥鎖。一旦mysql_store_result()準備就緒,可釋放鎖定,其他線程可在相同的連接上執行查詢。 ·???????? 如果使用POSIX線程進行編程,可使用pthread_mutex_lock()和pthread_mutex_unlock()來建立并釋放互斥鎖。 如果你有1個調用MySQL函數的線程,而該函數未創建與MySQL數據庫的連接,就需了解下述事宜: 調用mysql_init()或mysql_connect()時,MySQL會為調試庫使用的線程創建與線程相關的變量(尤其)。 在線程調用mysql_init()或mysql_connect()之前,如果調用了MySQL函數,該線程將沒有所需的線程類變量,而且你很可能或早或晚結束于內核轉儲。 要想使這些操作平穩工作,需要采取下述措施: 1.??? 如果程序在調用mysql_real_connect()之前需要調用任何其他MySQL函數,請在啟動程序時調用my_init()。 2.??? 調用任何MySQL函數之前,在線程處理程序中調用mysql_thread_init()。 3.??? 在線程中,調用pthread_exit()之前請調用mysql_thread_end()。這樣,就能釋放MySQL線程類變量使用的內存。 將客戶端鏈接到libmysqlclient_r時,如果存在未定義的符號,可能會出錯。在大多數情況下,其原因在于,未將線程庫包含在link/compile行上。 ### 25.3.?MySQL PHP API [ 25.3.1. 使用MySQL和PHP的常見問題](#) PHP是一種服務器端、HTML嵌入式腳本處理語言,可使用該語言創建動態網頁。它可用于大多數操作系統和Web服務器,也能訪問大多數常見數據庫,包括MySQL。PHP可以作為單獨程序運行,也能編譯為模塊,用于Apache Web服務器。 PHP實際上提供了兩種不同的MySQL API擴展: ·???????? mysql:適用于PHP版本4和5,該擴展用于MySQL 4.1之前的MySQL版本。該擴展不支持MySQL 5.1中采用的、改進的鑒定協議,也不支持與預處理語句或多語句。如果打算與MySQL 5.1一起使用該擴展,應配置MySQL服務器,以使用“**--old-passwords**”選項(請參見[A.2.3節,“客戶端不支持鑒定協議”](# "A.2.3.?Client does not support authentication protocol"))。在PHP網站的文檔中記錄了該該擴展[http://php.net/mysql](http://php.net/mysql)。 ·???????? mysqli是“MySQL, Improved”的縮寫,該擴展僅適用于PHP 5。它能用于MySQL 4.1.1和更高版本。該擴展完全支持MySQL 5.1中采用的鑒定協議,也支持預處理語句和多語句API。此外,該擴展還提供了先進的、面向對象的編程接口。在[http://php.net/mysqli](http://php.net/mysqli)上,可找到關于mysqli擴展的文檔。在[http://www.zend.com/php5/articles/php5-mysqli.php](http://www.zend.com/php5/articles/php5-mysqli.php)處,給出了一篇有用的文章。 PHP分發版和文檔均能從[PHP網站](http://www.php.net/)獲得。 ### 25.3.1.?使用MySQL和PHP的常見問題 ·???????? 錯誤:超出了最大執行時間,這是一種PHP限制,如果需要,進入文件php.ini,并設置最大執行時間(開始為30秒)。此外,還可以將每腳本允許使用的RAM增加一倍,從8MB變為16MB,這也是個不錯的主意。 ·???????? 致命錯誤:在…中調用了不支持或未定義的mysql_connect()函數,這意味著,你的PHP版本不支持MySQL。你可以編譯動態MySQL模塊并將其加載到PHP,或使用內置的MySQL支持重新編譯PHP。在PHP手冊中,詳細介紹了該進程。 ·???????? 錯誤:對'uncompress'的未定義引用,這意味著所編譯的客戶端庫支持壓縮客戶端/服務器協議。更正方法是,用“-lmysqlclient”進行鏈接時,在最后添加“-lz”。 ·???????? 錯誤:客戶端不支持鑒定協議,與MySQL 4.1.1和更高版本一起使用較舊的mysql擴展時常會遇到該問題。可能的解決方案是:降級到MySQL 4.0,轉向PHP 5和較新的mysqli擴展,或用“--old-passwords”配置MySQL服務器(更多信息,請參見[A.2.3節,“客戶端不支持鑒定協議”](# "A.2.3.?Client does not support authentication protocol"))。 ### 25.4.?MySQL Perl API Perl DBI模塊為數據庫訪問提供了一個通用接口。能夠編寫無需更改就能與不同的數據庫引擎一起工作的DBI腳本。要想使用DBI,必須安裝DBI模塊,并為打算訪問的每種服務器安裝數據庫驅動程序(DBD)模塊。對于MySQL,該驅動程序是DBD::mysql模塊。 Perl DBI是推薦的Perl接口。它取代了舊的名為mysqlperl的接口,mysqlperl已過時。 關于Perl DBI支持的安裝說明,請參見[2.13節,“Perl安裝注意事項”](# "2.13.?Perl Installation Notes")。 DBI信息能夠在命令行上提供,也能以在線方式提供,或采用印刷形式: ·???????? 一旦安裝了DBI和DBD::mysql模塊,可使用perldoc命令在命令行上獲取關于它們的信息: ~~~ ·??????????????? shell> perldoc DBI ~~~ ~~~ ·??????????????? shell> perldoc DBI::FAQ ~~~ ~~~ ·??????????????? shell> perldoc DBD::mysql ~~~ 也可以使用pod2man、pod2html等將這類信息轉換為其他格式。 ·???????? 關于Perl DBI的在線信息,請訪問DBI網站,[http://dbi.perl.org/](http://dbi.perl.org/)。該站點還提供了1個一般性DBI郵件列表。MySQL AB提供了1個專門針對DBD::mysql的郵件列表,請參見[1.7.1.1 “MySQL郵件列表”](# "1.7.1.1.?The MySQL Mailing Lists")。 ·???????? 至于印刷版信息,官方的DBI書籍是*編程Perl DBI*(Alligator Descartes和Tim Bunce,O'Reilly & Associates, 2000)。關于該書的信息,請訪問DBI網站[http://dbi.perl.org/](http://dbi.perl.org/)。 關于與MySQL一起使用DBI的專門信息,請參見*針對Web的MySQL和Perl(*Paul DuBois, New Riders, 2001)。該書的網站是[http://www.kitebird.com/mysql-perl/](http://www.kitebird.com/mysql-perl/)。 ### 25.5.?MySQL C++ API [25.5.1. Borland C++](#) MySQL++是用于C++的MySQL API。Warren Young負責該項目。要想了解更多信息,請訪問[http://www.mysql.com/products/mysql++/](http://www.mysql.com/products/mysql++/)。 ### 25.5.1.?Borland C++ 可以使用Borland C++ 5.02編譯MySQL Windows源碼(Windows源碼僅包括用于Microsoft VC++的項目,對于Borland C++,你將不得不自己編制項目文件)。 使用Borland C++時的1個已知問題是,它采用了不同于VC++的結構對齊方式。這意味著,如果你打算與Borland C++一起使用默認的libmysql.dll庫(它是使用VC++編譯的),將會遇到問題。為了避免該問題,僅應調用將Null作為參量的mysql_init(),而不是預先分配MYSQL結構。 ### 25.6.?MySQL Python API MySQLdb為Python提供了MySQL支持,它符合Python DB API版本2.0的要求,可在[http://sourceforge.net/projects/mysql-python/](http://sourceforge.net/projects/mysql-python/)上找到它。 ### 25.7.?MySQL Tcl API MySQLtcl是一種簡單的API,用于從Tcl編程語言訪問MySQL數據庫服務器。可在[http://www.xdobry.de/mysqltcl/](http://www.xdobry.de/mysqltcl/)上找到它。 ### 25.8.?MySQL Eiffel Wrapper Eiffel MySQL是一種與MySQL數據庫服務器的接口,它采用的是Eiffel編程語言,由Michael Ravits編寫。可在[http://efsa.sourceforge.net/archive/ravits/mysql.htm](http://efsa.sourceforge.net/archive/ravits/mysql.htm)上找到它。 ### 25.9.?MySQL程序開發實用工具 [ 25.9.1. msql2mysql:轉換mSQL程序以用于MySQL](#)[ 25.9.2. mysql_config:獲取編譯客戶端的編譯選項](#) 在本節中,介紹了開發MySQL程序時可能會有用的一些實用工具。 ·???????? msql2mysql 1種shell腳本,用于將mSQL程序轉換為MySQL程序。它不能處理所有情況,但能為轉換提供良好的開端。 ·???????? mysql_config 1種shell腳本,能生成編譯MySQL程序時所需的選項值。 ### 25.9.1.?msql2mysql:轉換mSQL程序以用于MySQL 最初,開發的MySQL C API很類似為mSQL數據庫系統開發的API。正因為如此,通過更改C API函數的名稱,通常能相對容易地轉換mSQL程序,使之用于MySQL。 **msql2mysql**實用工具用于將mSQL C API函數調用轉換為其MySQL對等物。**msql2mysql**能夠轉換位于恰當位置輸入文件,在執行具體轉換之前復制原件。例如,可采用下述方式使用**msql2mysql**: ~~~ shell> cp client-prog.c client-prog.c.orig ~~~ ~~~ shell> msql2mysql client-prog.c ~~~ ~~~ client-prog.c converted ~~~ 然后,檢查client-prog.c,并執行可能需要的后期轉換修訂。 **msql2mysql**使用**replace**實用工具來替換函數名。請參見[8.14節,“replace:字符串替換實用工具”](# "8.14.?replace — A String-Replacement Utility")。 ### 25.9.2.?mysql_config:獲取編譯客戶端的編譯選項 **mysql_config**提供了關于編譯MySQL客戶端以及將其連接到MySQL的有用信息。 **mysql_config**支持下述選項: ·???????? --cflags 編譯器標志,用于查找包含文件,以及編譯libmysqlclient庫時所要使用的關鍵編譯器標志和定義。 ·???????? --include 編譯器選項,用于查找MySQL包含文件(注意,正常情況下應使用“—cflags”而不是該選項)。 ·???????? --libmysqld-libs, ---embedded 與MySQL嵌入式服務器進行鏈接所需的庫和選項。 ·???????? --libs 與MySQL客戶端庫進行鏈接所需的庫和選項。 ·???????? --libs_r 與線程安全MySQL客戶端庫進行鏈接所需的庫和選項。 ·???????? --port 默認的TCP/IP端口號,配置MySQL時定義。 ·???????? --socket 默認的Unix套接字文件,配置MySQL時定義。 ·???????? --version 版本號以及MySQL分發版的版本。 如果未使用任何選項調用了**mysql_config**,將顯示它所支持的所有選項的列表,以及它們的值: ~~~ shell> mysql_config ~~~ ~~~ Usage: /usr/local/mysql/bin/mysql_config [options] ~~~ ~~~ Options: ~~~ ~~~ ? --cflags???????? [-I/usr/local/mysql/include/mysql -mcpu=pentiumpro] ~~~ ~~~ ? --include??????? [-I/usr/local/mysql/include/mysql] ~~~ ~~~ ? --libs?????????? [-L/usr/local/mysql/lib/mysql -lmysqlclient -lz ~~~ ~~~ ??????????????????? -lcrypt -lnsl -lm -L/usr/lib -lssl -lcrypto] ~~~ ~~~ ? --libs_r???????? [-L/usr/local/mysql/lib/mysql -lmysqlclient_r ~~~ ~~~ ??????????????????? -lpthread -lz -lcrypt -lnsl -lm -lpthread] ~~~ ~~~ ? --socket???????? [/tmp/mysql.sock] ~~~ ~~~ ? --port???????? ??[3306] ~~~ ~~~ ? --version??????? [4.0.16] ~~~ ~~~ ? --libmysqld-libs [-L/usr/local/mysql/lib/mysql -lmysqld -lpthread -lz ~~~ ~~~ ??????????????????? -lcrypt -lnsl -lm -lpthread -lrt] ~~~ 可以在命令行上使用**mysql_config**,并包含針對特定選項的值。例如,要想編譯MySQL客戶端程序,可使用**mysql_config**,如下例所示: ~~~ shell> CFG=/usr/local/mysql/bin/mysql_config ~~~ ~~~ shell> sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`" ~~~ 以這種方式使用**mysql_config**時,務必在字符(‘`’)內調用它。這樣,就能通知shell執行它,并將其輸出代入到環境命令中。 [這是MySQL參考手冊的翻譯版本,關于MySQL參考手冊,請訪問]()[dev.mysql.com](http://dev.mysql.com/doc/mysql/en)。 原始參考手冊為英文版,與英文版參考手冊相比,本翻譯版可能不是最新的。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看