以前只用过sql server 和 access,都是很简单的应用,利用ado连接上数据库,然后查询等。最近因为实际需要,被推荐使用sqlite3,当时第一次听到这个名词。然后百度了下,最后找到了官网http://www.sqlite.org/index.html,sqlite3是干什么的,我就不多说了,本身我自己也说不出个所以然,还不如直接看百度。
看了下官网上的介绍,然后就是Document下提供的简单入门文档,绕了半天弯路,最后才理解,sqlite3就是两个文件,sqlite3.h 和sqlite3.cpp。官网上的源代码文件几乎全下下来看了一下,找到了一个dll,但是没找到lib,所以花了大把时间去找或者自己生成这个lib,最终发现,在不更改这两这文件的前提下,没法生成lib(可能能生成,但是我目前是这么觉得)。
好了,废话不多说了,在找到了两个源文件之后,就能使用sqlite3了。建议在使用前看下http://www.sqlite.org/cintro.html这个文档,剩下的就只要从tp://www.sqlite.org/c3ref/funclist.html中找对应函数的说明吧。(强调一下,标题有说是初级入门,所以我自己也有很多不明白的地方,但是基本能够使用一些常用的数据库操作了)。其实最好的方式还是看官方的文档说明,不明白的地方自己去尝试,这样子才能明白具体是什么含义。这里推荐两个个管理器方便查看数据库管理文件,我最喜欢的是navicat lite,因为它是中文的,而且和sql server的管理器很像。另外也有sqlite database browser,这个不用安装就能用,但是和名字一样,就像一个浏览器,只适合浏览,操作上我不喜欢。
接下来就准备上代码了,从代码就能看出来,我是菜鸟,呵呵。代码里实现的功能就是创建(或者是打开)一个数据库,如果表不存在则添加一个表,在往表里面添加两条记录,然后取出。我目前只需要会这些,就只做了这些测试。
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include "sqlite3.h" // 记得把sqlite3.h 和 sqlite3.cpp加入到工程中来
using namespace std;
int main()
{
sqlite3* lpdDb = NULL; // 连接数据库用的一个对象
sqlite3_stmt* lpdExcute = NULL; // 这个对象怎么称呼。。 我也不知道,好像有叫它为事务的,我看了下statement的意思,有指令的意思,就当作是指令(sql就是指令,哈哈)句柄了吧
do
{
// 建立或者打开数据库
int liRet = sqlite3_open_v2(
"sqltest.db",//NULL, // 这里指名数据库的名称和存放路径, 如果为空,在磁盘中临时建立一个数据库,当关闭后会自动删除
&lpdDb, // sqlite3对象指针,后面就全靠这个指针与数据库挂钩了
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, // 指名打开或者创建这个数据库的一些标记
NULL // 这个参数文档里说的蛮麻烦的,我没看懂。。。。。。 不过暂时也不需要用。。
);
if( SQLITE_OK != liRet )
break;
// 判断表是否存在,不存在则创建它
// sql学的很简单,搜了下百度,看不懂那些判断表是否存在的sql语句,所以就用种方式了。。。唉
char lscIsExit[] = "select * from stocks";
// 这个sqlite函数相当于是sql查询工具中的检查器,能够检测sql语句的正确性
liRet = sqlite3_prepare_v2(
lpdDb, // 数据库连接指针
lscIsExit, // utf-8编码的sql语句
sizeof(lscIsExit), // sql语句的最大长度,字节数
&lpdExcute, // 指令句柄
NULL // 最后一个参数是当sql语句没执行完时,能返回的一个指针指向没执行完的部分,基本不用。sql语句没执行完,。。。还能做什么?
);
if(SQLITE_ERROR == liRet) // sql语句错误或者不存在,创建表
{
// 创建新的数据表
char lscSqlCreate[] = "create table stocks( \
stockname TEXT not null primary key, \
stockcode TEXT not null, \
exchange TEXT not null, \
pyname TEXT not null \
)";
liRet = sqlite3_prepare_v2(lpdDb,lscSqlCreate,sizeof(lscSqlCreate),&lpdExcute,NULL);
if(SQLITE_ERROR == liRet)
break;
// 执行sql语句
liRet = sqlite3_step(lpdExcute);
if(SQLITE_DONE != liRet) // 执行的是没有返回结果集的sql语句时,返回值是SQLITE_DONE
break;
sqlite3_finalize(lpdExcute); // 这个sql语句的利用结束了,就调用这个函数
// 插入新的数据
// 这里sql语句里面使用通配符,在后面只需要绑定对应的值就能直接执行sql语句,而不用多次调用sqlite3_prepare_v2函数了
// 当然也可以不用通配符,在这里特地使用通配符,练习一下,嘿嘿。
char lscInsertValue[] ="insert into stocks(stockname,stockcode,exchange,pyname) values(?,?,?,?)";
if(SQLITE_OK != sqlite3_prepare_v2(lpdDb,lscInsertValue,-1,&lpdExcute,NULL))
break;
// 绑定参数
// 注意当存入汉字的时候,应该使用这个函数,而不是sqlite3_bind_text(使用这个函数会失败,即使指定的空间大小是足够的,不知道为什么)
// 区别就在于第三个参数和第四个参数。
liRet = sqlite3_bind_text16(
lpdExcute,
1, // 参数的索引值,最左边的为1
L"大智慧", // 参数值
-1,//sizeof(L"大智慧"), // 参数的字节数,如果参数为负数,则遇到第一个结束符时终止
SQLITE_STATIC // 这个参数当该函数返回失败结果时,对参数值的释放
);
if(SQLITE_OK != liRet)break;
if(SQLITE_OK != sqlite3_bind_text(lpdExcute,2,"601519",-1,SQLITE_STATIC))break;
if(SQLITE_OK != sqlite3_bind_text(lpdExcute,3,"sh",-1,SQLITE_STATIC))break;
if(SQLITE_OK != sqlite3_bind_text(lpdExcute,4,"dzh",-1,SQLITE_STATIC))break;
// 执行sql语句,插入记录
if(SQLITE_DONE != sqlite3_step(lpdExcute))break;
// 之前以为这个函数能将有绑定上的数据清理掉,然后再直接重新绑定就行了,但是发现还是要调用下面那个函数。并且不要这个函数也可以
//liRet = sqlite3_clear_bindings(lpdExcute);
// 这个函数就是使得lpdExcute恢复到刚调用完sqlite3_prepare_v2的状态
liRet = sqlite3_reset(lpdExcute);
// 继续插入一条记录
if(SQLITE_OK != sqlite3_bind_text16(lpdExcute,1,L"海马汽车",-1,SQLITE_STATIC))break;
if(SQLITE_OK != sqlite3_bind_text(lpdExcute,2,"000572",-1,SQLITE_STATIC))break;
if(SQLITE_OK != sqlite3_bind_text(lpdExcute,3,"sz",-1,SQLITE_STATIC))break;
if(SQLITE_OK != sqlite3_bind_text(lpdExcute,4,"hmqc",-1,SQLITE_STATIC))break;
if(SQLITE_DONE != sqlite3_step(lpdExcute))break;
sqlite3_finalize(lpdExcute);
}
// 查询数据
// 这里顺便试了下sqlite3支持的字符串连接方式是oracle的方式,网上搜的。
char lscSqlSelect[] = "select stockname,exchange||''||stockcode from stocks";
if(SQLITE_OK != sqlite3_prepare_v2(lpdDb,lscSqlSelect,-1,&lpdExcute,NULL))
break;
if(SQLITE_ROW != sqlite3_step(lpdExcute))
break;
int liCountColums = sqlite3_column_count(lpdExcute);
if(2 != liCountColums)
{
cout<<"查询结果集的列数不对"<<endl;
break;
}
// 获取列值
int i = 0;
setlocale(LC_ALL, "chs"); // 使得控制台支持unicode汉字显示
do
{
// 注意第一列是存入unicode,所以用16版本的函数
int liCbStockName = sqlite3_column_bytes16(
lpdExcute,
0
);
if(0 == liCbStockName)break;
wchar_t* lswStockName = (wchar_t*)sqlite3_column_text16(lpdExcute,0);
const unsigned char* lscColumValue= sqlite3_column_text(
lpdExcute,
1 // 列索引
);
cout << "CbStockName:"<<liCbStockName<<endl;
wcout << lswStockName << " ";
cout << lscColumValue << endl;
}while(SQLITE_DONE != sqlite3_step(lpdExcute));
cout<<endl;
liRet = sqlite3_finalize(lpdExcute);
if(SQLITE_OK != liRet)
{
cout<< "sqlite3_finalize之前存在错误,错误代码为:"<<liRet <<endl;
}
// 关闭连接
while(SQLITE_BUSY == sqlite3_close(lpdDb))
{
cout<< "不能关闭数据库连接,数据库正在使用中。。。"<<endl;
cout<< "按人任意键再次尝试关闭数据库连接"<<endl;
_getch();
}
cout<<"数据库成功关闭。"<<endl;
_getch();
return 0;
}while(false);
cout<<"出错了,错误代码:"<<sqlite3_errcode(lpdDb)<<" 错误描述:"<<sqlite3_errmsg(lpdDb)<<endl;
if(NULL != lpdExcute)
{
int liRet = sqlite3_finalize(lpdExcute);
if(SQLITE_OK != liRet)
{
cout<< "sqlite3_finalize之前存在错误,错误代码为:"<<liRet <<endl;
}
}
while(SQLITE_BUSY == sqlite3_close(lpdDb))
{
cout<< "不能关闭数据库连接,数据库正在使用中。。。"<<endl;
cout<< "按人任意键再次尝试关闭数据库连接"<<endl;
_getch();
}
cout<<"数据库成功关闭。"<<endl;
_getch();
return 1;
}
唉,看完源代码,其实好多地方我也还是不明白,还请知道了的告诉我一下,谢谢了。