• Sqlite3 C/C++ 初级入门


           以前只用过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;
    }


           唉,看完源代码,其实好多地方我也还是不明白,还请知道了的告诉我一下,谢谢了。

          

    友情提示: 写个博客对于我来说不容易,如果此文是我原创,烦请转载加个链接http://www.cnblogs.com/monotone/。谢谢。
  • 相关阅读:
    vim代码对齐
    在liunx中,快速查找到以前使用过的命令行
    linux文件权限与目录设置
    ASP常用代码
    存储过程
    WebService
    SNS
    浪曦博客系统
    SQL事件探查器与索引优化向导
    光盘AJAX
  • 原文地址:https://www.cnblogs.com/monotone/p/2770601.html
Copyright © 2020-2023  润新知