c 使用mysql输出语句_使用C语言访问MySQL数据 —— 执行SQL语句(1)

2011-05-14 wcdj

(一) 不返回数据的SQL语句 —— UPDATE、DELETE 和 INSERT

(二) 发现插入的内容

在能够连接数据库并正确处理错误后,可以做一些实际工作了。执行SQL语句的主要API函数被恰当地命名为:

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

这个例程接受连接结构指针和文本字符串形式的有效SQL语句(注意 :没有结束的分号,这与mysql工具不同)。如果成功,它返回0。对于包含二进制数据的查询,可以使用第二个例程 mysql_real_query 。

(一) 不返回数据的SQL语句 —— UPDATE、DELETE 和 INSERT

my_ulonglong mysql_affected_rows ( MYSQL *connection );

用于检查受查询影响的行数。

函数的返回值使用无符号类型是出于移植性的考虑。这个函数返回受之前执行的UPDATE、DELETE 或 INSERT 查询影响的行数。

注意 :

MySQL返回的是被一个更新操作修改的行数,但许多其他数据库将仅仅因为记录匹配 WHERE 子句就把它视为已经更新过。

例子:

$ mysql -u wcdj -p newdatabase

Enter password:

Welcome to the MySQL monitor. Commands end with ; or /g.

删除表children

mysql> DROP TABLE children;

Query OK, 0 rows affected (0.58 sec)

创建表children

mysql> CREATE TABLE children (

->    childno int(11) AUTO_INCREMENT NOT NULL PRIMARY KEY,

->    fname varchar(30),

->    age int

->   );

Query OK, 0 rows affected (0.09 sec)

源文件 insert1.c 完成在表 children 中插入一个新行。

#include

#include

#include "mysql.h"

int main()

{

MYSQL my_connection;

mysql_init(&my_connection);

int res;

if (mysql_real_connect(&my_connection, "localhost", "wcdj", "123", "newdatabase", 0, NULL, 0))

{

printf("Connection success/n");

res = mysql_query(&my_connection, "INSERT INTO children(fname, age) VALUES('csdn', 100)");

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;

}

编译程序:

$ gcc -I/usr/include/mysql insert1.c -L/usr/lib/mysql -lmysqlclient -o insert1

源代码 update1.c 完成在表 children 中将 fname = 'csdn' 行的 age 更新为200。

#include

#include

#include "mysql.h"

int main()

{

MYSQL my_connection;

mysql_init(&my_connection);

int res;

if (mysql_real_connect(&my_connection, "localhost", "wcdj", "123", "newdatabase", 0, NULL, 0))

{

printf("Connection success/n");

res = mysql_query(&my_connection, "UPDATE children SET age = 200 WHERE fname = 'csdn'");

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

}

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;

}

编译程序:

$ gcc -I/usr/include/mysql update1.c -L/usr/lib/mysql -lmysqlclient -o update1

注意 :

(1) mysql在默认状态下,返回的是实际需要对数据进行修改的行数。可以使用 mysql_real_connect 的 CLINET_FOUND_ROWS 标志来获得更传统的报告。

mysql_real_connect( &my_connection, "localhost", "wcdj", "123", "newdatabase", 0, NULL, CLIENT_FOUND_ROWS )

(2) 函数 mysql_affected_rows 还有最后一个古怪之处,它出现在从数据库中删除数据的时候。如果使用 WHERE 子句删除数据,那么 mysql_affected_rows 将返回你期望的删除的行数。但如果在 DELETE 语句中没有 WHERE 子句,那么表中所有行都会被删除,但是由程序返回的受影响行数却为0。这是因为:MySQL优化了删除所有行的操作,它并不是执行许多个单行删除操作。这一行为不会受到 CLIENT_FOUND_ROWS 选项标志的影响。

(二) 发现插入的内容

表的定义如下:

mysql> CREATE TABLE children (

->    childno int(11) AUTO_INCREMENT NOT NULL PRIMARY KEY,

->    fname varchar(30),

->    age int

->   );

childno 列被设为AUTO_INCREMENT 类型,它由MySQL自动分配ID。

问题 :

一旦你插入一行,你如何知道刚插入的孩子被分配了什么数字呢?

你可以执行一条 SELECT 语句来搜索孩子的名字,但这样效率会很低,并且如果有两个相同名字的孩子,这将不能保证唯一性。或者,如果同时有多个用户快速地插入数据,那么可能在更新操作和 SELECT 语句之间会有其他行被插入。

解决方法 :

MySQL以函数 LAST_INSERT_ID() 的形式提供了一个专门的解决方案。

无论何时MySQL向 AUTO_INCREMENT 列中插入数据,MySQL都会基于每个用户对最后分配的值进行跟踪。用户程序可以通过SELECT专用函数 LAST_INSERT_ID() 来发现该值,这个函数的作用有点儿像是表中的虚拟列。

例子:

mysql> INSERT INTO children(fname, age) VALUES('Tom1', 13);

Query OK, 1 row affected (0.06 sec)

mysql> SELECT LAST_INSERT_ID();

+------------------------------+

|         last_insert_id()              |

+------------------------------+

|                  8                           |

+------------------------------+

1 row in set (0.01 sec)

mysql> INSERT INTO children(fname, age) VALUES('Tom2', 14);

Query OK, 1 row affected (0.02 sec)

mysql> SELECT LAST_INSERT_ID();

+------------------------------+

|         last_insert_id()              |

+------------------------------+

|                  9                           |

+------------------------------+

1 row in set (0.00 sec)

mysql> DELETE FROM children WHERE fname='Tom2';

Query OK, 1 row affected (0.00 sec)

mysql> SELECT LAST_INSERT_ID();

+------------------------------+

|         last_insert_id()              |

+------------------------------+

|                  9                           |    注意 :删除后,last_insert_id() 得到仍然是上次的值。

+------------------------------+

1 row in set (0.00 sec)

使用 Alt+F2 打开另一终端,使用另一用户root登录并向newdatabase插入数据,测试last_insert_id()的变化:

$ mysql -u root -p newdatabase

Enter password:

Welcome to the MySQL monitor. Commands end with ; or /g.

显示当前表的内容

SELECT * FROM children;

(略)

插入数据

mysql> INSERT INTO children(fname, age) VALUES('msdn', 300);

Query OK, 1 row affected (0.00 sec)

显示当前表的内容

mysql> SELECT * FROM children;

(略,发现msdn成功加入到最后一条)

mysql> SELECT LAST_INSERT_ID();

+------------------------------+

|          last_insert_id()             |

+------------------------------+

|                  10                         |    注意 :9这条记录删除了,但是还是在上次的基础上加1。

+------------------------------+

1 row in set (0.00 sec)

使用使用 Alt+F1 再切换到第一个终端,测试:

mysql> SELECT LAST_INSERT_ID();

+------------------------------+

|          last_insert_id()             |

+------------------------------+

|                  9                           |    注意 :还是当前会话最后添加返回的ID,没有受到另一个root用户添加数据的影响

+------------------------------+

1 row in set (0.00 sec)

显示当前表的内容

mysql> SELECT * FROM children;

(略,msdn是通过另一个root用户加入的)

插入数据

mysql> INSERT INTO children(fname, age) VALUES('superman', 400);

Query OK, 1 row affected (0.00 sec)

显示当前表的内容

mysql> SELECT * FROM children;

(略,superman成功加入到最后一条)

mysql> SELECT LAST_INSERT_ID();

+------------------------------+

|           last_insert_id()            |

+------------------------------+

|                  11                         |    注意 :本会话中,上次返回9,这次返回11,第10条记录是另一个root用户插入的

+------------------------------+

1 row in set (0.00 sec)

总结 :

last_insert_id() 返回的数字是由当前会话插入的最后一个数字。但是,如果执行 select * from children,可以看到其他会话确实已经插入数据了。

例子:

在C程序中使用自动分配的ID

insert2.c

#include

#include

#include "mysql.h"

int main()

{

MYSQL my_connection;

MYSQL_RES *res_ptr;

MYSQL_ROW sqlrow;

mysql_init(&my_connection);

int res;

if (mysql_real_connect(&my_connection, "localhost", "wcdj", "123", "newdatabase", 0, NULL, 0))

{

printf("Connection success/n");

res = mysql_query(&my_connection, "INSERT INTO children(fname, age) VALUES('newbie',8)");

if (!res)

{

printf("Insert %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));

}

// last_insert_id()

res = mysql_query(&my_connection, "SELECT LAST_INSERT_ID()");

if (res)

{

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

}

else

{

res_ptr = mysql_use_result(&my_connection);// mysql_use_result

if (res_ptr)

{

while ((sqlrow = mysql_fetch_row(res_ptr)))// mysql_fetch_row

{

printf("We inserted childno %s/n", sqlrow[0]);

}

mysql_free_result(res_ptr);// mysql_free_result

}

}

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;

}

编译程序:

$ gcc -I/usr/include/mysql insert2.c -L/usr/lib/mysql -lmysqlclient -o insert2

参考 :

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值