应用举例¶
本章主要介绍在Qt应用程序中QACI具体怎么使用。
显示加载aci¶
在Windows_64和Linux_64环境下使用的函数是一样的,只是指定的路径名和动态库名不一样。在这里使用了QLibrary类,所以需要包含QLibrary头文件。
1、在windows_64环境下:¶
QLibrary * aci_dll = NULL;
QLibrary * aci_dll = NULL;
aci_dll = new QLibrary("C:\\QT\\aci\\lib\\aci.dll"); //aci的路径
aci_dll->load();
if(aci_dll->isLoaded())
{
qDebug()<<"load aci.dll success.";
}
aci_dll = new QLibrary("C:\\QT\\aci\\lib\\aci.dll"); //aci的路径
aci_dll->load();
if(!aci_dll->isLoaded())
{
qDebug()<<"load aci.dll failed.";
qDebug() << aci_dll->errorString();
return 0;
}
else
{
qDebug()<<"load aci.dll success.";
}
2、在Linux_64环境下:¶
QLibrary * aci_so = NULL;
aci_so = new QLibrary("//xww//aci//lib//libaci.so"); //aci的路径
aci_so->load();
if(!aci_so->isLoaded())
{
qDebug()<<"load libaci.so failed.";
qDebug() << aci_so->errorString();
return 0;
}
else
{
qDebug()<<"load libaci.so success.";
}
创建数据库连接¶
这里使用了QSqlDatabase类,所以需要包含QSqlDatabase头文件,值得注意的是,QT中创建的数据库连接全部是全局连接,在其他主线程和子线程中都可以访问,因此需要注意并发控制(加锁或者在线程中创建自己的数据库连接,QSqlDatabase::addDatabase函数第二个参数为给连接指定一个名称)。
QSqlDatabase db_st = QSqlDatabase::addDatabase("QACI");//加载QACI驱动
db_st.setPort(2003); //端口号
db_st.setHostName("localhost"); //主机地址
db_st.setDatabaseName("OSRDB"); //库名
db_st.setUserName("SYSDBA"); //用户名
db_st.setPassword("szoscar55"); //密码
//打开数据库连接
if(db_st.open()){
qDebug()<<"链接本地数据库OSRDB成功";
}else{
qDebug()<<"链接本地数据库OSRDB失败";
QSqlError error = db_st.lastError();
qDebug()<< error.databaseText();
qDebug()<< error.driverText();
return 0;
}
连接相关信息查看¶
qDebug() << "database's name is" << db_st.databaseName(); //数据库名
qDebug() << "database's hostname is" << db_st.hostName(); //主机名
qDebug() << "database's port is" << db_st.port(); //端口号
qDebug() << "database's username is" << db_st.userName(); //用户名
qDebug() << "database's password is" << db_st.password(); //密码
qDebug() << "database's name is" << db_st.driverName(); //数据库驱动名
qDebug() << "connect option is" << db_st.connectOptions(); //连接选项
查看当前可用数据库驱动¶
获取可用驱动,这里可以看到除了QACI还有QACI1.0,这个QACI1.0是为了记录QACI的版本,1.0就是其版本号。
QStringList drivers = db_st.drivers();
qDebug() << "the useful drivers are as follows:";
foreach(QString driver, drivers) {
qDebug() << driver;
}
获取数据中所有表、视图、系统表¶
QSql::Tables:当前连接用户拥有的表 QSql:: SystemTables:集群系统表 QSql:: Views:当前连接用户拥有的视图
//获取数据中所有表
QStringList current_tables = db_st.tables(QSql::Tables); //SystemTables,Tables,Views3种
qDebug() << "the useful tables are as follows:";
foreach (QString table, current_tables) {
qDebug() << table;
}
获取表的域信息¶
这里使用了QSqlRecord类,所以需要包含QSqlRecord头文件。
//获取表的域信息
QSqlRecord record_t2 = db_st.record("xww_test2");
qDebug() << "the fields of table are as follows:";
for (int i = 0; i < record_t2.count(); i++)
{
qDebug() << record_t2.fieldName(i);
}
获取表的主键信息¶
这里使用了QSqlIndex类,所以需要包含QSqlIndex头文件。
//获取表的主键信息
QSqlIndex primarykey_t2 = db_st.primaryIndex("xww_test2");
int pk_count = primarykey_t2.count(); //
qDebug() << "name:" << primarykey_t2.name(); //
for(int i=0;i < pk_count;i++)
{
qDebug() << "fieldname:" << primarykey_t2.fieldName(i);//
//qDebug() << "field:" << primarykey_t2.field(i);
qDebug() << "value:" << primarykey_t2.value(i); //
}
获取数值精度类型¶
这里使用了QSqlIndex类,所以需要包含QSqlIndex头文件。
//数值精度
qDebug() << "the numerical pracision is:" << db_st.numericalPracisionPolicy();
插入数据¶
直接通过sql语句插入¶
这里使用了QSqlQuery类,所以需要包含QSqlQuery头文件。
QSqlQuery query;
//insert..............................................................................
query.exec("insert into xww_test1 values(1,'i love china')");
query.exec(QString::fromLocal8Bit("insert into xww_test1 values(2,'神舟通用')"));
query.exec(QString::fromLocal8Bit("insert into xww_test1 values(3,'我爱中国')"));
按名字绑定插入¶
这里使用了QSqlDriver类,所以需要包含QSqlDriver头文件。
//NamedPlaceholders
if(db_st.driver()->hasFeature(QSqlDriver::NamedPlaceholders))
{
query.prepare(QString::fromLocal8Bit("insert into xww_test1(c1,c2) values(:c1,:c2)"));
query.bindValue(":c1",4);
query.bindValue(":c2",QString::fromLocal8Bit("按名字绑定"));
query.exec();
}
按位置绑定插入¶
//PositionalPlaceholders
if(db_st.driver()->hasFeature(QSqlDriver::PositionalPlaceholders))
{
query.prepare(QString::fromLocal8Bit("insert into xww_test1(c1,c2) values(?,?)"));
query.bindValue(0,5);
query.bindValue(1,QString::fromLocal8Bit("按位置绑定"));
query.exec();
}
按数组绑定方式插入¶
//通过邦定数组方式insert........
query.prepare("insert into xww_test2(a1,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12) "
"values(:a1,:c1,:c2,:c3,:c4,:c5,:c6,:c7,:c8,:c9,:c10,:c11,:c12)");
QVariantList a1;
a1 << -128 << 2 << 3 << 4;
query.addBindValue(a1);
QVariantList c1;
c1 << 2147483647 << 22 << 33 << 44;
query.addBindValue(c1);
QVariantList c2;
c2 << -32768 << 3 << 4<< 5;
query.addBindValue(c2);
QVariantList c3;
qint64 maxint64 = Q_INT64_C(9223372036854775807);
c3 << maxint64 << 4 << 5<< 6;
query.addBindValue(c3);
QVariantList c4;
c4 << 4.44 << 23424.2323 << 323.2323 << 243243.323;
query.addBindValue(c4);
QVariantList c5;
c5 << 55.55 << 23424.2323 << 323.2323 << 243243.323;
query.addBindValue(c5);
QVariantList c6;
c6 << 6.66 << 23424.2323 << 323.2323 << 243243.323;
query.addBindValue(c6);
QVariantList c7;
c7 << "7:31:13" << "6:31:13" << "12:31:13" << "12:31:13";
query.addBindValue(c7);
QVariantList c8;
c8 << "1998-11-12" << "2000-11-12" << "1999-11-12" << "1999-11-12";
query.addBindValue(c8);
QVariantList c9;
c9 << "1999-11-12 12:31:13" << "2016-11-12 12:31:13" << "2015-11-12 12:31:13" << "2014-11-12 12:31:13";
query.addBindValue(c9);
QVariantList c10;
c10 << "char20" << "Boris" << QString::fromLocal8Bit("清风徐来") << "John";
query.addBindValue(c10);
QVariantList c11;
c11 << "varchar100" << "Boris" << QString::fromLocal8Bit("窗前明月光") << "Kobe";
query.addBindValue(c11);
QVariantList c12;
c12 << "text" << "Boris" << QString::fromLocal8Bit("问君能有几多愁") << "Jordan";
query.addBindValue(c12);
//如果没有执行成功
if(query.execBatch() == false)
{
qDebug() << query.lastError();
}
删除数据¶
//清空xww_test1表.......................................................
query.exec("delete from xww_test1");
数据查询¶
获取所有结果¶
//select...........................................................................
query.exec("select * from xww_test1 order by c1");
QSqlRecord rec = query.record(); //获取select的结果信息
int columncount = rec.count(); //获取列数
qDebug() << "columncount of table xww_test1 is:" << columncount;
//获取所有的列
while(query.next()){
if(columncount != 0)
{
QString columnvalue;
int i;
for(i=0;i < (columncount-1);i++)
{
columnvalue += (query.value(i).toString() + ",");
}
columnvalue += query.value(i).toString(); //最后一列没有不加逗号
qDebug() << columnvalue;
}
}
获取特定的结果¶
//返回全部的属性和结果集........................................................................
query.exec("select * from xww_test1");
//指向第一条记录
if(query.next()){
int RowNum = query.at(); //获取query所指向的记录在结果集中的编号
int ColumnNum = query.record().count(); //获取每条记录的列数,必须添加<QSqlRecord>头文件
int FieldNum = query.record().indexOf("c2"); //根据列名查询列的编号
QString column = query.value(0).toString()+","+query.value(FieldNum).toString();
qDebug() << "row number is:" << RowNum << ",column count is " << ColumnNum << ",column value is:" << column;
}
//指向第二条记录
if(query.seek(1))
{
qDebug() << "row number is:" << query.at() << ",c1 is:" << query.value(0).toInt() << ",c2 is:" << query.value(1).toString();
}
//指向最后一条记录
if(query.last())
{
qDebug() << "row number is:" << query.at() << ",c1 is:" << query.value(0).toInt() << ",c2 is:" << query.value(1).toString();
}
满足一定条件的结果集¶
//满足一定条件的结果集................................................................................
query.prepare("select c2 from xww_test1 where c1= :c1 ");
int test1_c1 = 1;
query.addBindValue(test1_c1);
query.exec();
if(query.next())
{
qDebug() << "when c1 = 1,c2 = " <<query.value(0).toString();
}
事务操作¶
这里需要注意一下:QSqlDatabase::database().commit()操作,不管提交正确还是错误,返回值都是true。并且提交错误的时候会自动回滚。
//事务操作........................................................................................
if(QSqlDatabase::database().transaction())//启动事务操作
{
QSqlQuery query1; //必须在开始事务之后,不然执行sql语句时事务标志为false
query1.exec("insert into xww_test1 values(6,'第六行')");
query1.exec("insert into xww_test1 values(7,'第七行')");
query1.exec(QString::fromLocal8Bit("insert into xww_test1 values(5000000000000,'test1中国')"));//第一列int越界
query1.exec("delete from xww_test1 where c1=6");
if(!QSqlDatabase::database().commit())//提交。不管提交正确还是错误,返回值都是true。提交错误的时候会自动回滚。
{
qDebug() << QSqlDatabase::database().lastError();
if(!QSqlDatabase::database().rollback())//回滚。代码不会走到这里。
{
qDebug() << QSqlDatabase::database().lastError();
}
}
}
Returning语法使用¶
神通支持Returning语法,用于返回插入/更新相关列的值,常用于返回主键ID列,使用方法如下:
//create table test( a int ,b varchar(30);
//returning int
QSqlQuery query;
query.prepare("insert into test values(?,?) returning a into ? ");
query.bindValue(0,999);
query.bindValue(1,"移植3");
query.bindValue(2,0,QSql::Out);
query.exec();
qDebug()<<query.boundValue(2).toInt();
//returning varchar
query.prepare("insert into test values(?,?) returning b into ? ");
query.bindValue(0,999);
query.bindValue(1,"移植3");
query.bindValue(2,"",QSql::Out);
query.exec();
qDebug()<<query.boundValue(2).toString();
存储过程调用¶
神通QACI支持存储过程、匿名块的调用,并支持返回存储过程的out参数操作:
匿名块¶
匿名块是一个以begin开头end; 结束的一个SQL块,SQL块里面包含多条sql语句,不能包含返回结果集的查询,select into 是可以的,匿名块执行如下:
query.exec(begin insert into test values(1, 'aaa'); insert into test values(2, 'bbb'); end;") ;
无out参数存储过程¶
In参数的绑定和insert参数绑定操作完全类似,如下:
/* create or replace procedure p1( a int ,b varchar2(100)) as
tmp int;
begin
tmp = a;
dbms_output.put_line(b||a);
end;
*/
QSqlQuery query;
query.prepare("CALL p1(?, ?)");
query.bindValue(0, 11);
query.bindValue(1, "aaa");
query.exec();
有out参数存储过程¶
- 返回一个参数
/* create or replace procedure p2( a int ,b out int) as
tmp int;
begin
b = a;
end;
/
*/
QSqlQuery query;
query.prepare("CALL p2(?, ?)");
query.bindValue(0, 22);
query.bindValue(1, 0, QSql::Out);
query.exec();
int i = query.boundValue(1).toInt();
qDebug()<<i;
- 返回两个参数
/* create or replace procedure p3( a int ,b out int,c out varchar(30)) as
tmp int;
begin
b = a;
c='yyyyy'||a;
end;
/
*/
QSqlQuery query;
QString yy="";
query.prepare("CALL p3(:c1, :c2, :c3)");
query.bindValue(0, 33);
query.bindValue(1, 0, QSql::Out);
query.bindValue(2, yy, QSql::Out);
query.exec();
int ii = query.boundValue(1).toInt();
QString tmp = query.boundValue(2).toString();
qDebug()<<ii<<","<<tmp;
中文数据字典¶
QACI支持表名、字段名、约束名为中文的情况下的数据操作:
/*
create table 中文表(a int 中,文列1 varchar(100));
alter table 中文表 add CONSTRAINT 中文表pk PRIMARY KEY (中文列1) ;
insert into 中文表 values(1,'中文1');
insert into 中文表 values(2,'中文2');
*/
QSqlQuery query;
query.exec("select * from 中文表");
while(query.next()){
qDebug()<<query.value(0).toInt()<<","<<query.value(1).toString();
qDebug()<<query.value("a").toInt()<<","<<query.value("中文列1").toString();
}
qDebug()<<query.executedQuery();
//主键名称为中文时,获取主键也是支持的:
QSqlIndex primarykey_t2 = db.primaryIndex("中文表");
int pk_count1 = primarykey_t2.count();
qDebug() << "name:" << primarykey_t2.name();
for(int i=0;i < pk_count1;i++)
{
qDebug() << "fieldname:" << primarykey_t2.fieldName(i);
}
空值和空串处理¶
演示如何向数据库插入一个空值,空串,并进行查询:
空值插入¶
- 方式一:不绑定的参数即可插入一个NULL值
QSqlQuery query;
query.exec("truncate table test");
query.prepare("insert into test values(?,?) ");
query.bindValue(0,999);
//second不做绑定即为插入一个NULL
query.exec();
- 方式二:绑定一个类型即可
//int列插入一个空值
query.prepare("insert into test values(?,?) ");
query.bindValue(0,QVariant(QVariant::Int));
query.bindValue(1,"ccc");
query.exec();
// 字符串列插入一个空值
query.prepare("insert into test values(?,?) ");
query.bindValue(0,888);
query.bindValue(1,QVariant(QVariant::String));
query.exec();
批量绑定插入空值¶
//batch insert NULL
query.prepare("insert into test values(?,?) ");
QVariantList bc1;
bc1<<111<<112<<113;
QVariantList bc2;
bc2<<"a"<<QVariant(QVariant::String)<<"c";
query.addBindValue(bc1);
query.addBindValue(bc2);
query.execBatch();
空串插入¶
query.prepare("insert into test values(?,?) ");
query.bindValue(0,666);
query.bindValue(1,"");
query.exec();
批量绑定插入空串¶
//batch insert ""
query.prepare("insert into test values(?,?) ");
QVariantList bc11;
bc11<<111<<112<<113;
QVariantList bc22;
bc22<<"a"<<""<<"c";
query.addBindValue(bc11);
query.addBindValue(bc22);
query.execBatch();
如何判断空值¶
query.prepare("select * from test ");
query.exec();
while(query.next())
{
qDebug()<<query.value(1).isNull();
}
各种数据类型操作示例¶
数值类型操作¶
对于tinyint、smallint、bigint、double precision、float类型操作:
- 数值插入
//create table tbnum( a tinyint,b smallint ,c bigint,d double precision,e float);
QSqlQuery query;
query.prepare("insert into tbnum values(?,?,?,?,?)");
long long bigintdata = 922337203685477580;
double doubledata=1234567.1234567;
query.bindValue(0,65);
query.bindValue(1,2);
query.bindValue(2,bigintdata);
query.bindValue(3,doubledata);
query.bindValue(4,4.111);
query.exec();
- 数值查询
QSqlQuery query;
query.prepare("select * from tbnum");
query.exec();
db.setNumericalPrecisionPolicy(QSql::HighPrecision);
qDebug()<<"uuuuuuu:"<<db.numericalPrecisionPolicy();
while(query.next())
{
qDebug()<<query.value(0).toInt();
qDebug()<<query.value(1).toInt();
qDebug()<<query.value(2).toLongLong();
qDebug()<<query.value(3).toDouble();
qDebug()<<query.value(4).toFloat();
}
字符串类型操作¶
字符串操作比较简单,如下:
//create table test( a int,b varchar(100));
QSqlQuery query;
query.prepare("insert into test values(?,?)");
query.bindValue(0,11);
query.bindValue(1, "aaa");
query.exec();
QString strdata = "bbb";
query.prepare("insert into test values(?,?)");
query.bindValue(0,12);
query.bindValue(1, "aaa");
query.exec();
二进制类型操作¶
Binary和varbinary二进制类型,操作如下:
- 二进制类型插入
通过QVariant::ByteArray类型插入数据:
//create table tbbinary( a int,b binary(30),c varbinary(100));
QSqlQuery query;
QString qdata = "ssss";
QVariant c1 = QVariant(QVariant::ByteArray);
c1 = qdata.toLocal8Bit();
query.prepare("insert into tbbinary values(?,?,?)");
query.bindValue(0,11);
query.bindValue(1,c1);
query.bindValue(2,c1);
query.exec();
通过十六进制字符串插入数据:
query.prepare("insert into tbbinary values(?,?,?)");
query.bindValue(0,12);
query.bindValue(1,"1010");//16进制字符串,比如EFEF
query.bindValue(2,"1010");
query.exec();
- 二进制类型查询
QSqlQuery query;
query.prepare("select * from tbbinary");
query.exec();
while(query.next())
{
qDebug()<<query.value(0).toInt();
qDebug()<<query.value(1).toString(); //将二进制转换成字符串
qDebug()<<query.value(2).toString();//将二进制转换成字符串
}
日期类型操作¶
演示向数据库中的date、time、timestamp类型插入数据和读取数据的方式:
- 日期类型插入
插入日期类型有两种方式,一种为直接插入字符串,另外一种为插入对于的QT类型,比如:
//create table tbtime( a int,b date,c time,d timestamp(6));
QSqlQuery query;
query.exec("drop table tbtime");
query.exec("create table tbtime( a int,b date,c time,d timestamp(6))");
//1) 字符串方式插入时间
query.prepare("insert into tbtime values(?,?,?,?)");
query.bindValue(0,11);
query.bindValue(1,"2020-2-6");
query.bindValue(2,"18:10:10.1");
query.bindValue(3,"2020-2-6 18:10:10.11");
query.exec();
//2) 通过QT 的时间类class插入, 支持毫秒数为3位,最大值为999
query.prepare("insert into tbtime values(?,?,?,?)");
QDate c11 = QDate::currentDate();
QTime c21 = QTime::currentTime();
QDateTime c31 = QDateTime::currentDateTime();
query.bindValue(0,11);
query.bindValue(1,c11);
query.bindValue(2,c21);
query.bindValue(3,c31);
query.exec();
- 日期类型查询
query.prepare("select * from tbtime");
query.exec();
while(query.next())
{
qDebug()<<query.value(0).toInt();
qDebug()<<query.value(1).toDate().toString("yyyy-MM-dd");
qDebug()<<query.value(2).toTime().toString("hh:mm:ss.zzz");
qDebug()<<query.value(3).toDateTime().toString("yyyy-MM-dd hh:mm:ss");
}
bool类型操作¶
Binary和varbinary二进制类型,操作如下:
- bool类型插入
插入bool类型有两种方式,一种为插入0/1数值,另外一种为插入bool值;
//create table tbbool( a int,b bool);
QSqlQuery query;
query.exec("truncate table tbbool");
query.prepare("insert into tbbool values(?,?)");
query.bindValue(0,11);
query.bindValue(1,1); //真
query.exec();
query.bindValue(0,13);
query.bindValue(1,true); // 真
query.exec();
query.bindValue(0,14);
query.bindValue(1,0); //假
query.exec();
query.bindValue(0,15);
query.bindValue(1,false); //假
query.exec();
- bool类型查询
QSqlQuery query;
query.prepare("select * from tbbool");
query.exec();
while(query.next())
{
qDebug()<<query.value(0).toInt();
qDebug()<<query.value(1).toBool(); //打印true/false
}
BLOB大对象类型操作¶
- blob类型插入
//插入大约1M数据
//create table tbblob( a int,b blob);
QSqlQuery query;
QString qdata = "";
QVariant c1 = QVariant(QVariant::ByteArray);
QByteArray tmpblob = qdata.toLocal8Bit();
for(int i=1;i<=100000;i++)
{
tmpblob.append("1234567890");
}
query.prepare("insert into tbblob values(?,?)");
query.bindValue(0,11);
query.bindValue(1,tmpblob);
query.exec();
- blob类型查询
QSqlQuery query;
query.prepare("select * from tbblob");
query.exec();
while(query.next())
{
qDebug()<<query.value(0).toInt();
qDebug()<<query.value(1).toByteArray().size(); //打印获取到的数值长度
}
CLOB大对象类型操作¶
- clob类型插入
//插入大约1M数据
//create table tbclob( a int,b clob);
QSqlQuery query;
QString qdata = "";
for(int i=1;i<=100000;i++)
{
qdata.append("1234567890");
}
query.prepare("insert into tbclob values(?,?)");
query.bindValue(0,11);
query.bindValue(1,qdata);
query.exec();
- clob类型查询
QSqlQuery query;
query.prepare("select * from tbclob");
query.exec();
while(query.next())
{
qDebug()<<query.value(0).toInt();
qDebug()<<query.value(1).toString().left(10); //打印获取到CLOB数据的前10个字符
}
interval类型操作¶
interval时间类型因为QT中并没有类型与之对应,因此只能用字符串方式进行操作,如下:
- interval类型插入
//create table tbinterval( a int,b INTERVAL day to second(3),c INTERVAL year to month);
QSqlQuery query;
query.exec("drop table tbinterval");
query.exec("create table tbinterval( a int,b INTERVAL day to second(3),c INTERVAL year to month)");
query.prepare("insert into tbinterval values(?,?,?)");
query.bindValue(0,11);
query.bindValue(1,"1 10:11:12.333");
query.bindValue(2,"11-10");
query.exec();
- interval类型查询
query.prepare("select * from tbinterval");
query.exec();
while(query.next())
{
qDebug()<<query.value(0).toInt();
qDebug()<<query.value(1).toString();
qDebug()<<query.value(2).toString();
}