第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伺服器庫概述

使用嵌入式MySQL伺服器庫,能夠在客戶端應用程式中使用具備全部特性的MySQL伺服器。 主要優點在於,增加了速度,並使得嵌入式應用程式的管理更簡單。

嵌入式伺服器庫是以MySQL的客戶端/伺服器版本為基礎的,採用C/C++語言編寫。 其結果是嵌入式伺服器也是用C/C++語言編寫的。 在其他語言中,嵌入式伺服器不可用。

API與嵌入式MySQL版本和客戶端/伺服器版本等效。 要想更改舊的線程式應用程式以使用嵌入式庫,正常情況下,僅需新增對下述函數的使用即可。

函數

何時使用

mysql_server_init()

應在使用任何其他MySQL函數之前使用,最好是在main()函數中使用。

mysql_server_end()

應在程式退出前使用。

mysql_thread_init()

應在您所建立的、用於訪問MySQL的每個線程中使用。

mysql_thread_end()

應在使用pthread_exit()之前使用。

隨後,必須將您的代碼與libmysqld.a連結起來,而不是libmysqlclient.a。

libmysqlclient.a中還包含mysql_server_xxx()函數,使用這類函數,通過將應用程式連結到恰當的庫,即可在嵌入式版本和客戶端/伺服器版本之間切換。 請參見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節,「典型配置選項

將您的程式與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()」

使用選項檔案,能夠簡化客戶端/伺服器應用程式和嵌入了MySQL的應用程式之間的切換。將常用選項置於[server]組。它們可被兩種MySQL版本讀取。客戶端/伺服器選項應被放在[mysqld]部分。將嵌入式MySQL伺服器庫的選項放在[embedded]部分。將與應用程式相關的選項放在標記為[ApplicationName_SERVER]的部分。請參見4.3.2節,「使用選項檔案」

25.1.5. 嵌入式伺服器中尚需完成的事項(TODO)

·         我們將提供一些選項以省去MySQL的某些部分,從而使庫變得更小。

·         仍有很多速度最佳化工作需要完成。

·         錯誤將被寫入stderr。我們將增加1個選項為它們指定檔案名。

·         使用嵌入式版本時,需要更改InnoDB,使之不再冗長。如果您的資料庫不含InnoDB資料表,要想抑制相關消息,可為組[libmysqd_server]下的選項檔案增加--skip-innodb」選項,或在用mysql_server_init()初始化伺服器時新增該選項。

25.1.6. 嵌入式伺服器示範

LinuxFreeBSD系統上,無需更改就能使用下面這兩個示範程式。對於其他作業系統,需要進行小的修改,主要是檔案路徑。設計這兩個示範的目的在於,為您提供足夠的細節訊息,以便理解問題,它們是實際應用程式的必要組成部份。第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/

25.2. MySQL C API

C API代碼是與MySQL一起提供的。它包含在mysqlclient庫中,並允許C程式訪問資料庫。

MySQL原始碼分發版的很多客戶端是用C語言編寫的。如果您正在尋找能演示如何使用C API的示範,可參看這些客戶端程式。您可以在MySQL原始碼分發版的客戶端目錄下找到它們。

大多數其他客戶端API(除了Connector/JConnector/NET)採用mysqlclient庫來與MySQL伺服器進行通信。這意味著(例如),您可以利用很多相同環境變數(與其他客戶端程式使用的環境變數相同)帶來的好處,這是因為它們是從庫中引用的。關於這些變數的詳細清單,請參見第8章:客戶端和實用工具程式

客戶端具有最大的通信緩衝區大小。初始分配的緩衝區大小(16KB)將自動增加到最大(最大為16MB)。由於緩衝區大小將按需增加,簡單地增加預設的最大限制,從其本身來說不會增加資源使用。該大小檢查主要是檢查錯誤查詢和通信訊息包。

通信緩衝區必須足夠大,足以包含1SQL語句(用於客戶端-伺服器通信)以及1行返回的數據(用於伺服器-客戶端通信)。每個線程的通信緩衝區將動態增加,以處理直至最大限制的任何查詢或行。例如,如果BLOB值包含高達16MB的數據,那麼通信緩衝區的大小限制至少為16MB(在伺服器和客戶端)。客戶端的預設最大值為16MB,但伺服器的預設最大值為1MB。也可以在啟動伺服器時,通過更改max_allowed_packet參數的值增加它。請參見7.5.2節,「調節伺服器參數」

每次查詢後,MySQL伺服器會將通信緩衝區的大小降至net_buffer_length字節。對於客戶端,不會降低與連接相關緩衝區大小,直至連接關閉為止,此時,客戶端內存將被收回。

關於使用線程的編程方法,請參見25.2.15節,「如何生成線程式客戶端」。關於在相同程式建立包含「伺服器」和「客戶端」的獨立應用程式的更多訊息(不與外部MySQL伺服器通信),請參見25.1節,「libmysqld,嵌入式MySQL伺服器庫」

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()的類型。該類型提供的範圍為01.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個或多個下述位集合:

標誌值

標誌描述

NOT_NULL_FLAG

字段不能為NULL

PRI_KEY_FLAG

字段是主鍵的組成部分

UNIQUE_KEY_FLAG

字段是唯一鍵的組成部分

MULTIPLE_KEY_FLAG

字段是非唯一鍵的組成部分

UNSIGNED_FLAG

字段具有UNSIGNED屬性

ZEROFILL_FLAG

字段具有ZEROFILL屬性

BINARY_FLAG

字段具有BINARY屬性

AUTO_INCREMENT_FLAG

字段具有AUTO_INCREMENT屬性

ENUM_FLAG

字段是ENUM(不再重視)

SET_FLAG

字段是 SET(不再重視)

BLOB_FLAG

字段是BLOBTEXT(不再重視)

TIMESTAMP_FLAG

字段是TIMESTAMP(不再重視)

不再重視BLOB_FLAGENUM_FLAGSET_FLAGTIMESTAMP_FLAG標誌,原因在於,它們指出了字段的類型,而不是類型的屬性。更可取的方式是使用MYSQL_TYPE_BLOBMYSQL_TYPE_ENUMMYSQL_TYPE_SETMYSQL_TYPE_TIMESTAMP測試field->type

在下面的示範中,介紹了標誌值的典型用法:

if (field->flags & NOT_NULL_FLAG)
    printf("Field can't be null\n");

可以使用下述方面的宏來定義標誌值的布爾狀態:

標誌狀態

描述

IS_NOT_NULL(flags)

如果該字段定義為NOT NULL,為

IS_PRI_KEY(flags)

如果該字段是主鍵,為

IS_BLOB(flags)

如果該字段是BLOBTEXT,為(不再重視,用測試field->type取而代之)。

·         unsigned int decimals

用於數值字段的十進制數數目。

·         unsigned int charset_nr

用於字段的字元編碼編號。

·         enum enum_field_types type

字段的類型。類型值可以是下標所列的MYSQL_TYPE_符號之一:

類型值

類型描述

MYSQL_TYPE_TINY

TINYINT字段

MYSQL_TYPE_SHORT

SMALLINT字段

MYSQL_TYPE_LONG

INTEGER字段

MYSQL_TYPE_INT24

MEDIUMINT字段

MYSQL_TYPE_LONGLONG

BIGINT字段

MYSQL_TYPE_DECIMAL

DECIMALNUMERIC字段

MYSQL_TYPE_NEWDECIMAL

精度數學DECIMALNUMERIC

MYSQL_TYPE_FLOAT

FLOAT字段

MYSQL_TYPE_DOUBLE

DOUBLEREAL字段

MYSQL_TYPE_BIT

BIT字段

MYSQL_TYPE_TIMESTAMP

TIMESTAMP字段

MYSQL_TYPE_DATE

DATE字段

MYSQL_TYPE_TIME

TIME字段

MYSQL_TYPE_DATETIME

DATETIME字段

MYSQL_TYPE_YEAR

YEAR字段

MYSQL_TYPE_STRING

CHAR字段

MYSQL_TYPE_VAR_STRING

VARCHAR字段

MYSQL_TYPE_BLOB

BLOBTEXT字段(使用max_length來確定最大長度)

MYSQL_TYPE_SET

SET字段

MYSQL_TYPE_ENUM

ENUM字段

MYSQL_TYPE_GEOMETRY

Spatial字段

MYSQL_TYPE_NULL

NULL-type字段

MYSQL_TYPE_CHAR

不再重視,用MYSQL_TYPE_TINY取代

可以使用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函數描述」

函數

描述

mysql_affected_rows()

返回上次UPDATEDELETEINSERT查詢更改/刪除/插入的行數。

mysql_autocommit()

切換 autocommit模式,ON/OFF

mysql_change_user()

更改打開連接上的用戶和資料庫。

mysql_charset_name()

返回用於連接的預設字元編碼的名稱。

mysql_close()

關閉伺服器連接。

mysql_commit()

提交事務。

mysql_connect()

連接到MySQL伺服器。該函數已不再被重視,使用mysql_real_connect()取代。

mysql_create_db()

建立資料庫。該函數已不再被重視,使用SQL語句CREATE DATABASE取而代之。

mysql_data_seek()

在查詢結果集中搜尋屬性行編號。

mysql_debug()

用給定的字串執行DBUG_PUSH

mysql_drop_db()

撤銷資料庫。該函數已不再被重視,使用SQL語句DROP DATABASE取而代之。

mysql_dump_debug_info()

讓伺服器將調試訊息寫入日誌。

mysql_eof()

確定是否讀取了結果集的最後一行。該函數已不再被重視,可以使用mysql_errno()mysql_error()取而代之。

mysql_errno()

返回上次使用的MySQL函數的錯誤編號。

mysql_error()

返回上次使用的MySQL函數的錯誤消息。

mysql_escape_string()

為了用在SQL語句中,對特殊字元進行轉義處理。

mysql_fetch_field()

返回下一個資料表字段的類型。

mysql_fetch_field_direct()

給定字段編號,返回資料表字段的類型。

mysql_fetch_fields()

返回所有字段結構的數組。

mysql_fetch_lengths()

返回當前行中所有列的長度。

mysql_fetch_row()

從結果集中獲取下一行

mysql_field_seek()

將列光標置於指定的列。

mysql_field_count()

返回上次執行語句的結果列的數目。

mysql_field_tell()

返回上次mysql_fetch_field()所使用字段光標的位置。

mysql_free_result()

釋放結果集使用的內存。

mysql_get_client_info()

以字串形式返回客戶端版本訊息。

mysql_get_client_version()

以整數形式返回客戶端版本訊息。

mysql_get_host_info()

返回描述連接的字串。

mysql_get_server_version()

以整數形式返回伺服器的版本號。

mysql_get_proto_info()

返回連接所使用的協議版本。

mysql_get_server_info()

返回伺服器的版本號。

mysql_info()

返回關於最近所執行查詢的訊息。

mysql_init()

獲取或初始化MYSQL結構。

mysql_insert_id()

返回上一個查詢為AUTO_INCREMENT列生成的ID

mysql_kill()

殺死給定的線程。

mysql_library_end()

最終確定MySQL C API庫。

mysql_library_init()

初始化MySQL C API庫。

mysql_list_dbs()

返回與簡單正則資料表達式匹配的資料庫名稱。

mysql_list_fields()

返回與簡單正則資料表達式匹配的字段名稱。

mysql_list_processes()

返回當前伺服器線程的列資料表。

mysql_list_tables()

返回與簡單正則資料表達式匹配的資料表名。

mysql_more_results()

檢查是否還存在其他結果。

mysql_next_result()

在多語句執行過程中返回/初始化下一個結果。

mysql_num_fields()

返回結果集中的列數。

mysql_num_rows()

返回結果集中的行數。

mysql_options()

mysql_connect()設置連接選項。

mysql_ping()

檢查與伺服器的連接是否工作,如有必要重新連接。

mysql_query()

執行指定為「以Null終結的字串」的SQL查詢。

mysql_real_connect()

連接到MySQL伺服器。

mysql_real_escape_string()

考慮到連接的當前字元編碼,為了在SQL語句中使用,對字串中的特殊字元進行轉義處理。

mysql_real_query()

執行指定為計數字串的SQL查詢。

mysql_refresh()

刷新或復位資料表和高速緩衝。

mysql_reload()

通知伺服器再次加載授權資料表。

mysql_rollback()

回滾事務。

mysql_row_seek()

使用從mysql_row_tell()返回的值,搜尋結果集中的行偏移。

mysql_row_tell()

返回行光標位置。

mysql_select_db()

選擇資料庫。

mysql_server_end()

最終確定嵌入式伺服器庫。

mysql_server_init()

初始化嵌入式伺服器庫。

mysql_set_server_option()

為連接設置選項(如多語句)。

mysql_sqlstate()

返回關於上一個錯誤的SQLSTATE錯誤代碼。

mysql_shutdown()

關閉資料庫伺服器。

mysql_stat()

以字串形式返回伺服器狀態。

mysql_store_result()

檢索完整的結果集至客戶端。

mysql_thread_id()

返回當前線程ID

mysql_thread_safe()

如果客戶端已編譯為線程安全的,返回1

mysql_use_result()

初始化逐行的結果集檢索。

mysql_warning_count()

返回上一個SQL語句的告警數。

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(),但其名稱更清楚地指明,無論應用程式使用的是mysqlclientmysqld庫,啟動或結束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查詢(例如INSERTUPDATEDELETE),通過使用mysql_affected_rows(),可發現有多少行已被改變(影響)。

對於SELECT查詢,能夠檢索作為結果集的行。注意,某些語句因其返回行,類似與SELECT包括SHOWDESCRIBEEXPLAIN。應按照對待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查詢不返回數據(表明它是INSERTUPDATEDELETE等),而且不返回行。如果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語句插入的行數。對於UPDATEDELETEINSERT語句,可在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)

描述

在查詢結果集中尋找任意行。偏移值為行號,範圍從0mysql_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_PUSHmysql_debug()採用Fred Fish調試庫。要想使用該函數,必須編譯客戶端庫,使之支援調試功能。請參見E.1節,「調試MySQL伺服器」。請參見E.2節,「調試MySQL客戶端」

返回值

無。

錯誤

無。

示範:

這裡給出的使用將使客戶端庫在客戶端機器的/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:錯誤代碼和消息中,也列出了這些錯誤。

注意,如果成功,某些函數,如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節,「設置錯誤消息語言」

返回值

返回描述錯誤的、由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的值應在從0mysql_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.

返回值

資料表示結果集中列數的無符號整數。

錯誤

無。

示範:

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節,「字串」

該字串從形式上編碼為十六進制格式,每個字元編碼為2個十六進制數。結果被置入其中,並新增1個終結Null字節。

from」所指向的字串必須是長度字節「long」。必須為「to」分配緩衝區,緩衝區至少為length*2+1字節長。當mysql_hex_string()返回時,「to」的內容為由Null終結的字串。返回值是編碼字串的長度,不包括終結用Null字元。

可採用0xvalueX'value'格式將返回值置於SQL語句中。但是,返回值不包括0xX'...'。使用者必須提供所希望的格式是何種。

示範:

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對象。如果mysqlNULL指針,該函數將分配、初始化、並返回新對象。否則,將初始化對象,並返回對象的地址。如果mysql_init()分配了新的對象,當使用mysql_close()來關閉連接時。將釋放該對象。

返回值

初始化的MYSQL*句柄。如果無足夠內存以分配新的對象,返回NULL

錯誤

在內存不足的情況下,返回NULL

25.2.3.36. mysql_insert_id()

my_ulonglong mysql_insert_id(MYSQL *mysql)

描述

返回由以前的INSERTUPDATE語句為AUTO_INCREMENT列生成的值。在包含AUTO_INCREMENT字段的資料表中執行了INSERT語句後,應使用該函數。

更準確地講,將在下述條件下更新mysql_insert_id()

·         將值保存到AUTO_INCREMENT列中的INSERT語句。無論值是通過在列中儲存特殊值NULL0自動生成的,還是確切的非特殊值,都成立。

·         在有多行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_INCREMENTmysql_insert_id()返回0。如果需要保存值,在生成值的語句後,務必立刻使用mysql_insert_id()

mysql_insert_id()的值僅受在當前客戶端連接內發出的語句的影響。不受由其他客戶端發出的語句的影響。

請參見12.9.3節,「訊息函數」

此外還應注意,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.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.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 processlistSHOW 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.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處理」

返回值

返回值

描述

0

成功並有多個結果。

-1

成功但沒有多個結果。

>0

出錯

錯誤

·         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

返回值

資料表示結果集中行數的無符號整數。

錯誤

無。

示範:

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應指向整數的值。

可能的選項值:

選項

參量類型

功能

MYSQL_INIT_COMMAND

char *

連接到MySQL伺服器時將執行的命令。再次連接時將自動地再次執行。

MYSQL_OPT_COMPRESS

未使用

使用壓縮客戶端/伺服器協議

MYSQL_OPT_CONNECT_TIMEOUT

unsigned int *

以秒為單位的連接超時。

MYSQL_OPT_GUESS_CONNECTION

未使用

對於與libmysqld連結的應用程式,允許庫猜測是否使用嵌入式伺服器或遠程伺服器。「猜測」資料表示,如果設置了主機名但不是本地主機,將使用遠程伺服器。該行為是預設行為。 可使用MYSQL_OPT_USE_EMBEDDED_CONNECTION MYSQL_OPT_USE_REMOTE_CONNECTION覆蓋它。對於與libmysqlclient連結的應用程式,該選項將被忽略。

MYSQL_OPT_LOCAL_INFILE

指向單元的可選指針

如果未給定指針,或指針指向「unsigned int != 0」,將允許命令LOAD LOCAL INFILE

MYSQL_OPT_NAMED_PIPE

未使用

使用命名管道連接到NT平台上的MySQL伺服器。

MYSQL_OPT_PROTOCOL

unsigned int *

要使用的協議類型。應是mysql.h中定義的mysql_protocol_type的枚舉值之一。

MYSQL_OPT_READ_TIMEOUT

unsigned int *

從伺服器讀取訊息的超時(目前僅在Windows平台的TCP/IP連接上有效)。

MYSQL_OPT_RECONNECT

my_bool *

如果發現連接丟失,啟動或禁止與伺服器的自動再連接。從MySQL 5.0.3開始,預設情況下禁止再連接,這是5.0.13中的新選項,提供了一種以顯式方式設置再連接行為的方法。

MYSQL_OPT_SET_CLIENT_IP

char *

對於與libmysqld連結的應用程式(具備鑒定支援特性的已編譯libmysqld,它意味著,出於鑒定目的,用戶將被視為從指定的IP地址(指定為字串)進行連接。對於與libmysqlclient連結的應用程式,,該選項將被忽略。

MYSQL_OPT_USE_EMBEDDED_CONNECTION

未使用

對於與libmysqld連結的應用程式,對於連接來說,它將強制使用嵌入式伺服器。對於與libmysqlclient連結的應用程式,,該選項將被忽略。

MYSQL_OPT_USE_REMOTE_CONNECTION

未使用

對於與libmysqld連結的應用程式,對於連接來說,它將強制使用遠程伺服器。對於與libmysqlclient連結的應用程式,,該選項將被忽略。

MYSQL_OPT_USE_RESULT

未使用

不使用該選項。

MYSQL_OPT_WRITE_TIMEOUT

unsigned int *

寫入伺服器的超時(目前僅在Windows平台的TCP/IP連接上有效)。

MYSQL_READ_DEFAULT_FILE

char *

從命名選項檔案而不是從my.cnf讀取選項。

MYSQL_READ_DEFAULT_GROUP

char *

my.cnf或用MYSQL_READ_DEFAULT_FILE指定的檔案中的命名組讀取選項。

MYSQL_REPORT_DATA_TRUNCATION

my_bool *

通過MYSQL_BIND.error,對於預處理語句,允許或禁止通報數據截斷錯誤(預設為禁止)。

MYSQL_SECURE_AUTH

my_bool*

是否連接到不支援密碼混編功能的伺服器,在MySQL 4.1.1和更高版本中,使用了密碼混編功能。

MYSQL_SET_CHARSET_DIR

char*

指向包含字元編碼定義檔案的目錄的路徑名。

MYSQL_SET_CHARSET_NAME

char*

用作預設字元編碼的字元編碼的名稱。

MYSQL_SHARED_MEMORY_BASE_NAME

char*

命名為與伺服器進行通信的共享內存對象。應與您打算連接的mysqld伺服器使用的選項「-shared-memory-base-name」相同。

注意,如果使用了MYSQL_READ_DEFAULT_FILEMYSQL_READ_DEFAULT_GROUP,總會讀取客戶端組。

選項檔案中指定的組可能包含下述選項:

選項

描述

connect-timeout

以秒為單位的連接超時。在Linux平台上,該超時也用作等待伺服器首次回應的時間。

compress

使用壓縮客戶端/伺服器協議。

database

如果在連接命令中未指定資料庫,連接到該資料庫。

debug

調試選項。

disable-local-infile

禁止使用LOAD DATA LOCAL

host

預設主機名。

init-command

連接到MySQL伺服器時將執行的命令。再次連接時將自動地再次執行。

interactive-timeout

等同於將CLIENT_INTERACTIVE指定為mysql_real_connect()。請參見25.2.3.51節,「mysql_real_connect()」

local-infile[=(0|1)]

如果無參量或參量!= 0,那麼將允許使用LOAD DATA LOCAL

max_allowed_packet

客戶端能夠從伺服器讀取的最大訊息包。

multi-results

允許多語句執行或儲存程式的多個結果集。

multi-statements

允許客戶端在1個字串內發送多條語句。(由「;」隔開)。

password

預設密碼。

pipe

使用命名管道連接到NT平台上的MySQL伺服器。

protocol={TCP | SOCKET | PIPE | MEMORY}

連接到伺服器時將使用的協議。

port

預設端口號。

return-found-rows

通知mysql_info()返回發現的行,而不是使用UPDATE時更新的行

shared-memory-base-name=name

共享內存名稱,用於連接到伺服器(預設為"MYSQL")。

socket

預設的套接字檔案。

user

預設用戶。

注意,「timeout」(超時)已被connect-timeout」(連接超時)取代,但為了保持向後兼容,MySQL 5.1.2-alpha中仍支援「timeout」(超時)。

關於選項檔案的更多訊息,請參見4.3.2節,「使用選項檔案」

返回值

成功時返回0。如果使用了未知選項,返回非0值。

示範:

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查詢。正常情況下,字串必須包含1SQL語句,而且不應為語句新增終結分號(『;』)或「\g」。如果允許多語句執行,字串可包含多條由分號隔開的語句。請參見25.2.9節,「多查詢執行的C API處理」

mysql_query()不能用於包含二進制數據的查詢,應使用mysql_real_query()取而代之(二進制數據可能包含字元『\0』mysql_query()會將該字元解釋為查詢字串結束)。

如果希望瞭解查詢是否應返回結果集,可使用mysql_field_count()進行檢查。請參見25.2.3.22節,「mysql_field_count()」

返回值

如果查詢成功,返回0。如果出現錯誤,返回非0值。

錯誤

·         CR_COMMANDS_OUT_OF_SYNC

以不恰當的順序執行了命令。

·         CR_SERVER_GONE_ERROR

MySQL伺服器不可用。

·         CR_SERVER_LOST

在查詢過程中,與伺服器的連接丟失。

·         CR_UNKNOWN_ERROR

出現未知錯誤。

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()」

·         host」的值必須是主機名或IP地址。如果「host」是NULL或字串"localhost",連接將被視為與本地主機的連接。如果作業系統支援套接字(Unix)或命名管道(Windows),將使用它們而不是TCP/IP連接到伺服器。

·         user」參數包含用戶的MySQL登錄ID。如果「user」NULL或空字串"",用戶將被視為當前用戶。在UNIX環境下,它是當前的登錄名。在Windows ODBC下,必須明確指定當前帳號。請參見26.1.9.2節,「在Windows上配置MyODBC DSN」

·         passwd」參數包含用戶的密碼。如果「passwd」NULL僅會對該用戶的(擁有1個空密碼字段的)用戶資料表中的條目進行匹配檢查。這樣,資料庫管理員就能按特定的方式設置MySQL權限系統,根據用戶是否擁有指定的密碼,用戶將獲得不同的權限。

註釋:使用mysql_real_connect()之前,不要嘗試加密密碼,密碼加密將由客戶端API自動處理。

·         「db」是資料庫名稱。如果dbNULL連接會將預設的資料庫設為該值。

·         如果「port」不是0其值將用作TCP/IP連接的端口號。注意,「host」參數決定了連接的類型。

·         如果unix_socket不是NULL,該字串描述了應使用的套接字或命名管道。注意,「host」參數決定了連接的類型。

·         client_flag的值通常為0,但是,也能將其設置為下述標誌的組合,以允許特定功能:

標誌名稱

標誌描述

CLIENT_COMPRESS

使用壓縮協議。

CLIENT_FOUND_ROWS

返回發現的行數(匹配的),而不是受影響的行數。

CLIENT_IGNORE_SPACE

允許在函數名後使用空格。使所有的函數名成為保留字。

CLIENT_INTERACTIVE

關閉連接之前,允許interactive_timeout(取代了wait_timeout)秒的不活動時間。客戶端的會話wait_timeout變數被設為會話interactive_timeout變數的值。

CLIENT_LOCAL_FILES

允許LOAD DATA LOCAL處理功能。

CLIENT_MULTI_STATEMENTS

通知伺服器,客戶端可能在單個字串內發送多條語句(由『;』隔開)。如果未設置該標誌,將禁止多語句執行。

CLIENT_MULTI_RESULTS

通知伺服器,客戶端能夠處理來自多語句執行或儲存程式的多個結果集。如果設置了CLIENT_MULTI_STATEMENTS,將自動設置它。

CLIENT_NO_SCHEMA

禁止db_name.tbl_name.col_name語法。它用於ODBC。如果使用了該語法,它會使分析程式生成錯誤,在捕獲某些ODBC程式中的問題時,它很有用。

CLIENT_ODBC

客戶端是ODBC客戶端。它將mysqld變得更為ODBC友好。

CLIENT_SSL

使用SSL(加密協議)。該選項不應由應用程式設置,它是在客戶端庫內部設置的。

對於某些參數,能夠從選項檔案獲得取值,而不是取得mysql_real_connect()使用中的確切值。為此,在使用mysql_real_connect()之前,應與MYSQL_READ_DEFAULT_FILEMYSQL_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節,「字串」

按照連接的當前字元編碼,將「from」中的字串編碼為轉義SQL字串。將結果置於「to」中,並新增1個終結用NULL字節。編碼的字元為NUL (ASCII 0)、『\n』、『\r』、『\』、『'』、『"』、以及Control-Z(請參見9.1節,「文字值」)。(嚴格地講,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」。正常情況下,字串必須包含1SQL語句,而且不應為語句新增終結分號(『;』)或「\g」。如果允許多語句執行,字串可包含由分號隔開的多條語句。請參見25.2.9節,「多查詢執行的C API處理」

對於包含二進制數據的查詢,必須使用mysql_real_query()而不是mysql_query(),這是因為,二進制數據可能會包含\0』字元。此外,mysql_real_query()mysql_query()快,這是因為它不會在查詢字串上使用strlen()

如果希望知道查詢是否應返回結果集,可使用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)

描述

允許或禁止連接的選項。選項可以取下述值之一:

MYSQL_OPTION_MULTI_STATEMENTS_ON

允許多語句支援。

MYSQL_OPTION_MULTI_STATEMENTS_OFF

禁止多語句支援。

返回值

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伺服器關機程序」中,介紹了關機程序。

返回值

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 SQLODBC指定。關於可能取值的列資料表,請參見附錄B:錯誤代碼和消息

注意,並非所有的MySQL錯誤均會被映射到SQLSTATE錯誤代碼。值'HY000'(一般錯誤)用於未映射的錯誤。

返回值

包含SQLSTATE錯誤碼的、由Null終結的字串。

另請參見:

請參見25.2.3.14節,「mysql_errno()」。請參見25.2.3.15節,「mysql_error()」。請參見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()返回的連接處理程式。其他參數的指定如下:

·         keykey檔案的路徑名。

·         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)

描述

對於成功檢索了數據的每個查詢(SELECTSHOWDESCRIBEEXPLAINCHECK 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()」

mysql_store_result()將查詢的全部結果讀取到客戶端,分配1MYSQL_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.

返回值

具有多個結果的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)

描述

對於成功檢索數據的每個查詢(SELECTSHOWDESCRIBEEXPLAIN),必須使用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 TABLEDELETEDOINSERTREPLACESELECTSETUPDATE、以及大多數SHOW語句。MySQL 5.1中,不支援其他語句。

25.2.5. C API預處理語句的數據類型

預處理語句主要使用MYSQL_STMTMYSQL_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成員,指明變數是signedunsigned類型,詳情請參見本節後面的介紹)。對於日期和時間列類型,緩衝應指向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變數的地址,並在各次執行之間恰當地更改變數的值,以指明數據值是NULLNOT NULL

o        my_bool is_unsigned

該成員用於整數類型。(對應於MYSQL_TYPE_TINYMYSQL_TYPE_SHORTMYSQL_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

該結構用於將DATETIMEDATETIMETIMESTAMP數據直接發送到伺服器,或從伺服器直接接收這類數據。將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結構的部分:用於DATEDATETIMETIMESTAMP年、月、日部分。用於TIMEDATETIMETIMESTAMP值的小時、分鐘、秒部分。請參見25.2.10節,「日期和時間值的C API處理」

在下面的資料表格中,給出了可在MYSQL_BIND結構的buffer_type成員中指定的允許值。在該資料表中,還給出了與每個buffer_type值最接近的對應SQL類型,對於數值和臨時類型,給出了對應的C類型。

buffer_type

SQL類型

C類型

MYSQL_TYPE_TINY

TINYINT

char

MYSQL_TYPE_SHORT

SMALLINT

short int

MYSQL_TYPE_LONG

INT

int

MYSQL_TYPE_LONGLONG

BIGINT

long long int

MYSQL_TYPE_FLOAT

FLOAT

float

MYSQL_TYPE_DOUBLE

DOUBLE

double

MYSQL_TYPE_TIME

TIME

MYSQL_TIME

MYSQL_TYPE_DATE

DATE

MYSQL_TIME

MYSQL_TYPE_DATETIME

DATETIME

MYSQL_TIME

MYSQL_TYPE_TIMESTAMP

TIMESTAMP

MYSQL_TIME

MYSQL_TYPE_STRING

CHAR

 

MYSQL_TYPE_VAR_STRING

VARCHAR

 

MYSQL_TYPE_TINY_BLOB

TINYBLOB/TINYTEXT

 

MYSQL_TYPE_BLOB

BLOB/TEXT

 

MYSQL_TYPE_MEDIUM_BLOB

MEDIUMBLOB/MEDIUMTEXT

 

MYSQL_TYPE_LONG_BLOB

LONGBLOB/LONGTEXT

 

隱式類型轉換可沿兩個方向執行。

25.2.6. C API預處理語句函數概述

在此歸納了預處理語句處理功能可使用的函數,並在後面的章節中詳細介紹了它。請參見25.2.7節,「C API預處理語句函數描述」

函數

描述

mysql_stmt_affected_rows()

返回由預處理語句UPDATEDELETEINSERT變更、刪除或插入的行數目。

mysql_stmt_attr_get()

獲取預處理語句屬性的值。

mysql_stmt_attr_set()

設置預處理語句的屬性。

mysql_stmt_bind_param()

將應用程式數據緩衝與預處理SQL語句中的參數標記符關聯起來。

mysql_stmt_bind_result()

將應用程式數據緩衝與結果集中的列關聯起來。

mysql_stmt_close()

釋放預處理語句使用的內存。

mysql_stmt_data_seek()

尋找語句結果集中的任意行編號。

mysql_stmt_errno()

返回上次語句執行的錯誤編號。

mysql_stmt_error()

返回上次語句執行的錯誤消息。

mysql_stmt_execute()

執行預處理語句。

mysql_stmt_fetch()

從結果集獲取數據的下一行,並返回所有綁定列的數據。

mysql_stmt_fetch_column()

獲取結果集當前行中某列的數據。

mysql_stmt_field_count()

對於最近的語句,返回結果行的數目。

mysql_stmt_free_result()

釋放分配給語句句柄的資源。

mysql_stmt_init()

MYSQL_STMT結構分配內存並初始化它

mysql_stmt_insert_id()

對於預處理語句的AUTO_INCREMENT列,返回生成的ID

mysql_stmt_num_rows()

從語句緩衝結果集返回總行數。

mysql_stmt_param_count()

返回預處理SQL語句中的參數數目。

mysql_stmt_param_metadata()

返回結果集的參數元數據。

mysql_stmt_prepare()

為執行操作準備SQL字串。

mysql_stmt_reset()

復位伺服器中的語句緩衝區。

mysql_stmt_result_metadata()

以結果集形式返回預處理語句元數據。

mysql_stmt_row_seek()

使用從mysql_stmt_row_tell()返回的值,搜尋語句結果集中的行偏移。

mysql_stmt_row_tell()

返回語句行光標位置。

mysql_stmt_send_long_data()

將程式塊中的長數據發送到伺服器。

mysql_stmt_sqlstate()

返回關於上次語句執行的SQLSTATE錯誤代碼。

mysql_stmt_store_result()

將完整的結果集檢索到客戶端。

使用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()」

完成語句執行後,必須使用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客戶端/伺服器協議將執行下述動作:

·         伺服器解析語句,並通過賦值語句IDOK狀態發回客戶端。此外,如果它是面向結果集的語句,還將發送總的參數數目,列計數和元數據。在此使用過程中,伺服器將檢查語句的所有語法和語義。

·         客戶端採用該語句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預處理語句函數描述

為了準備和執行查詢,請使用下述部分詳細介紹的函數。

注意,與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)

描述

返回上次執行語句更改、刪除或插入的總行數。對於UPDATEDELETEINSERT語句,可在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()」

錯誤

無。

示範:

關於mysql_stmt_affected_rows()的用法,請參閱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()」

返回值

如果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」應指向整數的值。

可能的選項值:

選項

參量類型

功能

STMT_ATTR_UPDATE_MAX_LENGTH

my_bool *

如果設為1:更新mysql_stmt_store_result()中的元數據MYSQL_FIELD->max_length

STMT_ATTR_CURSOR_TYPE

unsigned long *

使用mysql_stmt_execute()時,語句將打開的光標類型。*arg可以是CURSOR_TYPE_NO_CURSOR(預設值)或CURSOR_TYPE_READ_ONLY

STMT_ATTR_PREFETCH_ROWS

unsigned long *

使用光標時,一次從伺服器獲取的行數。*arg的範圍從1unsigned long的最大值。預設值為1

如果與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預處理語句的數據類型」中,介紹了應設置的每個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.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預處理語句的數據類型」中,介紹了應設置的各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.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.7. mysql_stmt_data_seek()

void mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset)

描述

搜尋語句結果集中的任意行。偏移量為行編號,應位於從0mysql_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:錯誤代碼和消息中,也列出了錯誤消息。

返回值

錯誤代碼值。如果未出現錯誤,返回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()執行與語句句柄相關的預處理查詢。在該使用期間,將當前綁定的參數標記符的值發送到伺服器,伺服器用新提供的數據替換標記符。

如果語句是UPDATEDELETEINSERT,通過使用mysql_stmt_affected_rows(),可發現更改、刪除或插入的總行數。如果這是諸如SELECT等能生成結果集的語句,使用任何其他能導致查詢處理的函數之前,必須使用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指明的實際數據值的長度。

類型

長度

MYSQL_TYPE_TINY

1

MYSQL_TYPE_SHORT

2

MYSQL_TYPE_LONG

4

MYSQL_TYPE_LONGLONG

8

MYSQL_TYPE_FLOAT

4

MYSQL_TYPE_DOUBLE

8

MYSQL_TYPE_TIME

sizeof(MYSQL_TIME)

MYSQL_TYPE_DATE

sizeof(MYSQL_TIME)

MYSQL_TYPE_DATETIME

sizeof(MYSQL_TIME)

MYSQL_TYPE_STRING

data length

MYSQL_TYPE_BLOB

data_length

返回值

返回值

描述

0

成功,數據被提取到應用程式數據緩衝區。

1

出現錯誤。通過使用mysql_stmt_errno()mysql_stmt_error(),可獲取錯誤代碼和錯誤消息。

MYSQL_NO_DATA

不存在行/數據。

MYSQL_DATA_TRUNCATED

出現數據截短。

不返回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_DATEMYSQL_TYPE_TIMEMYSQL_TYPE_DATETIME、或MYSQL_TYPE_TIMESTAMP,但數據類型不是DATETIMEDATETIME、或TIMESTAMP

·         mysql_stmt_bind_result()返回所有其他不支援的轉換錯誤。

示範:

在下面的示範中,介紹了使用mysql_stmt_result_metadata()mysql_stmt_bind_result()mysql_stmt_fetch()從資料表中獲取數據的方法。(在本示範中,將檢索在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列編號為0offset」是數據值內的偏移量,將從該處開始檢索數據。可將其用於獲取碎片形式的數據值。值開始部分的偏移量為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)

描述

為語句處理程式返回關於最近語句的行數。對於諸如INSERTDELETE等不生成結果集的語句,該值為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)

描述

返回預處理INSERTUPDATE語句AUTO_INCREMENT列生成的值。在包含AUTO_INCREMENT字段的資料表上執行了預處理INSERT語句後,使用該函數。

更多訊息,請參見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.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」參量給出。字串必須包含1SQL語句。不應為語句新增終結用分號(;)\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.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.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)

描述

允許應用程式分段地(分塊)將參數數據發送到伺服器。可以多次使用該函數,以便發送關於某一列的字元或二進制數據的不同部分,列必須是TEXTBLOB數據類型之一。

「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()」

返回值

如果成功地將數據發送到伺服器,返回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 SQLODBC指定。關於可能值的列資料表,請參見附錄B:錯誤代碼和消息

注意,並非所有的MySQL錯誤均會被映射到SQLSTATE代碼。值"HY000"(一般錯誤)用於未映射的錯誤。

返回值

包含SQLSTATE錯誤代碼、由Null終結的字串。

25.2.7.27. mysql_stmt_store_result()

int mysql_stmt_store_result(MYSQL_STMT *stmt)

描述

對於成功生成結果集的所有語句(SELECTSHOWDESCRIBEEXPLAIN),而且僅當您打算對客戶端的全部結果集進行緩衝處理時,必須使用mysql_stmt_store_result(),以便後續的mysql_stmt_fetch()使用能返回緩衝數據。

對於其他語句,沒有必要使用mysql_stmt_store_result(),但如果使用了它,也不會造成任何傷害或導致任何性能問題。通過檢查mysql_stmt_result_metadata()是否返回NULL,可檢測語句是否生成了結果集。更多訊息,請參見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()」

返回值

如果成功完成了對結果的緩衝處理,返回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預處理語句方面的問題

下面列出了一些目前已知的與預處理語句有關的問題:

·         TIMETIMESTAMPDATETIME不支援秒部分,例如來自DATE_FORMAT()的秒部分

·         將整數轉換為字串時,在某些情況下,當MySQL不打印前導0時,可與預處理語句一起使用ZEROFILL。例如,與MIN(number-with-zerofill)一起。

·         將浮點數轉換為客戶端中的字串時,被轉換值最右側的位可能會與原始值的有所不同。

·         預處理語句不使用查詢高速緩衝,即使當查詢不含任何佔位符時也同樣。。請參見5.13.1節,「查詢高速緩衝如何工作」

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結構發送和接受日期和時間值(DATETIMEDATETIMETIMESTAMP)。25.2.5節,「C API預處理語句的數據類型」中,介紹了該結構的成員。

要想發送臨時數據值,可使用mysql_stmt_prepare()建立預處理語句。然後,在使用mysql_stmt_execute()執行語句之前,可採用下述步驟設置每個臨時參數:

1.    在與數據值相關的MYSQL_BIND結構中,將buffer_type成員設置為相應的類型,該類型指明了發送的臨時值類型。對於DATETIMEDATETIMETIMESTAMP值,buffer_type分別設置為MYSQL_TYPE_DATEMYSQL_TYPE_TIMEMYSQL_TYPE_DATETIMEMYSQL_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()將緩衝綁定到語句上。

下面給出了一個插入DATETIMETIMESTAMP數據的簡單示範。假定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.15節,「如何生成線程式客戶端」

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嵌入式伺服器函數介紹

如果希望允許應用程式連結到嵌入式MySQL伺服器庫,必須使用mysql_server_init()mysql_server_end()函數。請參見25.1節,「libmysqld,嵌入式MySQL伺服器庫」

但是,要想提供改進的內存管理,即使是對與「-lmysqlclient」而不是與「-lmysqld」連結的程式,也應包含啟用和結束庫使用的使用。mysql_library_init()mysql_library_end()函數可用於該目的。它們實際上是使其等效於mysql_server_init()mysql_server_end()#define符號,但它們的名稱更清楚地指明,無論應用程式使用的是libmysqlclientlibmysqld,開始使用或結束MySQL C API庫的使用時,應使用它們。關於更多訊息,請參見25.2.2節,「C API函數概述」

25.2.12.1. mysql_server_init()

int mysql_server_init(int argc, char **argv, char **groups)

描述

使用任何其他MySQL函數之前,必須在使用嵌入式伺服器的程式中使用該函數。它將啟動伺服器,並初始化伺服器使用的任何子系統(mysysInnoDB等)。如果未使用該函數,對mysql_init()的下一次使用將執行mysql_server_init()。如果您正在使用與MySQL一起提供的DBUG軟件包,應在使用了my_init()之後使用它。

對於main()的參量,argcargv是類似的參量。argv的第1個元素將被忽略(典型情況下,它包含程式名)。為了方便起見,如果沒有針對伺服器的命令行參量,argc可以是0mysql_server_init()將複製參量,以便能夠在使用之後安全地摧毀argvgroups

如果打算連接到外部伺服器而不啟動嵌入式伺服器,應為argc指定負值。

groups」中以Null終結的字串列資料表選擇了選項檔案中的活動「groups」。請參見4.3.2節,「使用選項檔案」。為了方便起見,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

成功使用mysql_query()後,mysql_store_result()能夠返回NULL。出現該情況時,表明出現了下述條件之一:

·         出現了malloc()故障(例如,如果結果集過大)。

·         無法讀取數據(在連接上出現了錯誤)。

·         查詢未返回數據(例如,它是INSERTUPDATEDELETE)。

通過使用mysql_field_count()始終能檢查語句是否應生成非空結果。如果mysql_field_count()返回0,結果為空,而且上一個查詢是未返回值的語句(例如INSERTDELETE)。如果mysql_field_count()返回非0值,語句應生成非空結果。關於這方面的示範,請參見mysql_field_count()函數介紹。

通過使用mysql_error()mysql_errno()可測試是否出現了錯誤。

25.2.13.2. What Results You Can Get from a Query

除了查詢返回的結果集外,還能獲取下述訊息:

·         執行INSERTUPDATEDELETE時,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()」

·         某些查詢(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()」

生成新的AUTO_INCREMENT值時,也能與mysql_query()一起通過執行SELECT LAST_INSERT_ID()語句獲得它,並從該語句返回的結果集檢索該值。

對於LAST_INSERT_ID(),最近生成的ID是在伺服器上按連接維護的。它不會被另一個客戶端改變。即使用non-magic值(即非Null0值)更新了另一個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列中的值,無論該值是因儲存NULL0而自動生成的,或是明確指定的,均如此。LAST_INSERT_ID()僅返回自動生成的AUTO_INCREMENT值。如果您保存了除NULL0之外的確切值,不會影響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:獲取編譯客戶端的編譯選項」

您也可以使用它來編譯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/)的二進製版本中,未用線程安全的選項對客戶端庫進行正常編譯(預設情況下,編譯的Windows二進製版本是線程安全的)。較新的二進制分發版應是正常的和線程安全的客戶端庫。

為了獲得能從其他線程中斷客戶端的線程式客戶端,並在與MySQL伺服器通信時設置超時,應使用「-lmysys」、「-lmystrings」-ldbug」庫,以及伺服器使用的net_serv.o代碼。

如果您不需要使用中斷或超時,可編譯線程安全客戶端庫(mysqlclient_r)並使用它。。請參見25.2節,「MySQL C API」。在該情況下,不必擔心net_serv.o對像檔案或其他MySQL庫。

使用線程式客戶端並打算使用超時或中斷時,可更好地利用thr_alarm.c檔案中的子程式。如果您正在使用來自mysys庫的子程式,唯一需要記住的事是首先使用my_init()!請參見25.2.11節,「C API線程函數介紹」

對於除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

PHP是一種伺服器端、HTML嵌入式指令處理語言,可使用該語言建立動態網頁。它可用於大多數作業系統和Web伺服器,也能訪問大多數常見資料庫,包括MySQLPHP可以作為單獨程式運行,也能編譯為模塊,用於Apache Web伺服器。

PHP實際上提供了兩種不同的MySQL API延伸:

·         mysql:適用於PHP版本45,該延伸用於MySQL 4.1之前的MySQL版本。該延伸不支援MySQL 5.1中採用的、改進的鑒定協議,也不支援與預處理語句或多語句。如果打算與MySQL 5.1一起使用該延伸,應配置MySQL伺服器,以使用「--old-passwords」選項(請參見A.2.3節,「客戶端不支援鑒定協議」)。在PHP網站的文檔中記錄了該該延伸http://php.net/mysql

·         mysqli是「MySQL, Improved」的縮寫,該延伸僅適用於PHP 5。它能用於MySQL 4.1.1和更高版本。該延伸完全支援MySQL 5.1中採用的鑒定協議,也支援預處理語句和多語句API。此外,該延伸還提供了先進的、面向對象的編程接口。在http://php.net/mysqli上,可找到關於mysqli延伸的文檔。在http://www.zend.com/php5/articles/php5-mysqli.php處,給出了一篇有用的文章。

PHP分發版和文檔均能從PHP網站獲得。

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節,「客戶端不支援鑒定協議」)。

25.4. MySQL Perl API

Perl DBI模塊為資料庫訪問提供了一個通用接口。能夠編寫無需更改就能與不同的資料庫引擎一起工作的DBI指令。要想使用DBI,必須安裝DBI模塊,並為打算訪問的每種伺服器安裝資料庫驅動程式(DBD)模塊。對於MySQL,該驅動程式是DBD::mysql模塊。

Perl DBI是推薦的Perl接口。它取代了舊的名為mysqlperl的接口,mysqlperl已過時。

關於Perl DBI支援的安裝說明,請參見2.13節,「Perl安裝注意事項」

DBI訊息能夠在命令行上提供,也能以線上方式提供,或採用印刷形式:

·         一旦安裝了DBIDBD::mysql模塊,可使用perldoc 命令在命令行上獲取關於它們的訊息:

·                shell> perldoc DBI
·                shell> perldoc DBI::FAQ
·                shell> perldoc DBD::mysql

也可以使用pod2manpod2html將這類訊息轉換為其他格式。

·         關於Perl DBI的線上訊息,請訪問DBI網站,http://dbi.perl.org/。該站點還提供了1個一般性DBI郵件列資料表。MySQL AB提供了1個專門針對DBD::mysql 的郵件列資料表,請參見1.7.1.1 MySQL郵件列資料表」

·         至於印刷版訊息,官方的DBI書籍是編程Perl DBIAlligator DescartesTim BunceO'Reilly & Associates, 2000)。關於該書的訊息,請訪問DBI網站http://dbi.perl.org/

關於與MySQL一起使用DBI的專門訊息,請參見針對WebMySQLPerlPaul DuBois, New Riders, 2001)。該書的網站是http://www.kitebird.com/mysql-perl/

25.5. MySQL C++ API

MySQL++是用於C++MySQL APIWarren Young負責該項目。要想瞭解更多訊息,請訪問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

MySQLdbPython提供了MySQL支援,它符合Python DB API版本2.0的要求,可在http://sourceforge.net/projects/mysql-python/上找到它。

25.7. MySQL Tcl API

MySQLtcl是一種簡單的API,用於從Tcl編程語言訪問MySQL資料庫伺服器。可在http://www.xdobry.de/mysqltcl/上找到它。

25.8. MySQL Eiffel Wrapper

Eiffel MySQL是一種與MySQL資料庫伺服器的接口,它採用的是Eiffel編程語言,由Michael Ravits編寫。可在http://efsa.sourceforge.net/archive/ravits/mysql.htm上找到它。

25.9. MySQL程式開發實用工具

在本節中,介紹了開發MySQL程式時可能會有用的一些實用工具。

·         msql2mysql

1shell指令,用於將mSQL程式轉換為MySQL程式。它不能處理所有情況,但能為轉換提供良好的開端。

·         mysql_config

1shell指令,能生成編譯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:字串替換實用工具」

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。 原始參考手冊為英文版,與英文版參考手冊相比,本翻譯版可能不是最新的。