首页 | 资讯动态 | linux基础 | 系统管理 | 网络管理 | 编程开发 | linux数据库 | 服务器技术 | linux相关 | linux认证 | 嵌入式 | 下载中心 | 专题 | linux招聘 | 镜像站
OKLinux中文技术站
·设为首页
·加入收藏
·联系我们
系统管理: 中文环境 系统管理 桌面应用 内核技术 | Linux基础: 基础入门 安装配置 常用命令 经验技巧 软件应用 | Linux数据库: Mysql Postgre Oracle DB2 Sybase other
网络管理: 网络安全 网络应用 Linux服务器 环境配置 黑客安全 | 编程开发: PHP CC++ Python Perl Shell 嵌入式开发 java jsp | PHP技术: PHP基础 PHP技巧 PHP应用 PHP文摘
Linux资讯 Linux招聘 Linux专题 Apache | Linux相关: 硬件相关 Linux解决方案 Linux认证 企业应用 其它Unix | 相关下载: 资料下载 参考手册 开发工具 服务器类 软路由 其它
 技术搜索:
会员中心 注册会员 高级搜索  
  → 当前位置:首页>linux数据库>mysql>正文

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

http://www.oklinux.cn  2006-10-24  来源: IBM DW中国 Richard Stones  会员收藏  游客收藏  【 】 
与 PostgreSQL 相似,可使用许多不同的语言来访问 MySQL,包括 C、C++、Java 和 Perl。从 Professional Linux Programming 中第 5 章有关 MySQL 的下列章节中,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 <stdlib.h>
      #include <stdio.h>

      #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_fetch_rowmysql_fetch_row


MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

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

mysql_data_seek


void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);

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

my_sql_row_tell, mysql_row_seek


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 使用的行号混淆。这些是不可交换的,结果将是您所希望看到的。

mysql_free_result

在迫不及待地使用这些新函数之前,我们需要知道的最后一个函数是 mysql_free_result。


void mysql_free_result(MYSQL_RES *result);

完成结果集时, 必须总是 调用这个函数,以允许 MySQL 库整理分配给它的对象。

检索数据

现在开始编写从数据库中检索数据的第一个程序。我们将选择所有年龄大于 5 的行的内容。不幸的是我们还不知道如何处理这个数据,所以我们能做的只有循环检索它。这便是 select1.c:


      #include <stdlib.h>
      #include <stdio.h>

      #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 相似,它返回指向结果集对象的指针;关键的不同点在于返回时,实际上没有将任何数据检索到结果集,只是初始化结果集以准备好检索数据。

 

原文链接:http://www-128.ibm.com/developerworks/cn/linux/database/c-sql/index.html


上一篇:将数据库访问集成到 Linux 应用中   下一篇:BI相关的开源工具


收藏于收藏夹】 【评论】 【推荐】 【打印】 【关闭
相关文档
·将数据库访问集成到 Linux 应用中
·MySQL的一些安全注意点
·在Linux高负载下mysql数据库彻底优化
·通过Putty远程安全管理MySQL
·如何保护MySQL重要数据
·让MYSQL彻底支持中文
·每天备份 mysql 数据库的脚本
·Mysql 5.0.22 Cluster for RedHat AS4-U2
·Linux 安装 Mysql
·如何在Linux系统中安装MySQL
·MySQL运算符获得更多数据比较功能
·你应该知道的10个MySQL客户启动选项
·如影随形的数据库 嵌入式数据库简介
·加速动态网站之MySQL 索引分析和优化
·怎样在UNIX系统下安装MySQL
·配置最新的PHP加MYSQL服务器完全版
发表评论
密码: 匿名评论
评论内容:

(不超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规)
 
  最新文档
·无需编程直接利用图形界面导入导出的方
·教你快速掌握 MySQL数据库中触发器的应
·解析:怎样在MySQL中获得更好的搜索结果
·将数据从MySQL迁移到 Oracle的注意事项
·细化解析:怎样修改 MySQL数据库中的密
·解析:优化MySQL数据库性能的几个好方法
·教你轻松掌握如何保护MySQL中的重要数
·细化解析:怎样把你的 MySQL 完全中文化
·带你轻松接触 MySQL中损坏的MyISAM表
·解析:教你轻松的掌握 ENUM和SET约束
·细化解析:与浮点比较有关的几个问题
·解析:以mysql_开始的未定义引用错误
  阅读排行
·Linux 安装 Mysql
·如何在Linux系统中安装MySQL
·在Linux 环境下安装 Mysql
·在Linux上安装MySQL Server 5.0
·图形化管理MySQL更轻松
·[Mysql]IIS+mysql+php相关知识介绍
·MySQL创始人David Axmark 访谈实录
·你应该知道的10个MySQL客户启动选项
·Heartbeat_2.0.3配置MySQL5.0.8集群
·Linux系统上安装MYSQL数据库的方法
·[MySQL]入门学习从安装入门到学习操作
·MySQL中文参考手册-创造并使用数据库
·MySQL5.0新特性教程 存储过程:第三讲
·MySQL 5.0新特性教程 存储过程:第一讲
·[Mysql]Mysql数据库管理系统优化方案
网摘收藏: