SQLite3的绑定函数族使用与其注意事项详解

前言

本文给大家展示的代码实际上就是如何利用Sqlite3的参数化机制做数据插入,也可以update操作,就看你怎么玩了,这里只列出代码,然后说一些注意事项。

下面的代码,有一个问题,插入后的东西一定是:

INSERT INTO "work" VALUES('铪','铪铪铪铪铪',NULL,NULL,NULL,NULL,'铪铪铪铪铪',NULL,NULL,110.0,1.0,108.9,NULL,NULL,'铪铪铪铪铪',NULL,NULL,NULL,'铪铪铪铪铪',NULL,NULL,NULL);

看看有问题的代码:

sqlite3_stmt *stmt;
 CString sql = "insert into work values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
 int rc = sqlite3_prepare_v2(db, sql.GetString(), -1, &stmt, NULL);

 if(rc != SQLITE_OK)
 {
 MessageBox("sqlite3_prepare_v2 Failed!");
 return;
 }

 count = 0;
 p_wnd = PrevWnd;

 while(count++ < ID_TOTALCOUNT)
 {
 CString DbStr;

 p_wnd = CWnd::GetNextDlgTabItem(p_wnd, FALSE);
 if(p_wnd == NULL)
 {
  return;
 }

 p_wnd->GetWindowText(DbStr);

 do
 {
  if(!DbStr.GetLength())
  {
  rc = sqlite3_bind_null(stmt, count);
  break;
  }

  //日期相关
  if( count == ID_CHUDANRIQI ||
  count == ID_CHUFARIQI ||
  count == ID_HUANKUANRIQI ||
  count == ID_HUOLIRIQI)
  {
  CDateTimeCtrl *TimeCtl = (CDateTimeCtrl *)p_wnd;
  CString time = DateTimeToString(*TimeCtl);

  rc = sqlite3_bind_text(stmt, count, time.GetString(), time.GetLength(), SQLITE_STATIC);
  break;
  }
  else
  {
  //金钱相关的处理real类型
  if( count == ID_BAOXIANJINE ||
   count == ID_YONGJINBILV ||
   count == ID_JINGBAOFEI ||
   count == ID_HUANKUANJINE ||
   count == ID_LIRUNBILV ||
   count == ID_LIRUNJINE)
  {
   double tMoney = 0.0;
   int rtn = sscanf_s(DbStr.GetString(), "%lf", &tMoney);

   ASSERT(rtn == 1);

   rc = sqlite3_bind_double(stmt, count, tMoney);
  }
  else
  {
   char *str = (char *)DbStr.GetString();
   int c = strlen(str);
   int c1 = DbStr.GetLength();

   rc = sqlite3_bind_text(stmt, count, DbStr.GetString(), -1/*DbStr.GetLength()*/, SQLITE_STATIC);
  }
  }
 }while(0);

 if(rc != SQLITE_OK)
 {
  CString ErrStr = sqlite3_errstr(rc);
  MessageBox(ErrStr);

  return;
 }
 }

 rc = sqlite3_step(stmt); 

 if(rc != SQLITE_DONE)
 {
 if(rc == SQLITE_ERROR)
 {
  CString DbErr;
  DbErr.Format("Sql Insert failed, %s", sqlite3_errmsg(db));

  MessageBox(DbErr);
 }
 else
 {
  MessageBox("sqlite3_step Failed!");
 }
 }

 sqlite3_finalize(stmt);

为什么呢?

因为,sqlite3_bind_text绑定的text,需要在做:

rc = sqlite3_step(stmt); 

的时候统一提交,而上面的代码使用的临时变量,rc = sqlite3_step(stmt);的时候,早就不存在了。因此乱码也是正常的。

修改如下:

sqlite3_stmt *stmt;
 CString sql = "insert into work values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
 int rc = sqlite3_prepare_v2(db, sql.GetString(), -1, &stmt, NULL);

 if(rc != SQLITE_OK)
 {
 MessageBox("sqlite3_prepare_v2 Failed!");
 return;
 }

 count = 0;
 p_wnd = PrevWnd;

 CString DbStr[ID_TOTALCOUNT + 1];

 while(count++ < ID_TOTALCOUNT)
 {
 DbStr[count].Empty();

 p_wnd = CWnd::GetNextDlgTabItem(p_wnd, FALSE);
 if(p_wnd == NULL)
 {
  return;
 }

 p_wnd->GetWindowText(DbStr[count]);

 do
 {
  if(!DbStr[count].GetLength())
  {
  rc = sqlite3_bind_null(stmt, count);
  break;
  }

  //日期相关
  if( count == ID_CHUDANRIQI ||
  count == ID_CHUFARIQI ||
  count == ID_HUANKUANRIQI ||
  count == ID_HUOLIRIQI)
  {
  CDateTimeCtrl *TimeCtl = (CDateTimeCtrl *)p_wnd;
  CString time = DateTimeToString(*TimeCtl);

  DbStr[count] = time;

  rc = sqlite3_bind_text(stmt, count, time.GetString(), time.GetLength(), SQLITE_STATIC);
  }
  else
  {
  //金钱相关的处理real类型
  if( count == ID_BAOXIANJINE ||
   count == ID_YONGJINBILV ||
   count == ID_JINGBAOFEI ||
   count == ID_HUANKUANJINE ||
   count == ID_LIRUNBILV ||
   count == ID_LIRUNJINE)
  {
   double tMoney = 0.0;
   int rtn = sscanf_s(DbStr[count].GetString(), "%lf", &tMoney);

   ASSERT(rtn == 1);

   rc = sqlite3_bind_double(stmt, count, tMoney);
  }
  else
  {
   rc = sqlite3_bind_text(stmt, count, DbStr[count].GetString(), DbStr[count].GetLength(), SQLITE_STATIC);
  }
  }
 }while(0);

 if(rc != SQLITE_OK)
 {
  CString ErrStr = sqlite3_errstr(rc);
  MessageBox(ErrStr);

  return;
 }
 }

 rc = sqlite3_step(stmt); 

 if(rc != SQLITE_DONE)
 {
 if(rc == SQLITE_ERROR)
 {
  CString DbErr;
  DbErr.Format("Sql Insert failed, %s", sqlite3_errmsg(db));

  MessageBox(DbErr);
 }
 else
 {
  MessageBox("sqlite3_step Failed!");
 }
 }

 sqlite3_finalize(stmt);

附上数据库创建的sql语法:

sqlite> .dump work
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE work (baodanhao text unique primary key , chudanriqi text,qudao text,lianxiren text,xiaoshou text,beibaorenxingming text,chufar
iqi text,baoxianpinpai text,baoxianjihua text,baoxianjine real,yongjinbilv real,jingbaofei real,huankuanfangshi text,haikuanjine real,huanku
anriqi text,shifouquane text,lirunbilv real,lirunjine real,huoliriqi text,fapiaojisong text,shifubaoxiangongsi text,beizhu text);

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 为SQLite3提供一个ANSI到UTF8的互转函数

    在使用Sqlite3时必须要用到的 使用方法: char* src = "...";//待转换的ANSI或UTF8字符串 char* dst = NULL;//保存由函数内部分配的内存指针, 不需要传入内存缓冲区的 转换为UTF-8:to_utf8(src, &dst); 转换为ANSI:to_gb(src, &dst); 返回值:零 - 失败, 非零 - 成功. 注意:如果操作成功, 需要手动释放函数内部分配的空间: 复制代码 代码如下: if(dst){    fr

  • SQLite3中的日期时间函数使用小结

    复制代码 代码如下: import sqlite3conn = sqlite3.connect('/tmp/sqlite.db')cur = conn.cursor() 接下来干嘛呢?建一张表吧.这里需要注意的是,SQLite不支持在创建表的同时创建索引,所以要分两步走,先创建表然后再创建索引 复制代码 代码如下: create_table_stmt = '''CREATE TABLE IF NOT EXISTS test_table ( id INTEGER PRIMARY KEY AUTOI

  • SQLite3的绑定函数族使用与其注意事项详解

    前言 本文给大家展示的代码实际上就是如何利用Sqlite3的参数化机制做数据插入,也可以update操作,就看你怎么玩了,这里只列出代码,然后说一些注意事项. 下面的代码,有一个问题,插入后的东西一定是: INSERT INTO "work" VALUES('铪','铪铪铪铪铪',NULL,NULL,NULL,NULL,'铪铪铪铪铪',NULL,NULL,110.0,1.0,108.9,NULL,NULL,'铪铪铪铪铪',NULL,NULL,NULL,'铪铪铪铪铪',NULL,NULL

  • 基于开发中使用UEditor编辑器的注意事项详解

    最近在一个刚结束的一个项目中使用到了UEditor编辑器,下面总结一下遇到的问题以及使用时需要注意的地方: 1. 使用UEditor插件需要先对其进行路径配置: 在ueditor.config.js文件中 配置 ueditor.config.js文件相对Ueditor文件夹的位置: 2. UEditor的图片上传功能: 此功能需将插件部署至服务器时才可生效: 3. UEditor报错"Cannot set property 'innerHTML' of undefined": 错误的原

  • vue实现绑定事件的方法实例代码详解

    一.前言 vuejs中的事件绑定,使用<v-on:事件名 = 函数名>来完成的,这里函数名是定义在Vue实例中的methods对象中的,Vue实例可以直接访问其中的方法. 二.事件绑定方式 1. 直接在标签中写js方法  <button v-on:click="alert('hi')">执行方法的第一种写法</button> 2.调用method的办法 <button v-on:click="run()">执行方法的第

  • 基于django ManyToMany 使用的注意事项详解

    使用场景一: 如果在一张表中ManayTOManay字段关联的是自身,也就是出项这样的代码: ManyToManyField(self) 那么,你需要注意一点,当你采用add方法将一个自身对象添加到该字段时,则自动建立两方的相互关联. 例如: 有一个朋友关系的字段,多对多关联到自身, friends = models.ManyToManyField('self') 当你采用friends .add()添加对象时,则自动建立双方的关联. 为了禁止这件事情发生,需要添加一个symmetrical参数

  • Oracle数据库服务器修改操作系统时间的注意事项详解

    Oracle 数据库服务器修改操作系统时间的注意事项: 对单机或者ha 1.对数据库本身而言,其实是没有影响的.因为scn不依赖于os时间 2.对app(应用程序)而言,若是app中使用了sysdate之类的,那确实是有影响的. 基于这个情况,我们一般推荐:改os时间 不往之前的时间去改,而是往今后的时间去改. 推荐:安装oracle10g时候注意事项&修改oracle数据库字符集编码 [安装oracle10g时候注意事项:1. 关闭网络连接2.--修改oracle数据库字符集编码:先用syst

  • C++中使用function和bind绑定类成员函数的方法详解

    定义一个普通的类 class Test1{ public: void fun(int val){ cout<<"hello world "<<val<<endl; } }; 开始第一个测试 int main(){ Test1 t; function<void(int)> pf = std::bind(&Test1::fun,t,2); pf(4); // return 0; } 输出的值是2,说明pf传进去的4并没有什么用,在bi

  • sun unsafe类功能及使用注意事项详解

    目录 Unsafe简介 获取Unsafe实例 Unsafe功能列表 Unsafe的数组操作 base offset含义 index scale含义 array copy to direct memory copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes) Benchmark 什么时候用Unsafe Unsafe简介 Unsafe是位于sun.misc包下的一个类,主要提供

  • Vue中判断语句与循环语句基础用法及v-if和v-for的注意事项详解

    目录 一.判断语句 v-if.v-else.v-else-if v-show 案例 二.循环语句 遍历数组 遍历对象 三.v-if和v-for的注意事项 总结 一.判断语句 v-if.v-else.v-else-if v-if是判断是否将DOM元素显示出来 不满足条件的元素,会直接删除,不会存在浏览器上面 v-show 也是用来判断,是否将DOM元素在页面上显示,但是与v-if有着区别,它的不显示是通过display:none;实现的,还是存在浏览上. <div id="app"

  • PostgreSQL查看带有绑定变量SQL的通用方法详解

    当我们在PostgreSQL中分析一些历史的SQL问题时,往往看到的SQL都是带有绑定变量的.而对于pg,我们没法像Oracle一样通过例如dba_hist_sqlbind之类的视图去获取历史的绑定变量值.不仅如此,对于这些带有绑定变量的SQL,我们甚至没法像在Oracle中一样获取一个预估的执行计划. 在pg中使用explain去执行则会报错: bill=# explain select * from t1 where id = $1 and info = $2; ERROR: there i

  • JavaScript this指向绑定方式及不适用情况详解

    目录 前言 问题复现 调用位置 默认绑定 隐式绑定 显式绑定 new 绑定 不适用的情况 总结 前言 JavaScript 中的 this 指向问题对于 web 前端入行不深的人来说是个比较复杂的问题.特写此文章来记录最近遇到的关于匿名函数中 this 指向问题的思考和感悟. 问题复现 最近在研究函数防抖场景时看到如下代码: function debounce(fn, delay) { var timer; // 维护一个 timer return function () { var _this

随机推荐