### 第25章:API和庫
[本章介紹了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->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()將返回
- 前言
- 1. 一般信息
- 2. 安裝MySQL
- 3. 教程
- 4. MySQL程序概述
- 5. 數據庫管理
- 6. MySQL中的復制
- 7. 優化
- 8. 客戶端和實用工具程序
- 9. 語言結構
- 10. 字符集支持
- 11. 列類型
- 12. 函數和操作符
- 13. SQL語句語法
- 14. 插件式存儲引擎體系結構
- 15. 存儲引擎和表類型
- 16. 編寫自定義存儲引擎
- 17. MySQL簇
- 18. 分區
- 19. MySQL中的空間擴展
- 20. 存儲程序和函數
- 21. 觸發程序
- 22. 視圖
- 23. INFORMATION_SCHEMA信息數據庫
- 24. 精度數學
- 25. API和庫
- 26. 連接器
- 27. 擴展MySQL
- A. 問題和常見錯誤
- B. 錯誤代碼和消息
- C. 感謝
- D. MySQL變更史
- E. 移植到其他系統
- F. 環境變量
- G. MySQL正則表達式
- H. MySQL中的限制
- I. 特性限制
- J. GNU通用公共許可
- K. MySQL FLOSS許可例外
- 索引