使用C语言访问MySQL数据 —— 执行SQL语句(1)

来源:互联网 发布:微博手游直播软件 编辑:程序博客网 时间:2024/06/04 20:11

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 中插入一个新行。

 

编译程序:
$ gcc -I/usr/include/mysql insert1.c -L/usr/lib/mysql -lmysqlclient -o insert1

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

编译程序:
$ 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

编译程序:
$ gcc -I/usr/include/mysql insert2.c -L/usr/lib/mysql -lmysqlclient -o insert2


参考

Linux 程序设计(第4版)第8章 P.283
SQL语言基本语句介绍
http://www.longen.org/s-z/details~z/SqlSentence.htm

 

 

 

 

 

 

原创粉丝点击