目录
通过mySQL++库
简介
安装和配置
linux环境
WIN32环境
C++调用mysql++
通过Mysql connector c++库
前言
Connector C++ 使用
3.4 静态库和动态库:
动态库:创建项目和配置
代码编写
使用中会遇到的问题
1.返回的结果中文乱码问题:
2,插入数据时出现Incorrect string value: '\xC0\xAD\xC0\xAD' for column 'user_name' at row 1,数据库无法识别的字符串错误
3、使用C++获取系统时间并存进Mysql中DateTime类型的字段
更多实例
mysql开发中文博客:iMySQL | 老叶茶馆 – Oracle MySQL ACE Director,专注MySQL
2020-04-20 20:29:49
MySQL其实提供了C实现的接口,而MySQL++则是一个C++实现的封装MySQL C接口的一个Wrapper,遵循了标准C++的规则,是个跨平台的开源工具。我们主要用MySQL++来开发C++程序。
还是万年不变的新手主题——安装和配置
安装MySQL++之前需要先安装MySQL:
[root@ollen mysql++]# yum install mysql-devel
紧接着下载MySQL++源码并解压,我们把压缩包解压到/usr/mysql++下:
[root@ollen mysql++]# wget http://www.tangentsoft.net/mysql++/releases/mysql++-3.2.2.tar.gz
[root@ollen mysql++]# tar -zxvf mysql++-3.2.2.tar.gz
[root@ollen mysql++]# mv mysql++-3.2.2 mysql++
进入mysql++目录下,开始编译,先执行./configure生成makefile文件,之后再make,编译出libmysqlpp.so库文件:
[root@ollen mysql++]# ./configure --enable-thread-check --enable-disasm LDFLAGS='-pthread'
[root@ollen mysql++]# make
[root@ollen mysql++]# make install
(注意:configure 不加--enable-disasm LDFLAGS='-pthread'参数make会报错undefined reference to symbol 'pthread_create@@GLIBC_2.2.5' )
install成功后会将.so文件拷贝到/usr/local/lib下,并把.h头文件拷贝到/usr/local/include下。
到这里MySQL++已经安装到本机了,然而如果直接在C++代码里引用如下头文件是无法编译通过的!
#include
原因是C++在编译时需要加载这个动态库,默认情况下,g++编译器只会使用/lib和/usr/lib这两个目录下的库文件。回头看一下make之前的./configure步骤,我们并没有指定--prefix=/some/path,所以库会默认安装到/usr/local目录下。既然libmysqlpp.so是在/usr/local/lib下,编译器当然就无法找到它的定义了。
那么编译器如何正确找到/usr/local/lib目录呢?
/etc/ld.so.conf文件记录了编译器编译时使用的动态库路径!那我们把/usr/local/lib路径加入到文件末尾就可以了!
配置文件修改保存后,通过ldconfig程序(在usr/sbin/下),将/etc/ld.so.conf文件列举的路径下的库文件缓存到/etc/ld.so.cache以供开发使用:
[root@ollen mysql++]# ldconfig
建议多做一步,创建so的连接:
[root@localhost mysql++]# ln -s /usr/local/lib/libmysqlpp.so /usr/lib/libmysqlpp.so
到这里就配置完成了。
1、下载源码,解压,用VS打开工程
2、mysql++是对mysqlconnect的封装,所以依赖下载:mysqlconnect
3、mysqlconnect 下下来后是MYSQL,解压,将其中的MySQL Connector C 6.1.5 放到C盘,查看VS工程的配置
按教程 【VS】VS工程设置, 将include和lib目录设置到MySQL Connector C 6.1.5\include和MySQL Connector C 6.1.5\lib
然后右键VS工程的mysqlpp项目--》设置生成的库类型未lib---》右键项目---》生成--》生产的mysqlpp.lib在工程配置的输出目录下。
把mysql++-3.2.5\lib下的头文件取出,放到一个文件夹 这些头文件就是mysqlpp.lib的头文件
我先用MySQL创建了一个test数据库,并添加了一张Student表,结构如下:
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`Sid` char(8) NOT NULL DEFAULT '',
`Sname` char(20) NOT NULL DEFAULT '',
`Sage` int(11) NOT NULL DEFAULT '0',
`Sgen` char(1) NOT NULL DEFAULT '',
`Sdept` char(10) NOT NULL DEFAULT '',
PRIMARY KEY (`Sid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `student` VALUES ('09388308','zhsuiy',19,'F','MD8-208'),('09388321','David',20,'M','ZS4-731'),('09388334','zhxilin',20,'M','ZS4-722');
并且插入了如下一些测试数据:
在C++代码里,我们连接这个test数据库之后,进行一个查询,并将结果打印出来:
#include
#include
using namespace std;
int main()
{
const char* db = 0, *server = 0, *user = 0, *password = "";
db = "test";
server = "localhost";
user = "root";
password = "1234567";
mysqlpp::Connection conn(false);
if (conn.connect(db, server, user, password))
{
cout << "connect db succeed. " << endl;
mysqlpp::Query query = conn.query("SELECT * FROM student");
if (mysqlpp::StoreQueryResult res = query.store())
{
cout.setf(ios::left); //left 输出调整为左对齐.
cout << setw(31) << "Sid" <<
setw(10) << "Sname" << //setw(10)设置输出的域宽,不足补齐
setw(10) << "Sage" <<
setw(10) << "Sgender" <<
setw(10) << "SDepartment" << endl;
mysqlpp::StoreQueryResult::const_iterator it;
for (it = res.begin(); it != res.end(); ++it)
{
mysqlpp::Row row = *it;
cout << setw(30) << row[0] << ' ' <<
setw(9) << row[1] << ' ' <<
setw(9) << row[2] << ' ' <<
setw(9) << row[3] << ' ' <<
setw(9) << row[4] << ' ' <<
endl;
}
}
}
else
{
cout << "connect db fail. " << endl;
}
return 0;
}
编译命令如下,编译时需要链接mysql和mysql++:
g++ -o main hello.cpp -lmysqlpp -I/usr/include/mysql -I/usr/local/include/mysql++
g++ -o main hello.cpp -L /usr/local/lib/ -Wl,-rpath="/usr/local/lib" -lmysqlpp -I/usr/include/mysql -I/usr/local/include/mysql++
(安装的mysql++的库libmysqlpp.so在/usr/local/lib下,所以编译项加-Wl,-rpath="/usr/local/lib",让程序运行时去"/usr/local/lib"找库)
解释一下后面这段参数:
-Ldir(大写/eL/):编译时查找路径dir,这里分别是/usr/lib/mysql和/usr/local/lib,分别指mysql和mysql++所在目录(<---修改:这里不需要写了,因为ld.so.conf已经加上/usr/local/lib,/usr/lib和/usr/local/lib都能默认找到)
-llib(小写/eL/):编译时链接的库lib,这里是mysqlpp,即libmysqlpp.o;(<---修改:编译器在查找的时候有隐式规则,即在指定的名字前加lib,后加.so来查找对应的库文件)
-Idir(大写/ai/):编译时包含库头文件路径,这里分别是/usr/include/mysql和/usr/local/include/mysql++;(<---修改:这里还需要是因为.h文件分别放在include目录下的mysql文件夹和mysql++文件夹下,如果.h直接在include目录中就不必写了)
写成makefile就是如下:
main : hello.cpp
@g++ -o main hello.cpp -lmysqlpp -I/usr/include/mysql -I/usr/local/include/mysql++
clean:
@rm main
执行结果如下:
数据库链接成功并成功查询了Student表里的数据。
selinux 开启的原因.
查看SELinux状态:
/usr/sbin/sestatus -v ##如果SELinux status参数为enabled即为开启状态
修改配置文件需要重启机器:
修改/etc/selinux/config 文件
将SELINUX=enforcing改为SELINUX=disabled
链接:https://www.jianshu.com/p/efdafe4322b9
mysql++ 自带的一些精巧演示例子
//mysql++ API 的几个典型例子:
//使用 in 删除 记录:
ostringstream strbuf;
unsigned int i = 0;
con.real_connect(MY_DATABASE, MY_HOST, MY_USER, MY_PASSWORD, 3306, (int) 0, 60, NULL);
Query query = con.query();
query << MY_QUERY; // 使用这样的方法进行查询,真是很简练呀!tcf
ResUse res = query.use();
Row row;
// 开始拼 sql
strbuf << "delete from " << MY_TABLE << " where " << MY_FIELD << " in (";
for (; row = res.fetch_row(); i++)
strbuf << row[0] << ",";
if (!i)
return 0;
string output(strbuf.str());
output.erase(output.size() - 1, 1); // 去掉最后一个,
output += ")";
query.exec((const string &) output);
//打印结果
cout << output << endl;
return 0;
//------------------------------------------------------------------------------------------------------ -
query.reset();
query << "select * from cpptest";
// 打印 query 语句
cout << "Query: " << query.preview() << endl;
// 执行query 并保存到 Result
mysqlpp::Result res = query.store();
cout << "记录条数: " << res.size() << endl << endl;
// 打印表中的数据
cout.setf(ios::left);
cout << setw(20) << "Item" <<
setw(9) << "Num" <<
setw(9) << "Weight" <<
setw(9) << "Price" << "Date" << endl << endl;
// Result 类提供的 iterator是只读随机 显示读取记录的
mysqlpp::Row row;
mysqlpp::Result::iterator i;
for (i = res.begin(); i != res.end(); ++i)
{
row = *i;
// 可以使用 列的位置或者 名称来 显示
cout << setw(20) << row[0].c_str() <<
setw(9) << row[1].c_str() <<
setw(9) << row.lookup_by_name("weight").c_str() <<
setw(9) << row[3].c_str() <<
row[4] << endl;
}
//---------------------------------------------------------------------------------------------------- -
//一个简单的查询
Query query = con.query();
stock row;
row.set("Hot Dogs", 100, 1.5, 1.75, "1998-09-25");
query.insert(row);
cout << "Query : " << query.preview() << endl;
query.execute();
print_stock_table(query);
//--------------------------------------------------------------------------------------------------------
2020-05-07 16:40:01
一、依赖:MySQL Connector/C++需要安装配置boost库
MySQL Connector/C++需要安装配置boost库,boost库安装编译:【boost】Windows下VS2017下boost库安装配置_bandaoyu的博客-CSDN博客
二、简介
应用程序要想访问数据库,必须使用数据库提供的编程接口。目前业界广泛被使用的API标准有ODBC和JDBC。
ODBC是由微软提出的访问关系型数据库的C程序接口。
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。
MySQL实现了三种Connector用于C/C++ 客户端程序来访问MySQL服务器:Connector/ODBC, Connector/C++(JDBC)以及Connector/C(libmysqlclient)。
MySQL C++ Driver的实现基于JDBC规范
MySQL Connector/C++是由Sun Microsystems开发的MySQL连接器。它提供了基于OO的编程接口与数据库驱动来操作MySQL服务器。
与许多其他现存的C++接口实现不同,Connector/C++遵循了JDBC规范。也就是说,Connector/C++ Driver的API主要是基于Java语言的JDBC接口。JDBC是java语言与各种数据库连接的标准工业接口。
Connector/C++实现了大部分JDBC规范。如果C++程序的开发者很熟悉JDBC编程,将很快的入门。
参考:静态库和动态库使用方法【C++】VS2015/VS2017连接Mysql数据库教程 - 水郁 - 博客园
动态库与静态库优缺点比较
接着根据我们的需要,执行后续步骤:
如果用静态库,可能比较麻烦,因为静态库需要和编译器版本相匹配,因此需要手动编译一份,所以此次选择动态库。
1、新建一个空项目
2、将D:\Program Files\MySQL\Connector C++ 1.1.3\include添加到项目的包含目录中(根据具体路径而定)
3、将D:\boost\boost_1_55_0添加到项目的包含目录中(根据具体路径而定)
4、将D:\Program Files\MySQL\Connector C++ 1.1.3\lib\opt添加到项目的库目录中(根据具体路径而定)
5、添加mysqlcppconn.lib至附加依赖项中
6、如果使用的mysql是64位的,还需要将项目的解决方案平台由win32改成x64
7、将D:\Program Files\MySQL\Connector C++ 1.1.3\lib\opt(根据具体路径而定)下的mysqlcppconn.dll复制到项目中去,和.cpp,.h文件位于同一路径下
将D:\Program Files\MySQL\MySQL Server 5.6\lib(根据具体路径而定)下的libmysql.dll复制到项目中去,和.cpp,.h文件位于同一路径下
至此,相关配置全部完成
6、程序引入头文件
#include "jdbc/mysql_connection.h"
#include "jdbc/mysql_driver.h"
#include "jdbc/cppconn/statement.h"
7、连接数据库
//初始化驱动
sql::mysql::MySQL_Driver *driver = NULL;
sql::Connection *con = NULL;
driver = sql::mysql::get_mysql_driver_instance();
if (driver == NULL)
{
cout << "driver is null" << endl;
}
con = driver->connect("tcp://localhost:3306", "root", "root");
if (con == NULL)
{
cout << "conn is null" << endl;
}
cout << "connect suceess" << endl;
8、程序使用mysql版本为mysql-5.6.24-win32,完整的代码如下:
#include "iostream"
#include "jdbc/mysql_connection.h"
#include "jdbc/mysql_driver.h"
#include "jdbc/cppconn/statement.h"
#include "jdbc/cppconn/prepared_statement.h"
using namespace std;
using namespace sql;
int main()
{
//初始化驱动
sql::mysql::MySQL_Driver *driver = NULL;
sql::Connection *conn = NULL;
driver = sql::mysql::get_mysql_driver_instance();
if (driver == NULL)
{
cout << "driver is null" << endl;
}
//连接
//con = driver->connect("tcp://localhost:3306", "root", "root");
conn = driver->connect("tcp://localhost:3306/ourcms", "root", "root");
if (conn == NULL)
{
cout << "conn is null" << endl;
}
cout << "connect suceess" << endl;
//查询
int flag = 0;
sql::Statement *stmt = conn->createStatement();
sql::ResultSet *res;
res = stmt->executeQuery("SELECT * FROM cms_device");
while (res->next())
{
cout << res->getInt("id") << endl;
cout << res->getString("phone").c_str() << endl;
cout << res->getString("imsi").c_str() << endl;
}
//插入
conn->setAutoCommit(0);//关闭自动提交
PreparedStatement *prep_stmt;
int updatecount = 0;
res->first();
flag = 0;
while (res->next())
{
if (strcmp(res->getString("imsi").c_str(), "460010010000100") == 0)
{
flag = 1;
break;
}
}
if (flag == 0) {
prep_stmt = conn->prepareStatement("INSERT INTO cms_device (id,phone,imsi) VALUES (111,?,?)");
prep_stmt->setString(1, "15043214321");
prep_stmt->setString(2, "460010010000100");
updatecount = prep_stmt->executeUpdate();
}
Savepoint *savept;
savept = conn->setSavepoint("SAVEPT1");
res->first();
flag = 0;
while (res->next())
{
if (strcmp(res->getString("imsi").c_str(), "460010010000101") == 0)
{
flag = 1;
break;
}
}
if (flag == 0) {
prep_stmt = conn->prepareStatement("INSERT INTO cms_device (phone,imsi) VALUES (?,?)");
prep_stmt->setString(1, "15043214321");
prep_stmt->setString(2, "460010010000101");
updatecount = prep_stmt->executeUpdate();
}
conn->rollback(savept);
conn->releaseSavepoint(savept);
conn->commit();
//更新
conn->setAutoCommit(1);//打开自动提交
prep_stmt = conn->prepareStatement("update cms_device set phone=? where phone=?");
prep_stmt->setString(1, "15011111111");
prep_stmt->setString(2, "15043214321");
updatecount = prep_stmt->executeUpdate();
}
版权声明:本文为CSDN博主「csdndenglu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/csdndenglu/article/details/90906120
程序代码
main.cpp
#include
#include
运行结果
安装好了boost库和Mysql connector c++ 1.1.3库后,我们配置好工程的属性,就能使用通过sql::Connection::createStatement(),方法创建的sql::Statement*对象,对数据库进行操作,但是如果你数据库中的编码是utf8或者其他支持中文的编码,那么你必需要在执行sql查询语句之前,执行这么一句代码:m_sqlStatement->execute("set names 'gbk'");这里的m_sqlStatement是一个sql::Statement*对象。这样你在执行查询语句,例如:m_sqlStatement->executeQuery("select * from userinfo_tbl"),就不会出现中文乱码了。
原因和上面差不多,是程序中对数据库进行操作的对象中使用的字符编码和数据库中的字符编码不一致所导致的,可以想象一下,我们编程时是通过Mysql connector c++ 1.1.3库中提供的对象对数据库进行操作,对数据库的一切操作都是由这些我们实例化出来的对象来完成,但是如果我们创建的对象的字符编码和数据库的编码不一样,那么数据库就无法识别对象想要存到数据库中的字符到底是啥,由于无法识别,数据库自然不会让你插入进去。解决方法和上面一样,在执行插入语句之前,创建一个sql::Statement*对象,执行m_sqlStatement->execute("set names 'gbk'"),这里的m_sqlStatement是一个sql::Statement*对象。无论是使用sql::PreparedStatement*还是使用sql::Statement*对数据库进行操作,基本都要执行这么一句,设置对象使用的编码。可能你们会奇怪为什么不是把编码设置成utf8而是设置成gbk,这个我也不知道,但是我试过了,数据库编码为utf8时,我执行了m_sqlStatement->execute("set names 'utf8'")代替上面的,但是还是会有乱码,只有设置成gbk时才不会乱码,至于为什么我也不太清楚,总之,先用起来再说。
无论是C++库函数还是Mysql connector c++ 1.1.3库中都没有提供DateTime这个数据类型,那么想要将Mysql中的DateTime类型读进C++的类型中,就必须要转换类型,最方便的方法是将DateTime装换成“2018-07-15 22:11:54”这样格式的字符串,存的时候按照字符串的格式存储,取得时候也按照字符串的格式取,具体代码如下:
从查询结果集中取出DateTime的数据:
rlt = statement->executeQuery("select * from userinfo_tbl");//statement是sql::Statement*类型对象
while (rlt->next())
{
std::cout << " user_name:" << rlt->getString("user_name");
std::cout << " user_pwd:" << rlt->getString("user_pwd");
std::cout << " user_email:" << rlt->getString("user_email");
std::cout << " user_update:" << rlt->getString("user_update") << std::endl; //user_update字段是DateTime类型的字段,
}
输出格式如下:
c++获取系统时间存进Mysql中 DateTime类型字段
做法如下:
try
{
CTime nowtime = CTime::GetCurrentTime();//获取系统当前时间#include
CString tstr = nowtime.Format("%Y-%m-%d %H:%M:%S");//格式化时间,将时间格式化成和数据库中格式一样的字符串
std::cout << tstr << std::endl;
sql::PreparedStatement* preStatement = jdbc.getPreStatement("INSERT INTO userinfo_tbl VALUES('拉拉','147258','[email protected]',?)");
preStatement->setString(1, tstr.GetString());
preStatement->executeUpdate();
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
这样就能获取系统系统间并将时间存进数据库了。
以上说法纯粹个人摸索理解出来的,有理解不正常或者其他纰漏之处还请大家海涵,用这个套工具开发服务器的人应该不多,遇到问题也是让人蛋疼,分享一下个人经验,还望能帮到有需要之人。
————————————————
版权声明:本文为CSDN博主「HumRun」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qqyn001/article/details/81057919
查询数据
#include
#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"
int main() {
const char* user = "root";
const char* passwd = "";
const char* host = "tcp://localhost:3306";
const char* database = "test";
try {
sql::mysql::MySQL_Driver* driver =
sql::mysql::get_mysql_driver_instance();
sql::Connection* conn = driver->connect(host, user, passwd);
conn->setSchema(database);
std::cout << "status: " << conn->isClosed() << std::endl;
sql::Statement *stmt = conn->createStatement();
sql::ResultSet *res = stmt->executeQuery("select 1;");
while (res->next()) {
std::cout << res->getInt(1) << std::endl;
}
res = stmt->executeQuery("select * from pet;");
while (res->next()) {
std::cout << res->getString(1) << ",";
std::cout << res->getString(2) << ",";
std::cout << res->getString(3) << ",";
std::cout << res->getInt(4) << ",";
std::cout << res->getString(5) << ",";
std::cout << res->getString(6) << std::endl;
}
delete res;
delete stmt;
delete conn;
} catch (sql::SQLException& e) {
std::cout << "# ERR: SQLException in " << __FILE__;
std::cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << std::endl;
std::cout << "# ERR: " << e.what();
std::cout << " (MySQL error code: " << e.getErrorCode();
std::cout << ", SQLState: " << e.getSQLState() << " )" << std::endl;
}
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
using namespace sql;
using namespace std;
class BookInfor {
public:
string name;
string writer;
string img;
string price;
};
class Mysql {
public:
mysql::MySQL_Driver *driver;
Connection *con;
Statement *state;
ResultSet *result;
PreparedStatement *prep_stmt;
Mysql()//构造函数
{
driver = sql::mysql::get_mysql_driver_instance();
// 建立链接
con = driver->connect("tcp://127.0.0.1:3307", "root", "root");
state = con->createStatement();
state->execute("use book_infor");
}
void query()//查询
{
// 查询
result = state->executeQuery("select * from book");
// 输出查询
while (result->next())
{
int id = result->getInt("id");
//string img = result->getString("bookname");
cout << id << endl;
}
}
int insert(BookInfor book)//插入
{
bool retstatus = state->execute("INSERT INTO book (bookname,imgpath) VALUES ('Napier', 'New Zealand')");
if (!retstatus)
{
return state->getUpdateCount();
}
else
{
return 0;
}
}
int prepare_insert(BookInfor book)
{
prep_stmt = con->prepareStatement("INSERT INTO book (name,img,price,writer) VALUES (?,?,?,?)");
prep_stmt->setString(1, book.name);
prep_stmt->setString(2, book.img);
prep_stmt->setString(3, book.price);
prep_stmt->setString(4, book.writer);
bool updatecount = prep_stmt->executeUpdate();
if (!updatecount)
{
return state->getUpdateCount();
}
else
{
return 0;
}
}
~Mysql()//析构函数
{
delete state;
delete con;
}
};
/*
int main()
{
BookInfor book;
book.img = "dd";
book.writer = "dd";
book.name = "dd";
book.price = "dd";
Mysql m;
m.prepare_insert(book);
}
*/
————————————————
版权声明:本文为CSDN博主「bobobe」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/bobobe/article/details/51449760