快捷搜索:

在MySQL数据库中使用C执行SQL语句

与PostgreSQL相似,可应用许多不合的说话来造访MySQL,包括C、C++、Java和Perl。从下列章节中,Neil Matthew和Richard Stones应用详尽的MySQL C接口向我们先容了若何在MySQL数据库中履行SQL语句。他们将评论争论返回数据的语句,例如INSERT以及不返回数据的语句,例如UPDATE和 DELETE。然后,他们将编写从数据库检索数据的简单法度榜样。

履行SQL语句

现在,我们已经有了一个连接,并且知道若何处置惩罚差错,是时刻评论争论应用我们的数据库来作一些实际事情了。履行所有类型的SQL的主关键字是mysql_query:

int mysql_query(MYSQL *connection, const char *query)

正如您所见,它异常简单。它取一个指向连接布局的指针和包孕要履行的SQL的文本字符串;与敕令行对象不合,将不应用停止分号。成功之后,返回0。在必要包孕二进制数据的特殊环境下,可以应用相关的函数,mysql_real_query。虽然出于本章的目的,我们仅必要评论争论mysql_query。

不返回数据的SQL语句

我们将先评论争论UPDATE、DELETE和INSERT语句。由于它们不返回数据,以是更易于应用。

这里我们将先容的另一个紧张函数是反省受影响的行数的函数:

my_ulonglong mysql_affected_rows(MYSQL *connection);

可能关于这一函数的最显而易见的事便是其非同平常的返回结果。因为可移植性缘故原由,这是一个特殊的无符号类型。为了在printf中应用,建议将其强制转换成应用%lu款式规范的无符号长整数。这个函数返回受曩昔的UPDATE、INSERT或DELETE查询影响的行数,这些查询是应用 mysql_query履行的。

平日对付mysql_函数,返回码0表示没有行受影响;正数表示实际结果,平日是受影响的行数。

如前所述,当应用mysql_affected_rows时可能呈现未期望的结果。让我们先评论争论受INSERT语句影响的行数,它将按预期进行操作。将下列代码添加到法度榜样 connect2.c 中,并且称其为insert1.c:

#include

#include

#include "mysql.h"

int main(int argc, char *argv[]) {

MYSQL my_connection;

int res;

mysql_init(&my_connection);

if (mysql_real_connect(&my_connection, "localhost",

"rick", "bar", "rick", 0, NULL, 0)) {

printf("Connection success\n");

res = mysql_query(&my_connection,

"INSERT INTO children(fname,age),

VALUES('Ann',3)");

if (!res) {

printf("Inserted %lu rows\n",

(unsigned long)mysql_affected_rows(&my_connection));

} else {

fprintf(stderr, "Insert error %d: s\n",mysql_errno ,

(&my_connection),

mysql_error(&my_connection));

}

mysql_close(&my_connection);

} else {

fprintf(stderr, "Connection failed\n");

if (mysql_errno(&my_connection)) {

fprintf(stderr, "Connection error %d: %s\n",

mysql_errno(&my_connection),

mysql_error(&my_connection));

}

}

return EXIT_SUCCESS;

}

正如预期,插入的行数为1。

现在,我们变动代码,以是 'insert' 部分被调换成:

mysql_errno(&my_connection), mysql_error(&my_connection));

}

}

res = mysql_query(&my_connection, "UPDATE children SET AGE = 4

WHERE fname = 'Ann'");

if (!res) {

printf("Updated %lu rows\n",

(unsigned long)mysql_affected_rows(&my_connection));

} else {

fprintf(stderr, "Update error %d: %s\n",

mysql_errno(&my_connection),

mysql_error(&my_connection));

}

现在假设子表中有的数据,如下:

childno

fname

age

1

2

3

4

5

6

7

8

9

10

11

Jenny

Andrew

Gavin

Duncan

Emma

Alex

Adrian

Ann

Ann

Ann

Ann

14

10

4

2

0

11

5

3

4

3

4

假如我们履行update1,盼望申报的受影响行数为4,然则实际上法度榜样申报2,由于它仅必须变动2行,虽然WHERE子句标识了4行。假如想让 mysql_affected_rows申报的结果为4这可能是认识其它数据库的人所期望的),则必要记着将CLIENT_FOUND_ROWS标志通报到mysql_real_connect,在 update2.c中的法度榜样如下:

if (mysql_real_connect(&my_connection, "localhost",

"rick", "bar", "rick", 0, NULL, CLIENT_FOUND_ROWS)) {

假如我们在数据库中复位数据,然后运行带有这种改动的法度榜样,则它申报的行数为4。

函数mysql_affected_rows还有着末一个稀罕之处,它发生在从数据库中删除数据时。假如应用WHERE子句,则 mysql_affected_rows将按预期返回删除行数。然则,假如没有WHERE子句,则删除所有行,申报受影响的行数却为0。这是由于因为效率缘故原由优化删除全部表。这种行径不受CLIENT_FOUND_ROWS选项标志的影响。

返回数据的语句

现在是时刻评论争论SQL的最普遍用法了,从数据库检索数据的SELECT语句。

MySQL 还支持返回结果的SHOW、DESCRIBE和EXPLAIN SQL语句,然则这里不斟酌它们。按常规,手册中包孕这些语句的阐明。

您将会从PostgreSQL章记起,可以从PQexec中的SQL SELECT 语句检索数据,这里顿时获取所稀有据,或者应用游标从数据库中逐行检索数据,以便搞定大年夜数据。

因为完全相同的缘故原由,MySQL的检索措施险些完全相同,虽然它实际上不用游标的形式描述逐行检索。然则,它供给了缩小这两种措施间差异的API,假如必要,它平日使两种措施的交换加倍轻易。

平日,从MySQL数据库中检索数据有4个阶段:

发出查询

检索数据

处置惩罚数据

履行所需的任何收拾

象曩昔一样,我们应用mysql_query发出查询。数据检索是应用mysql_store_result或mysql_use_result完成的,这取决于想若何检索数据,随后应用mysql_fetch_row调用序列来处置惩罚数据。着末,必须调用mysql_free_result以容许 MySQL履行任何所需的收拾。

整个急速数据检索的函数

可以从SELECT语句(或其他返回数据的语句)中检索完所稀有据,在单一调用中,应用mysql_store_result:

MYSQL_RES *mysql_store_result(MYSQL *connection);

必须在mysql_query检索数据后才能调用这个函数,以在结果集中存储该数据。这个函数从办事器中检索所稀有据并急速将它存储在客户机中。它返回一个指向曩昔我们从未碰到过的布局(结果集布局)的指针。假如语句掉败,则返回NULL。

应用等价的PostgreSQL时,应该知道返回NULL意味着已经发生了差错,并且这与未检索到数据的环境不合。纵然,返回值不是NULL,也不料味着当前稀有据要处置惩罚。

假如未返回NULL,则可以调用mysql_num_rows并且检索实际返回的行数,它当然可能是0。

my_ulonglong mysql_num_rows(MYSQL_RES *result);

它从mysql_store_result取得返回的结果布局,并且在该结果集中返回行数,行数可能为0。假如mysql_store_result成功,则mysql_num_rows也老是成功的。

这种mysql_store_result和mysql_num_rows的组合是检索数据的一种简便并且直接的措施。一旦 mysql_store_result成功返回,则所有查询数据都已经存储在客户机上并且我们知道可以从结果布局中检索它,而不用担心会发生数据库或收集差错,由于对付法度榜样所稀有据都是本地的。还可以急速发明返回的行数,它可以使编码更简便。如前所述,它将所有结果急速地发送回客户机。对付大年夜结果集,它可能消费大年夜量的办事器、收集和客户机资本。因为这些缘故原由,应用更大年夜的数据集时,最好仅检索必要的数据。不久,我们将评论争论若何应用 mysql_use_result函数来完成该操作。

一旦检索了数据,则可以应用mysql_fetch_row来检索它,并且应用mysql_data_seek、mysql_row_seek、mysql_row_tell操作结果集。在开始检索数据阶段之前,让我们先评论争论一下这些函数。

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

这个函数采纳从存储结果中获取的结果布局,并且从中检索单一行,在行布局中返回分配给您的数据。当没有更多半据或者发生差错时,返回NULL。稍后,我们将回来处置惩罚这一行中的数据。

void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);

这个函数容许您进入结果集,设置将由下一个获取操作返回的行。offset是行号,它必须在从0到结果集中的行数减 1 的范围内。通报0将导致鄙人一次调用mysql_fetch_row时返回第一行。

MYSQL_ROW_OFFEST mysql_row_tell(MYSQL_RES *result);

这个函数返回一个偏移值,它表示结果集中确当前位置。它不是行号,不能将它用于mysql_data_seek。然则,可将它用于:

MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset);

它移动结果集中确当前位置,并返回曩昔的位置。

无意偶尔,这一对函数对付在结果集中的已知点之间跳转很有用。请留意,不要将row tell和row seek应用的偏移值与data_seek应用的行号肴杂。这些是弗成互换的,结果将是您所盼望看到的。

void mysql_free_result(MYSQL_RES *result);

完成结果集时, 必须老是调用这个函数,以容许MySQL库收拾分配给它的工具。

检索数据

现在开始编写从数据库中检索数据的第一个法度榜样。我们将选择所丰年岁大年夜于5的行的内容。不幸的是我们还不知道若何处置惩罚这个数据,以是我们能做的只有轮回检索它。这就是 select1.c:

#include

#include

#include "mysql.h"

MYSQL my_connection;

MYSQL_RES *res_ptr;

MYSQL_ROW sqlrow;

int main(int argc, char *argv[]) {

int res;

mysql_init(&my_connection);

if (mysql_real_connect(&my_connection, "localhost", "rick",

"bar", "rick", 0, NULL, 0)) {

printf("Connection success\n");

res = mysql_query(&my_connection, "SELECT childno, fname,

age FROM children WHERE age > 5");

if (res) {

printf("SELECT error: %s\n", mysql_error(&my_connection));

} else {

res_ptr = mysql_store_result(&my_connection);

if (res_ptr) {

printf("Retrieved %luows\n",(unsignedlong)mysql_num_rows(res_ptr));

while ((sqlrow = mysql_fetch_row(res_ptr))) {

printf("Fetched data...\n");

}

if (mysql_errno(&my_connection)) {

fprintf(stderr, "Retrive error: s\n",mysql_error(&my_connection));

}

}

mysql_free_result(res_ptr);

}

mysql_close(&my_connection);

} else {

fprintf(stderr, "Connection failed\n");

if (mysql_errno(&my_connection)) {

fprintf(stderr, "Connection error %d: %s\n",

mysql_errno(&my_connection),mysql_error(&my_connection));

}

}

return EXIT_SUCCESS;

}

检索结果集并轮回经由过程已检索的数据的紧张部分都已凸起显示。

一次检索一行数据

要按必要逐行检索数据,而不是急速获取整个数据并将它存储在客户机中,可以将mysql_store_result调用调换成 mysql_use_result:

MYSQL_RES *mysql_use_result(MYSQL *connection);

这个函数还取得一个连接工具并返回结果结合指针,或者掉足时返回NULL。与mysql_store_result相似,它返回指向结果集工具的指针;关键的不合点在于返回时,实际上没有将任何数据检索到结果集,只是初始化结果集以筹备好检索数据。

您可能还会对下面的文章感兴趣: