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
参考 :