C++操作mysql数据库文章资料汇总_MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2101 | 回复: 0   主题: C++操作mysql数据库文章资料汇总        下一篇 
gang
注册用户
等级:上等兵
经验:142
发帖:79
精华:0
注册:2011-12-30
状态:离线
发送短消息息给gang 加好友    发送短消息息给gang 发消息
发表于: IP:您无权察看 2014-12-17 14:33:47 | [全部帖] [楼主帖] 楼主

VC的MySQL编程
在你的程式中使用数据库是个不做的注意。如果已经有可用的MySQL服务器,在VC中可以按照如下方法实现与数据库的连接。

1、找來MySQL(Win32)安裝目录下的include文件夾, 將其添加到VC头文件目录列表中;

(VC6 -> Options -> Directories -> 加入此目录)
(VC2005 -> 工具 -> 选项 -> 项目和解決方案 -> VC++目录 -> 显示以下内容的目录 -> 包含文件 -> 加入此目录)


2、找到MySQL(Win32)安裝目录下的lib文件夹, 將其添加到VC库文件目录列表中;

(VC6 -> Options -> Directories -> 加入此目录)
(VC2005 -> 工具 -> 选项 -> 项目和解决方案 -> VC++目录 -> 显示以下内容的目录 -> 库文件 -> 加入此目录,注意是lib\debug或lib\opt)


3、新建一个工程,参考如下代码;

// mysql.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <winsock.h>
#include <mysql.h>
#include <windows.h>
#pragma comment(lib, "libmysql.lib")
int main(int argc, char* argv[])
...{
      unsigned short Port = 3306;
      char *IPAddress = "192.168.31.56";
      char *UserName = "root";
      char *Password = "";
      char *DBName = "SAS_1_2_0";
      printf("Start... ");
      MYSQL *ssock;
      //char execsql[500];
      ssock = (MYSQL *)malloc(sizeof(MYSQL));
      //在某些版本中,不需要该初始化工作,可观看mysql.H以及readme
      mysql_init(ssock);
      if(ssock == NULL)
      ...{
            printf("EROR: MySQL ssock init error. ");
            return FALSE;
      }
      //连接指定数据库
      ssock = mysql_real_connect(ssock, IPAddress, UserName, Password, NULL, Port, NULL, 0);
      if(!ssock)
      ...{
            printf("conn fail... ");
            //memcpy(eee, mysql_error(ssock), 20);
            //fprintf(stderr, "Failed to connect to database: Error: %s ", mysql_error(ssock));
            //printf("%c ", eee);
            unsigned int mtint = mysql_errno(ssock);
            //printf("%d ");
            return FALSE;
      }
      if(mysql_select_db(ssock, DBName) != 0)
      ...{
            printf("select db error. ");
            return FALSE;
      }
      printf("version=%d ", mysql_get_server_version(ssock));
      //exec my execsql string
      //sprintf(execsql,"create table girls (name char(10),age int)");
      //mysql_real_query(ssock,execsql,strlen(execsql));
      mysql_close(ssock);
      printf("End... ");
      return TRUE;
}


4、编译连接,运行即可。

关键词: C++ mysql 编程
QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
回复 引用
举报顶端
本站代购的美国VPS详细列表
[离线] usidc5

[usidc5]


级别: 管理员

发帖

 8488


金币

 2753


威望

 3222


贡献值

 0


元宝

 0


    关注Ta
    发消息

只看该作者 沙发  发表于: 2010-07-19
MYSQL C API函数-1
这里归纳了C API可使用的函数,并在下一节详细介绍了它们。

函数
描述

mysql_affected_rows()


返回上次UPDATE、DELETE或INSERT查询更改/删除/插入的行数。

mysql_autocommit()


切换 autocommit模式,ON/OFF

mysql_change_user()


更改打开连接上的用户和数据库。

mysql_charset_name()


返回用于连接的默认字符集的名称。

mysql_close()


关闭服务器连接。

mysql_commit()


提交事务。

mysql_connect()


连接到MySQL服务器。该函数已不再被重视,使用mysql_real_connect()取代。

mysql_create_db()


创建数据库。该函数已不再被重视,使用SQL语句CREATE DATABASE取而代之。

mysql_data_seek()


在查询结果集中查找属性行编号。

mysql_debug()


用给定的字符串执行DBUG_PUSH。

mysql_drop_db()


撤销数据库。该函数已不再被重视,使用SQL语句DROP DATABASE取而代之。

mysql_dump_debug_info()


让服务器将调试信息写入日志。

mysql_eof()


确定是否读取了结果集的最后一行。该函数已不再被重视,可以使用mysql_errno()或mysql_error()取而代之。

mysql_errno()


返回上次调用的MySQL函数的错误编号。

mysql_error()


返回上次调用的MySQL函数的错误消息。

mysql_escape_string()


为了用在SQL语句中,对特殊字符进行转义处理。

mysql_fetch_field()


返回下一个表字段的类型。

mysql_fetch_field_direct()


给定字段编号,返回表字段的类型。

mysql_fetch_fields()


返回所有字段结构的数组。

mysql_fetch_lengths()


返回当前行中所有列的长度。

mysql_fetch_row()


从结果集中获取下一行

mysql_field_seek()


将列光标置于指定的列。

mysql_field_count()


返回上次执行语句的结果列的数目。

mysql_field_tell()


返回上次mysql_fetch_field()所使用字段光标的位置。

mysql_free_result()


释放结果集使用的内存。

mysql_get_client_info()


以字符串形式返回客户端版本信息。

mysql_get_client_version()


以整数形式返回客户端版本信息。

mysql_get_host_info()


返回描述连接的字符串。

mysql_get_server_version()


以整数形式返回服务器的版本号。

mysql_get_proto_info()


返回连接所使用的协议版本。

mysql_get_server_info()


返回服务器的版本号。

mysql_info()


返回关于最近所执行查询的信息。

mysql_init()


获取或初始化MYSQL结构。

mysql_insert_id()


返回上一个查询为AUTO_INCREMENT列生成的ID。

mysql_kill()


杀死给定的线程。

mysql_library_end()


最终确定MySQL C API库。

mysql_library_init()


初始化MySQL C API库。

mysql_list_dbs()


返回与简单正则表达式匹配的数据库名称。

mysql_list_fields()


返回与简单正则表达式匹配的字段名称。

mysql_list_processes()


返回当前服务器线程的列表。

mysql_list_tables()


返回与简单正则表达式匹配的表名。

mysql_more_results()


检查是否还存在其他结果。

mysql_next_result()


在多语句执行过程中返回/初始化下一个结果。

mysql_num_fields()


返回结果集中的列数。

mysql_num_rows()


返回结果集中的行数。

mysql_options()


为mysql_connect()设置连接选项。

mysql_ping()


检查与服务器的连接是否工作,如有必要重新连接。

mysql_query()


执行指定为“以Null终结的字符串”的SQL查询。

mysql_real_connect()


连接到MySQL服务器。

mysql_real_escape_string()


考虑到连接的当前字符集,为了在SQL语句中使用,对字符串中的特殊字符进行转义处理。

mysql_real_query()


执行指定为计数字符串的SQL查询。

mysql_refresh()


刷新或复位表和高速缓冲。

mysql_reload()


通知服务器再次加载授权表。

mysql_rollback()


回滚事务。

mysql_row_seek()


使用从mysql_row_tell()返回的值,查找结果集中的行偏移。

mysql_row_tell()


返回行光标位置。

mysql_select_db()


选择数据库。

mysql_server_end()


最终确定嵌入式服务器库。

mysql_server_init()


初始化嵌入式服务器库。

mysql_set_server_option()


为连接设置选项(如多语句)。

mysql_sqlstate()


返回关于上一个错误的SQLSTATE错误代码。

mysql_shutdown()


关闭数据库服务器。

mysql_stat()


以字符串形式返回服务器状态。

mysql_store_result()


检索完整的结果集至客户端。

mysql_thread_id()


返回当前线程ID。

mysql_thread_safe()


如果客户端已编译为线程安全的,返回1。

mysql_use_result()


初始化逐行的结果集检索。

mysql_warning_count()


返回上一个SQL语句的告警数。

QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
回复 引用
举报顶端
本站代购的美国服务器详细列表
[离线] usidc5

[usidc5]


级别: 管理员

发帖

 8488


金币

 2753


威望

 3222


贡献值

 0


元宝

 0


    关注Ta
    发消息

只看该作者 板凳  发表于: 2010-07-19
MYSQL C API函数-2
与MySQL交互时,应用程序应使用该一般性原则:

1. 通过调用mysql_library_init(),初始化MySQL库。库可以是mysqlclient C客户端库,或mysqld嵌入式服务器库,具体情况取决于应用程序是否与“-libmysqlclient”或“-libmysqld”标志链接。

2. 通过调用mysql_init()初始化连接处理程序,并通过调用mysql_real_connect()连接到服务器。

3. 发出SQL语句并处理其结果。(在下面的讨论中,详细介绍了使用它的方法)。

4. 通过调用mysql_close(),关闭与MySQL服务器的连接。

5. 通过调用mysql_library_end(),结束MySQL库的使用。

调用mysql_library_init()和mysql_library_end()的目的在于,为MySQL库提供恰当的初始化和结束处理。对于与客户端库链接的应用程序,它们提供了改进的内存管理功能。如果不调用mysql_library_end(),内存块仍将保持分配状态(这不会增加应用程序使用的内存量,但某些内存泄漏检测器将抗议它)。对于与嵌入式服务器链接的应用程序,这些调用会启动并停止服务器。

mysql_library_init()和mysql_library_end()实际上是#define符号,这类符号使得它们等效于mysql_server_init()和mysql_server_end(),但其名称更清楚地指明,无论应用程序使用的是mysqlclient或mysqld库,启动或结束MySQL库时,应调用它们。对于早期的MySQL版本,可调用mysql_server_init()和mysql_server_end()取而代之。

如果愿意,可省略对mysql_library_init()的调用,这是因为,必要时,mysql_init()会自动调用它。

要想连接到服务器,可调用mysql_init()来初始化连接处理程序,然后用该处理程序(以及其他信息,如主机名、用户名和密码)调用mysql_real_connect()。建立连接后,在低于5.0.3版的API中,mysql_real_connect()会将再连接标志(MYSQL结构的一部分)设置为1,或在较新的版本中,将其设置为0。对于该标志,值“1”指明,如果因连接丢失而无法执行语句,放弃之前,会尝试再次连接到服务器。从MySQL 5.0.13开始,可以在mysql_options()上使用MYSQL_OPT_RECONNECT选项,以控制再连接行为。完成连接后,调用mysql_close()中止它。

当连接处于活动状态时,客户端或许会使用mysql_query()或mysql_real_query()向服务器发出SQL查询。两者的差别在于,mysql_query()预期的查询为指定的、由Null终结的字符串,而mysql_real_query()预期的是计数字符串。如果字符串包含二进制数据(其中可能包含Null字节),就必须使用mysql_real_query()。

对于每个非SELECT查询(例如INSERT、UPDATE、DELETE),通过调用mysql_affected_rows(),可发现有多少行已被改变(影响)。

对于SELECT查询,能够检索作为结果集的行。注意,某些语句因其返回行,类似与SELECT。包括SHOW、DESCRIBE和EXPLAIN。应按照对待SELECT语句的方式处理它们。

客户端处理结果集的方式有两种。一种方式是,通过调用mysql_store_result(),一次性地检索整个结果集。该函数能从服务器获得查询返回的所有行,并将它们保存在客户端。第二种方式是针对客户端的,通过调用mysql_use_result(),对“按行”结果集检索进行初始化处理。该函数能初始化检索结果,但不能从服务器获得任何实际行。

在这两种情况下,均能通过调用mysql_fetch_row()访问行。通过mysql_store_result(),mysql_fetch_row()能够访问以前从服务器获得的行。通过mysql_use_result(),mysql_fetch_row()能够实际地检索来自服务器的行。通过调用mysql_fetch_lengths(),能获得关于各行中数据大小的信息。

完成结果集操作后,请调用mysql_free_result()释放结果集使用的内存。

这两种检索机制是互补的。客户端程序应选择最能满足其要求的方法。实际上,客户端最常使用的是mysql_store_result()。

mysql_store_result()的1个优点在于,由于将行全部提取到了客户端上,你不仅能连续访问行,还能使用mysql_data_seek()或mysql_row_seek()在结果集中向前或向后移动,以更改结果集内当前行的位置。通过调用mysql_num_rows(),还能发现有多少行。另一方面,对于大的结果集,mysql_store_result()所需的内存可能会很大,你很可能遇到内存溢出状况。

mysql_use_result()的1个优点在于,客户端所需的用于结果集的内存较少,原因在于,一次它仅维护一行(由于分配开销较低,mysql_use_result()能更快)。它的缺点在于,你必须快速处理每一行以避免妨碍服务器,你不能随机访问结果集中的行(只能连续访问行),你不知道结果集中有多少行,直至全部检索了它们为止。不仅如此,即使在检索过程中你判定已找到所寻找的信息,也必须检索所有的行。

通过API,客户端能够恰当地对查询作出响应(仅在必要时检索行),而无需知道查询是否是SELECT查询。可以在每次mysql_query()或mysql_real_query()后,通过调用mysql_store_result()完成该操作。如果结果集调用成功,查询为SELECT,而且能够读取行。如果结果集调用失败,可调用mysql_field_count()来判断结果是否的确是所预期的。如果mysql_field_count()返回0,查询不返回数据(表明它是INSERT、UPDATE、DELETE等),而且不返回行。如果mysql_field_count()是非0值,查询应返回行,但没有返回行。这表明查询是失败了的SELECT。关于如何实现该操作的示例,请参见关于mysql_field_count()的介绍。

无论是mysql_store_result()还是mysql_use_result(),均允许你获取关于构成结果集的字段的信息(字段数目,它们的名称和类型等)。通过重复调用mysql_fetch_field(),可以按顺序访问行内的字段信息,或者,通过调用mysql_fetch_field_direct(),能够在行内按字段编号访问字段信息。通过调用mysql_field_seek(),可以改变当前字段的光标位置。对字段光标的设置将影响后续的mysql_fetch_field()调用。此外,你也能通过调用mysql_fetch_fields(),一次性地获得关于字段的所有信息。

为了检测和通报错误,MySQL提供了使用mysql_errno()和mysql_error()函数访问错误信息的机制。它们能返回关于最近调用的函数的错误代码或错误消息,最近调用的函数可能成功也可能失败,这样,你就能判断错误是在何时出现的,以及错误是什么。
QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
回复 引用
举报顶端
免费试用30天的美国homestead空间
[离线] usidc5

[usidc5]


级别: 管理员

发帖

 8488


金币

 2753


威望

 3222


贡献值

 0


元宝

 0


    关注Ta
    发消息

只看该作者 地板  发表于: 2011-08-19
使用MySQL connector/C++链接MySQL数据库

首先去MySQL官网下载MySQL connector/C++

http://dev.mysql.com/downloads/connector/cpp/1.0.html


下载第二个包,windows32位非安装版(个人觉得这个包干净)。目前的版本是Connector/C++ 1.0.5。

Windows (x86, 32-bit), ZIP Archive (mysql-connector-c++-noinstall-1.0.5-win32.zip)


将整个包解压到项目文件夹下的的源文件目录。文件夹名字太长,将“mysql-connector-c++-noinstall-1.0.5-win32”改为“mysql”。

下面要配置vs2008的环境。

1. 项目属性页->C/C++->General->Additional Include Directories。将mysql\include目录和mysql\include\cppconn目录添加进去。

2. 项目属性页->Linker->General->Additional Library Directories。将mysql\lib目录添加进去。

3. 项目属性页->Linker->Input->Additional Dependencies。添加这两项mysqlcppconn.lib,mysqlcppconn-static.lib(mysql\lib目录下的两个.lib文件)

4. 将mysql\lib下的mysqlcppconn.dll文件复制到windows\system32文件夹下。

环境配置完毕。

在连接数据库之前,先建立一张表。 (其实这些可以在代码中完成,我这样是为了让测试代码尽可能简练易查错)

打开控制台,输入mysql -u root -p,输入密码。

查看当前已有的数据库。(SQL语句末尾加上';'表示立即执行当前语句。)

mysql> show databases;


创建数据库

mysql> create database test;


使用数据库(这句不能加分号)

mysql> use test


查看已有的表

mysql> show tables;


创建表

mysql> create table testuser ( id INT, name CHAR(20));


插入数据

mysql> insert into testuser(id, name) values(1001, 'google');
mysql> insert into testuser(id, name) values(1002, 'kingsoft');
mysql> insert into testuser(id, name) values(1003, 'firefox');


现在在C++中查询这些数据

#include "stdafx.h"
#include <mysql_connection.h>
#include <mysql_driver.h>
#include <statement.h>
using namespace sql;
using namespace std;
void RunConnectMySQL()
{
      mysql::MySQL_Driver *driver;
      Connection *con;
      Statement *state;
      ResultSet *result;
      // 初始化驱动 
      driver = sql::mysql::get_mysql_driver_instance();
      // 建立链接 
      con = driver->connect("tcp://127.0.0.1:3306", "root", "123");
      state = con->createStatement();
      state->execute("use test");
      // 查询 
      result = state->executeQuery("select * from testuser where id < 1002");
      // 输出查询 
      while(result->next())
      {
            int id = result->getInt("ID");
            string name = result->getString("name");
            cout << id << " : " << name << endl;
      }
      delete state;
      delete con;
}
int _tmain(int argc, _TCHAR* argv[])
{
      RunConnectMySQL();
      getchar();
      return 0;
}


QQ: 378890364 微信:wwtree(省短信费) 紧急事宜发短信到0061432027638  本站微博:http://t.qq.com/wwtree QQ群:122538123
回复 引用
举报顶端
Godaddy优惠码-最新有效
[离线] usidc5

[usidc5]


级别: 管理员

发帖

 8488


金币

 2753


威望

 3222


贡献值

 0


元宝

 0


    关注Ta
    发消息

只看该作者 4楼 发表于: 2011-08-19
MySQL Connector/C++教程

原文地址: http://dev.mysql.com/tech-resources/articles/mysql-connector-cpp.html#trx
翻译: DarkBull(www.darkbull.net)
示例代码:MySqlDemo.7z
译者注:该教程是一篇介绍如何使用C++操作MySQL的入门教程,内容简单易用。我对原文中的一些例子进行了修改,并新添加了部分例子,主要目标是更简单明了的向读者介绍如何操作MySQL数据库。本人也是MySQL的初学者,错误也在所难免,欢迎拍砖!

    这篇教程将一步一步引导您如何去构建和安装MySql Connection/C++ Driver,同时提供几个简单的例子来演示如何连接MySQL数据库,如何向MySQL添加、获取数据。本教程关注如何在C++应用程序中操作MySQL,所以首先应该确定MySQL数据库服务已经开启并且在当前机器能够访问到。
    本教程面向的读者是MySQL Connector/C++的初学者,如果您对C++语言或者MySQL数据库不是很了解,请参考其他的教程。
    教程使用了下面所列的一些工具和技术,来构建、编译、运行例子程序(译者注:这是原文作者使用的环境。笔者使用的环境是:WinXP,MySQL5.1,VS2008, ):

Database  MySQL Server 5.1.24-rc
C++ Driver  MySQL Connector/C++ 1.0.5
MySQL Client Library  MySQL Connector/C 6.0
Compiler  Sun Studio 12 C++ compiler
Make  CMake 2.6.3
Operating System  OpenSolaris 2008.11 32-bit
CPU / ISA  Intel Centrino / x86
Hardware  Toshiba Tecra M2 Laptop


目录
MySQL C++ Driver的实现基于JDBC4.0规范
安装MySQL Connector/C++
运行时依赖

C++ IDE


为示例程序创建数据库与数据表
使用Connector/C++测试数据库连接
使用prepared Statements
使用事务
访问Result Set Metadata
访问Database Metadata
通过PreparedStatment对象访问参数元数据
捕获异常
调试/跟踪 MySQL Connector/C++
更多信息

MySQL C++ Driver的实现基于JDBC4.0规范
    MySQL Connector/C++是由Sun Microsystems开发的MySQL连接器。它提供了基于OO的编程接口与数据库驱动来操作MySQL服务器。
    与许多其他现存的C++接口实现不同,Connector/C++遵循了JDBC规范。也就是说,Connector/C++ Driver的API主要是基于Java语言的JDBC接口。JDBC是java语言与各种数据库连接的标准工业接口。Connector/C++实现了大部分JDBC4.0规范。如果C++程序的开发者很熟悉JDBC编程,将很快的入门。
    MySQL Connector/C++实现了下面这些类:

Driver
Connection
Statement
PreparedStatement
ResultSet
Savepoint
DatabaseMetaData
ResultSetMetaData
ParameterMetaData


    Connector/C++可用于连接MySQL5.1及其以后版本。
    在MySQL Connector/C++发布之前,C++程序员可以使用MySQL C API或者MySQL++访问MySQL。前者是非标准、过程化的C API,后者是对MySQL C API的C++封装。
安装MySQL Connector/C++
    此处略。(译者注:用户可以到MySQL的官网[http://dev.mysql.com/downloads/connector/cpp/1.0.html]去下载MySQL Connector/C++的安装程序,或者只下载dll,或者下载源代码自己编译。笔者在Window平台上使用MySQL,下载了mysql-connector-c++-noinstall-1.0.5-win32这个版本用于调试。)
运行时依赖
    MySQL Connector/C++ Driver依赖MySQL的客户端库,在MySQL安装目录下的lib/opt/libmysql.dll。如果是通过安装程序来安装MySQL Connector/C++,libmysql会一并安装,如果从官网只下载了dll或源码,在使用时,程序必须链接到libmysql.dll。

C++ IDE


    此处略。(译者注:原文作者使用NetBean作为C++的IED。笔者使用VS2008)
为示例程序创建数据库与数据表
    (译者注:此节略掉许多不太重要的内容。)在MySQL中创建test数据库,使用下面语句创建数据表:City:

Create Table: CREATE TABLE `City` ( `CityName` varchar(30) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=ascii


     然后向City表中添加一些数据。最后表的内容为:

mysql> SELECT * FROM City;
+--------------------+
| CityName           |
+--------------------+
| Hyderabad, India   |
| San Francisco, USA  |
| Sydney, Australia  |
+--------------------+
3 rows in set (0.17 sec)


使用Connector/C++测试数据库连接
    下面的代码演示如何使用Connector/C++连接到MySQL服务器:
    连接到test数据库;
    执行一个查询获取City表中的数据,显示在控制台上; 
    使用Prepared Statements向City表插入数据;
    使用savepoints演示事务;
    获取结果集和数据库的元信息;
    例子代码仅仅用于演示,不建议读者在实际开发中使用这种样式的代码。(译者注:例子代码很长,如果看不太明白,没关系,等阅读完全文之后再回过头来看)

#include <iostream> #include <map> #include <string> #include <memory> #include "mysql_driver.h" #include "mysql_connection.h" #include "cppconn/driver.h" #include "cppconn/statement.h" #include "cppconn/prepared_statement.h" #include "cppconn/metadata.h" #include "cppconn/exception.h" #define DBHOST "tcp://127.0.0.1:3306" #define USER "root" #define PASSWORD "000000" #define DATABASE "test" #define NUMOFFSET 100 #define COLNAME 200 using namespace std; using namespace sql; #pragma comment(lib, "mysqlcppconn.lib") void Demo(); int main(int argc, char *argv[]) { Demo(); return 0; } /* 获取数据库信息 */ static void GetDBMetaData(Connection *dbcon) { if (dbcon->isClosed()) { throw runtime_error("DatabaseMetaData FAILURE - database connection closed"); } cout << "/nDatabase Metadata" << endl; cout << "-----------------" << endl; cout << boolalpha; /* The following commented statement won't work with Connector/C++ 1.0.5 and later */ //auto_ptr < DatabaseMetaData > dbcon_meta (dbcon->getMetaData()); DatabaseMetaData *dbcon_meta = dbcon->getMetaData(); cout << "Database Product Name: " << dbcon_meta->getDatabaseProductName() << endl; cout << "Database Product Version: " << dbcon_meta->getDatabaseProductVersion() << endl; cout << "Database User Name: " << dbcon_meta->getUserName() << endl << endl; cout << "Driver name: " << dbcon_meta->getDriverName() << endl; cout << "Driver version: " << dbcon_meta->getDriverVersion() << endl << endl; cout << "Database in Read-Only Mode?: " << dbcon_meta->isReadOnly() << endl; cout << "Supports Transactions?: " << dbcon_meta->supportsTransactions() << endl; cout << "Supports DML Transactions only?: " << dbcon_meta->supportsDataManipulationTransactionsOnly() << endl; cout << "Supports Batch Updates?: " << dbcon_meta->supportsBatchUpdates() << endl; cout << "Supports Outer Joins?: " << dbcon_meta->supportsOuterJoins() << endl; cout << "Supports Multiple Transactions?: " << dbcon_meta->supportsMultipleTransactions() << endl; cout << "Supports Named Parameters?: " << dbcon_meta->supportsNamedParameters() << endl; cout << "Supports Statement Pooling?: " << dbcon_meta->supportsStatementPooling() << endl; cout << "Supports Stored Procedures?: " << dbcon_meta->supportsStoredProcedures() << endl; cout << "Supports Union?: " << dbcon_meta->supportsUnion() << endl << endl; cout << "Maximum Connections: " << dbcon_meta->getMaxConnections() << endl; cout << "Maximum Columns per Table: " << dbcon_meta->getMaxColumnsInTable() << endl; cout << "Maximum Columns per Index: " << dbcon_meta->getMaxColumnsInIndex() << endl; cout << "Maximum Row Size per Table: " << dbcon_meta->getMaxRowSize() << " bytes" << endl; cout << "/nDatabase schemas: " << endl; auto_ptr < ResultSet > rs ( dbcon_meta->getSchemas()); cout << "/nTotal number of schemas = " << rs->rowsCount() << endl; cout << endl; int row = 1; while (rs->next()) { cout << "/t" << row << ". " << rs->getString("TABLE_SCHEM") << endl; ++row; } // while cout << endl << endl; } /* 获取结果集信息 */ static void GetResultDataMetaBata(ResultSet *rs) { if (rs -> rowsCount() == 0) { throw runtime_error("ResultSetMetaData FAILURE - no records in the result set"); } cout << "ResultSet Metadata" << endl; cout << "------------------" << endl; /* The following commented statement won't work with Connector/C++ 1.0.5 and later */ //auto_ptr < ResultSetMetaData > res_meta ( rs -> getMetaData() ); ResultSetMetaData *res_meta = rs -> getMetaData(); int numcols = res_meta -> getColumnCount(); cout << "/nNumber of columns in the result set = " << numcols << endl << endl; cout.width(20); cout << "Column Name/Label"; cout.width(20); cout << "Column Type"; cout.width(20); cout << "Column Size" << endl; for (int i = 0; i < numcols; ++i) { cout.width(20); cout << res_meta -> getColumnLabel (i+1); cout.width(20); cout << res_meta -> getColumnTypeName (i+1); cout.width(20); cout << res_meta -> getColumnDisplaySize (i+1) << endl << endl; } cout << "/nColumn /"" << res_meta -> getColumnLabel(1); cout << "/" belongs to the Table: /"" << res_meta -> getTableName(1); cout << "/" which belongs to the Schema: /"" << res_meta -> getSchemaName(1) << "/"" << endl << endl; } /* 打印结果集中的数据 */ static void RetrieveDataAndPrint(ResultSet *rs, int type, int colidx, string colname) { /* retrieve the row count in the result set */ cout << "/nRetrieved " << rs->rowsCount() << " row(s)." << endl; cout << "/nCityName" << endl; cout << "--------" << endl; /* fetch the data : retrieve all the rows in the result set */ while (rs->next()) { if (type == NUMOFFSET) { cout << rs -> getString(colidx) << endl; } else if (type == COLNAME) { cout << rs -> getString(colname) << endl; } // if-else } // while cout << endl; } void Demo() { Driver *driver; Connection *con; Statement *stmt; ResultSet *res; PreparedStatement *prep_stmt; Savepoint *savept; int updatecount = 0; /* initiate url, user, password and database variables */ string url(DBHOST); const string user(USER); const string password(PASSWORD); const string database(DATABASE); try { driver = get_driver_instance(); /* create a database connection using the Driver */ con = driver -> connect(url, user, password); /* alternate syntax using auto_ptr to create the db connection */ //auto_ptr con (driver -> connect(url, user, password)); /* turn off the autocommit */ con -> setAutoCommit(0); cout << "/nDatabase connection/'s autocommit mode = " << con -> getAutoCommit() << endl; /* select appropriate database schema */ con -> setSchema(database); /* retrieve and display the database metadata */ GetDBMetaData(con); /* create a statement object */ stmt = con -> createStatement(); cout << "Executing the Query: /"SELECT * FROM City/" .." << endl; /* run a query which returns exactly one result set */ res = stmt -> executeQuery ("SELECT * FROM City"); cout << "Retrieving the result set .." << endl; /* retrieve the data from the result set and display on stdout */ RetrieveDataAndPrint (res, NUMOFFSET, 1, string("CityName")); /* retrieve and display the result set metadata */ GetResultDataMetaBata (res); cout << "Demonstrating Prepared Statements .. " << endl << endl; /* insert couple of rows of data into City table using Prepared Statements */ prep_stmt = con -> prepareStatement ("INSERT INTO City (CityName) VALUES (?)"); cout << "/tInserting /"London, UK/" into the table, City .." << endl; prep_stmt -> setString (1, "London, UK"); updatecount = prep_stmt -> executeUpdate(); cout << "/tCreating a save point /"SAVEPT1/" .." << endl; savept = con -> setSavepoint ("SAVEPT1"); cout << "/tInserting /"Paris, France/" into the table, City .." << endl; prep_stmt -> setString (1, "Paris, France"); updatecount = prep_stmt -> executeUpdate(); cout << "/tRolling back until the last save point /"SAVEPT1/" .." << endl; con -> rollback (savept); con -> releaseSavepoint (savept); cout << "/tCommitting outstanding updates to the database .." << endl; con -> commit(); cout << "/nQuerying the City table again .." << endl; /* re-use result set object */ res = NULL; res = stmt -> executeQuery ("SELECT * FROM City"); /* retrieve the data from the result set and display on stdout */ RetrieveDataAndPrint(res, COLNAME, 1, string ("CityName")); cout << "Cleaning up the resources .." << endl; /* Clean up */ delete res; delete stmt; delete prep_stmt; con -> close(); delete con; } catch (SQLException &e) { cout << "ERROR: " << e.what(); cout << " (MySQL error code: " << e.getErrorCode(); cout << ", SQLState: " << e.getSQLState() << ")" << endl; if (e.getErrorCode() == 1047) { /* Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR) Message: Unknown command */ cout << "/nYour server does not seem to support Prepared Statements at all. "; cout << "Perhaps MYSQL < 4.1?" << endl; } return; } catch (std::runtime_error &e) { cout << "ERROR: " << e.what() << endl; return; } return; }


建立数据库连接
    sql::Connection代表到数据库的连接,可以通过sql::Driver来创建。sql::mysql::get_mysql_driver_instance()方法用于获取sql::Driver,通过调用sql::Driver::connect方法来创建sql::Connection对象。(译者注:笔者使用的Connector/C++版本与作者使用的版本不一样,接口方面也有点细微的差别。这里根据笔者使用的最新版本mysql-connector-c++-noinstall-1.0.5-win32来说明。)
    下面是get_mysql_driver_instance与connect这两个方法的签名:

view plaincopy to clipboardprint?
/* mysql_driver.h */
MySQL_Driver *sql::mysql::get_mysql_driver_instance()
/* mysql_driver.h */
sql::Connection * connect(const std::string& hostName, const std::string& userName, const std::string& password);
sql::Connection * connect(std::map<std::string, sql::ConnectPropertyVal> & options);
/* mysql_driver.h */
MySQL_Driver *sql::mysql::get_mysql_driver_instance()
/* mysql_driver.h */
sql::Connection * connect(const std::string& hostName, const std::string& userName, const std::string& password);


sql::Connection * connect(std::map<std::string, sql::ConnectPropertyVal> & options);    Driver类重载了connect方法,一个接收数据库地址的url、用户名和密码的字符串,后一个接收一个map,map中以key/value的形式包含数据库地址、用户名与密码。使用TCP/IP连接到MySql服务器的url字符串的格式如下:"tcp://[hostname[:port]][/schemaname]"。例如:tcp://127.0.0.1:5555/some_scehma。hostname和端口号是可选的,如果省略,默认是127.0.0.1与3306。如果hostname为"localhost",会被自动转换为"127.0.0.1"。schemaname也是可选的,如果连接字符串中没有设置schema,需要在程序中通过Connection::setSchema方法手动设置。
    在unix系统上,可以通过UNIX domain socket连接运行在本地的MySQL服务,连接字符串格式为:"unix://path/to/unix_socket_file",例如:unix:///tmp/mysql.sock.
    在windows系统上,可以以命名管道的方式连接到运行在本地的MySQL数据库,连接字符串格式为:"pipe://path/to/the/pipe"。MySQL服务必须启动允许命名管道连接,可以在启动MySQL服务器的时候,通过--enable-named-pipe命令行选项来启动该功能。如果没有通过--socket=name选项设置命名管道的名称,系统默认使用MySQL。在windows上,管道的名称是区别大小写的。
    下面的代码片断尝试连接到本地的MySQL服务器,通过3306端口,用户名为root,密码是000000,schema为test.

view plaincopy to clipboardprint?
sql::mysql::MySQL_Driver *driver = 0;
sql::Connection *conn = 0;
try
{
driver = sql::mysql::get_mysql_driver_instance();
conn = driver->connect("tcp://localhost:3306/test", "root", "000000");


    cout << "连接成功" << endl; 

}
catch (...)
{


    cout << "连接失败" << endl; 

}
if (conn != 0)
{
      delete conn;
}
sql::mysql::MySQL_Driver *driver = 0;
sql::Connection *conn = 0;
try
{
driver = sql::mysql::get_mysql_driver_instance();
conn = driver->connect("tcp://localhost:3306/test", "root", "000000");


cout << "连接成功" << endl;

}
catch (...)
{


cout << "连接失败" << endl;

}
if (conn != 0)
{
      delete conn;
}


也可以通过connection的第二个重载方法连接MySQL。ConnectPropertyVal是union类型,在connection.h中定义。

view plaincopy to clipboardprint?
sql::mysql::MySQL_Driver *driver = 0;
sql::Connection *conn = 0;
std::map<std::string, ConnectPropertyVal> connProperties;
ConnectPropertyVal tmp;
tmp.str.val = "tcp://127.0.0.1:3306/test";
connProperties[std::string("hostName")] = tmp;
tmp.str.val = "root";
connProperties[std::string("userName")] = tmp;
tmp.str.val = "000000";
connProperties[std::string("password")] = tmp;
try
{
driver = sql::mysql::get_mysql_driver_instance();
conn = driver -> connect(connProperties);


    cout << "连接成功" << endl; 

}
catch(...)
{


    cout << "连接失败" << endl; 

}
if (conn != 0)
{
      delete conn;
}
sql::mysql::MySQL_Driver *driver = 0;
sql::Connection *conn = 0;
std::map<std::string, ConnectPropertyVal> connProperties;
ConnectPropertyVal tmp;
tmp.str.val = "tcp://127.0.0.1:3306/test";
connProperties[std::string("hostName")] = tmp;
tmp.str.val = "root";
connProperties[std::string("userName")] = tmp;
tmp.str.val = "000000";
connProperties[std::string("password")] = tmp;
try
{
driver = sql::mysql::get_mysql_driver_instance();
conn = driver -> connect(connProperties);


cout << "连接成功" << endl;

}
catch(...)
{


cout << "连接失败" << endl;

}
if (conn != 0)
{
delete conn;


}    上面的连接字符串可以将协议与路径分开写(译者注:C++会把两个连在一起的字符串合并成一个字符串),如:mp.str.val = "unix://" "/tmp/mysql.sock"
    当建立与服务器之间的连接后,通过Connection::setSessionVariable方法可以设置像sql_mode这样的选项。
C++细节注意点
    像Connection这样的对象,必须在用完之后,显式的delete,例如:

view plaincopy to clipboardprint?
sql::Connection *conn = driver -> connect("tcp://127.0.0.1:3306", "root", "000000");
// do something
delete conn
sql::Connection *conn = driver -> connect("tcp://127.0.0.1:3306", "root", "000000");
// do something


delete conn    使用使用auto_ptr来维护连接对象的清理, 如:

view plaincopy to clipboardprint?
use namespace std;
use namespace sql;
auto_ptr < Connection > con ( driver -> connect("tcp://127.0.0.1:3306", "root", "000000") );
use namespace std;
use namespace sql;
auto_ptr < Connection > con ( driver -> connect("tcp://127.0.0.1:3306", "root", "000000") );获取Statement对象
    Statement对象用于向MySQL服务器发送SQL语句。该对象可以通过调用Connection::createStatement方法获得。Statement向MySQL发送一个静态的SQL语句,然后从MySQL获取操作的结果,我们无法向它提供sql参数。如果要向它传递参数,可以使用PreparedStatemenet类。如果相同的SQL语句(只SQL参数不同)要被执行多次,建议使用PreparedStatement类。
    Connection::createStatement的签名如下(关于Connection类所提供的方法列表,可以查看connection.h头文件):
view plaincopy to clipboardprint?
/* connection.h */   
ment* Connection::createStatement();
/* connection.h */


Statement* Connection::createStatement();    下面的的代码段通过调用Connection对象的createStatemenet来获取一个Statement对象:

view plaincopy to clipboardprint?
Connection *conn;  // Connection对象的引用 
Statement *stat;
Statement stat = conn -> createStatement();
Connection *conn;  // Connection对象的引用
Statement *stat;


Statement stat = conn -> createStatement(); 执行SQL语句
    在执行SQL语句之前应该通过Connection对象的setSchema方法设置相应的Schema(如果没有在数据库地址URL中指定schema)。
    Statement::executeQuery用于执行一个Select语句,它返回ResultSet对象。Statement::executeUpdate方法主要用于执行INSERT, UPDATE, DELETE语句(executeUpdate可以执行所有的SQL语句,如DDL语句,像创建数据表。),该方法返回受影响记录的条数。
    如果你不清楚要执行的是像select这样的查询语句还是像update/insert/delete这样的操作语句,可以使用execute方法。对于查询语句,execute()返回True,然后通过getResultSet方法获取查询的结果;对于操作语句,它返回False,通过getUpdateCount方法获取受影响记录的数量。
    在一些特殊的情况下,单条SQL语句(如执行存储过程),可能会返回多个结果集 和/或 受影响的记录数量。如果你不想忽略这些结果,通过getResultSet或getUpdateCount方法第一个结果后,再通过getMoreResults()来获取其他的结果集。
    下面是这些方法的签名,可以在statement.h头文件中查阅Statement的完整方法列表。

view plaincopy to clipboardprint?
/* connection.h */
void Connection::setSchema(const std::string& catalog);
/* statement.h */
ResultSet* Statement::executeQuery (const std::string& sql);
int Statement::executeUpdate (const std::string& sql);
bool Statement::execute (const std::string& sql);
ResultSet* Statement::getResultSet();
uint64_t Statement::getUpdateCount();
/* connection.h */
void Connection::setSchema(const std::string& catalog);
/* statement.h */
ResultSet* Statement::executeQuery (const std::string& sql);
int Statement::executeUpdate (const std::string& sql);
bool Statement::execute (const std::string& sql);
ResultSet* Statement::getResultSet();


uint64_t Statement::getUpdateCount();    这些方法出错时都会抛出SQLException异常,所以在你的代码中应该使用try...catch语句块来捕获这些异常。
    现在回顾上面那个完全的例子,你会发现获取City表的所有记录是如此的简单:

view plaincopy to clipboardprint?
Statement *stmt;
ResultSet *res;
res = stmt -> executeQuery ("SELECT * FROM City");
Statement *stmt;
ResultSet *res;


res = stmt -> executeQuery ("SELECT * FROM City");    executeQuery方法返回ResultSet对象,它包含了查询的结果。在以下情况下,executeQuery会抛出SQLException异常:数据库在执行查询时出错;在一个关闭的Statement对象上调用executeQuery;给出的SQL语句返回的不是一个简单的结果集;
    上面的代码可以用Statement::execute()重写:

view plaincopy to clipboardprint?
bool retvalue = stmt -> execute ("SELECT * FROM City");
if (retvalue)
{
      res = stmt -> getResultSet();
}
else
{
...
}
bool retvalue = stmt -> execute ("SELECT * FROM City");
if (retvalue)
{
      res = stmt -> getResultSet();
}
else
{
...


}    execute()返回True表示操作的结果是一个ResultSet对象,否则结果是受影响记录的数量或没有结果。当返回True时,通过getResultSet方法获取结果集,在返回False的情况下调用getResultSet方法,将返回NULL。
    当数据库在执行时发生错误或者在一个已关闭的Statement对象上执行execute与getResultSet方法,都会抛出SQLException异常。
    如果要往数据库里添加一条新的记录,可以像下面的例子一样简单的调用executeUpdate方法:

view plaincopy to clipboardprint?
int updateCount = stmt -> executeUpdate ("INSERT INTO City (CityName) VALUES ('Napier, New Zealand')");


    int updateCount = stmt -> executeUpdate ("INSERT INTO City (CityName) VALUES ('Napier, New Zealand')");    如果executeUpdate执行的是像INSERT, UPDATE或DELETE这样的数据操作语句(DML),它返回受影响的记录的数量;如果执行的是数据定义语句(DDL),它返回0。在数据库操作失败,或者在一个已经关闭的Statement上调用该方法,或者给出的SQL语句是一个查询语句(会返回结果集),该方法会抛出SQLException异常。
    下面的代码使用execute和getUpdateCount方法来生写上面的例子:

view plaincopy to clipboardprint?
int updateCount = 0;
bool retstatus = stat->execute("INSERT INTO City (CityName) VALUES ('Napier, New Zealand')");
if (!retstatus)
{
      updateCount = stat->getUpdateCount();
}
else
{
...
}
int updateCount = 0;
bool retstatus = stat->execute("INSERT INTO City (CityName) VALUES ('Napier, New Zealand')");
if (!retstatus)
{
      updateCount = stat->getUpdateCount();
}
else
{
...


}从ResultData中获取数据
    上面的段落介绍了执行SQL查询的方法:executeQuery和execute,用于获取ResultSet对象。我们可以通过ResultSet访问查询的结果。每一个ResultSet都包含一个游标(cursor),它指向数据集中的当前记录行。ResultSet中排列的记录是有序的(译者注:只能按顺序一条一条获取,不能跳跃式获取)。(但)在同一行中,列值的访问却是随意的:可以通过列的位置或者名称。通过列的名称访问列值让代码更清晰,而通过位置访问列值则更高效。
    列的名称通过SQL语句的AS子名设定,如果SQL语句中没有使用AS子名,列的名称默认为数据表中对应的列名。例如对于"SELECT CityName AS CN FROM City",CN就是结果集中列的名称。
    在ResultSet中的数据,可以通过getXX系列方法来获取,例如:getString(), getInt(),"XX"取决于数据的类型。next()与previous()使游标移到结果集中的下一条或上一条记录。
    Statement执行SQL语句返回ResultSet对象后,ResultSet就变成一个独立的对象,与原先的Statement再也没有联系,即使Statement对象关闭,重新执行其他sql语句,或者获取多个结果集中的下一个。ResultSet将一直有效,除非显式或隐式地将其关闭。
    在撰写本文时,对于Statement对象,MySQL Connector/C++总是返回缓存结果,这些结果在客户端缓存。不管结果集数据量大小,MySQLConnector/C++ Driver总是获取所有的数据。希望以后的版本中,Statement对象能够返回缓存和非缓存的结果集。
    下面是数据获取方法的签名,可以在resultset.h头文件中查看所有ResultSet类支持的方法。

view plaincopy to clipboardprint?
/* resultset.h */
size_t ResultSet::rowsCount() const;
void ResultSet::close();
bool ResultSet::next();
bool ResultSet::previous();
bool ResultSet::last();
bool ResultSet::first();
void ResultSet::afterLast();
void ResultSet::beforeFirst();
bool ResultSet::isAfterLast() const;
bool ResultSet::isBeforeFirst()const;
bool ResultSet::isClosed() const;
bool ResultSet::isNull(uint32_t columnIndex) const;
bool ResultSet::isNull(const std::string& columnLabel) const;
bool ResultSet::wasNull() const;
std::string ResultSet::getString(uint32_t columnIndex) const;
std::string ResultSet::getString(const std::string& columnLabel) const;
int32_t ResultSet::getInt(uint32_t columnIndex) const;
int32_t ResultSet::getInt(const std::string& columnLabel) const;
/* resultset.h */
size_t ResultSet::rowsCount() const;
void ResultSet::close();
bool ResultSet::next();
bool ResultSet::previous();
bool ResultSet::last();
bool ResultSet::first();
void ResultSet::afterLast();
void ResultSet::beforeFirst();
bool ResultSet::isAfterLast() const;
bool ResultSet::isBeforeFirst()const;
bool ResultSet::isClosed() const;
bool ResultSet::isNull(uint32_t columnIndex) const;
bool ResultSet::isNull(const std::string& columnLabel) const;
bool ResultSet::wasNull() const;
std::string ResultSet::getString(uint32_t columnIndex) const;
std::string ResultSet::getString(const std::string& columnLabel) const;
int32_t ResultSet::getInt(uint32_t columnIndex) const;


int32_t ResultSet::getInt(const std::string& columnLabel) const;    在下面的简单示例中,查询语句"SELECT * FROM City"返回的ResultSet中只包含一列:CityName,数据类型为String,对应MySQL中的VARCHAR类型。这个例子通过next方法循环从结果集中获取CityName值,并显示在控制台上:

view plaincopy to clipboardprint?
while (res -> next())
cout << rs -> getString("CityName") << endl;
while (res -> next())
{
cout << rs -> getString("CityName") << endl;


}    也可以通过位置来获取列值(位置从1开始而非从0开始),下面的代码产生相同的结果:

view plaincopy to clipboardprint?
while (res -> next())
cout << rs -> getString(1) << endl;
while (res -> next())
{
cout << rs -> getString(1) << endl;


}    如果数据库中该字段的值为NULL,getString将返回一个空的字符串。Result::isNull用于判断指定列在数据库中的值是否为NULL。Result::wasNULL()用于判断最近读取的列的值是否为空。
    下面的例子演示了通过cursor(游标)倒序读取结果集中的数据:

view plaincopy to clipboardprint?
/* Move the cursor to the end of the ResultSet object, just after the last row */
res -> afterLast();
if (!res -> isAfterLast())
{
      throw runtime_error("Error: Cursor position should be at the end of the result set after the last row.");
}
/* fetch the data : retrieve all the rows in the result set */
while (res -> previous())
{
      cout << rs->getString("CityName") << endl;
}
/* Move the cursor to the end of the ResultSet object, just after the last row */
res -> afterLast();
if (!res -> isAfterLast())
{
      throw runtime_error("Error: Cursor position should be at the end of the result set after the last row.");
}
/* fetch the data : retrieve all the rows in the result set */
while (res -> previous())
{
cout << rs->getString("CityName") << endl;


}    getString方法在以下情况下会抛出SQLException异常:指定列名或位置不存在;数据库在执行操作时失败;在一个关闭的cursor上执行调用该方法。

使用Prepared Statements对象
?    Mysql4.1版本中引进prepared statements对象是为了方便重复执行同一个query语句,尽管在每次执行中有不同的参数。Prepared Statements对象通过将sql语句和数据分割开,可以提高安全性。 这种将sql语句和数据分割开的做法,可以避免系统受一种类似SQL 注入式攻击。然而请记住,虽然这种做法可以提高安全性;但是防止系统遭受攻击并且在输入传送给数据库进行处理之前,对输入进行优化,仍然是程序开发者的责任。
    Prepared Statements对象是最佳的处理参数化的Sql statements的方式。 不像Statement对象, PreparedStatement对象被建立时就被赋予了Sql语句。在多数情况下,SQL语句被直接送往数据库服务器中进行语法检查、语法最佳化和语法分析的地方,以便最后由Mysql服务器执行。因此,PreparedStatement对象包含预编译过的sql语句。这意味着一旦prepared statement被执行,数据库只要执行PreparedStatement中的 SQL语句就行,而不用在使用之前进行编译。减少查询语句的解析可以使Mysql服务区的重要性能得到提升。
    Mysql的客户端/服务器协议,支持两种将数据库查询结果返回客户端的方法。文本协议总是在通过网络传送数据之前,将其转变为字符串(string)类型,服务器再将字符串数据转换为合适的数据类型。 不像文本协议,二进制协议在有些地方避免了将数据转换为string类型。prepared statements仅仅支持二进制协议。利用网络传送数据的基础之上,prepared statements所采用的二进制协议,可以通过减少在服务端和客户端的解码及译码过程,减轻CPU和网络的压力。
Connector/C++ 建立在MySQL C API和C library“libmysql”的基础之上,因此它集成了所有MySQL服务器和MySQL C API的限制。下面的语句可以在Connecter/C++中用作prepared statements :“CALL, CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE, 和大部分的显示statements。prepared statement协议并不支持USE。并且,Connector/C++也不包含prepared statement for the USE statement.。Check the MySQL C API Prepared Statements documentation for the complete list of statements which can be prepared.
Although PreparedStatement objects can be used with SQL statements with no parameters, 你可能在参数化的Sql语句中经常使用到他们。
创建一个PreparedStatement对象:
就像Statement对象一样,可以通过使用Connection instance创建PreparedStatement对象。在一个被激活的数据库Connection对象中,创建用于发送参数化的Sql语句到数据库的PreparedStatement,并使用prepareStatement的方法。
方法签名:

/* connection.h */
PreparedStatement * Connection::prepareStatement(const std::string& sql) throws SQLException;


prepareStatement()函数反悔一个新的PreparedStatement对象,该对象包含预编译的SQL语句。这个方法在遇到数据库进入错误或者在一个关闭的连接上调用此方法是,将发出SQL异常。
下面的代码片段用于创建PreparedStatement对象。

Connection *con;
PreparedStatement *prep_stmt;
prep_stmt = con -> prepareStatement ("INSERT INTO City (CityName) VALUES (?)");


给PreparedStatement对象的参数提供参数值。
如果是参数化的Sql语句,在执行该参数化Sql语句之前,就需要在问号占位符处提供一个数值。可以通过调用在PreparedStatement类中定义的setXX方法来完成该操作。注意:必须使用兼容数据类型的setXX()。例如,如果参数为INTEGER类型,就需要使用setInt();如果参数是String类型,就需要使用setString()。
下面的代码片段利用"London, UK",设置问号占位符处为std::string类型。

PreparedStatement *prep_stmt;
prep_stmt -> setString (1, "London, UK");


在PreparedStatement对象中运行Sql语句:
类似于在Statement类型中运行Sql语句,你可以使用executeQuery方法来执行SELECT语句,使用executeUpdate方法来执行SQL语句,比如: INSERT, UPDATE,DELETE或者一个不返回任何数据的SQL语句( SQL DDL 语句)。也可以使用execute方法来执行任何类型的SQL语句,通过检查Execute返回的数据,再进行更多的操作。
一些相关函数的签名方法如下,如果想得到PreparedStatement对象支持的完整的接口,请在connector/C++安装目录下查阅“prepared_statement.h”头文件。

/* prepared_statement.h */
ResultSet* PreparedStatement::executeQuery();
int PreparedStatement::executeUpdate();
bool PreparedStatement::execute();
ResultSet* PreparedStatement::getResultSet();
uint64_t PreparedStatement::getUpdateCount();


?PreparedStatement执行SQL语句返回ResultSet对象后,ResultSet就变成一个独立的对象,与原先的Statement再也没有联系,即使Statement对象关闭,重新执行其他sql语句,或者获取多个结果集中的下一个。ResultSet将一直有效,除非显式或隐式地将其关闭。
下面的代码片段在PreparedStatement对象中执行Sql语句:

prep_stmt -> setString (1, "London, UK");
int updatecount = prep_stmt -> executeUpdate();


一般情况下,参数值将在重复执行该语句之前保持不变。

--转自 北京联动北方科技有限公司




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论