- 代码里实现的功能就是创建(或者是打开)一个数据库,如果表不存在则添加一个表,在往表里面添加两条记录,然后取出。
- #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;
- }
Sqlite3 c/C++操作入门
最新推荐文章于 2024-06-13 13:04:41 发布