Nodejs 操作Sqlite3数据库

 

1、安装Nodejs

在nodejs官网(http://nodejs.cn/)下载安装nodesjs,本文版本是:v10.3.0。

2、安装sqlite3包

用npm包安装sqlite3。通过命令npm install sqlite3 –g安装,安装成功之后可以用npm list sqlite3 –g看对应sqlite3版本,本文版本是 sqlite3@4.0.2。

3、sqlite3 API介绍

在nodejs的模块安装模块下,进入sqlite3/lib目录下,打开sqlite3.js文件查看,操作数据库主要是用Database,Database相关的函数有:run、prepare、each、get、all、exec、map和close。

3.1、Database

用法:new sqlite3.Database(filename,[mode],[callback])。

功能:返回数据库对象并且自动打开和连接数据库,它没有独立打开数据库的方法。

3.1.1、close

用法:close([callback])。

功能:关闭和释放数据库对象。

3.1.2、run

用法:run(sql,param,...],[callback])。

功能:运行指定参数的SQL语句,完成之后调用回调函数,它不返回任何数据,在回调函数里面有一个参数,SQL语句执行成功,则参数的值为null,反之为一个错误的对象,它返回的是数据库的操作对象。在这个回调函数里面当中的this,里面包含有lastId(插入的ID)和change(操作影响的行数,如果执行SQL语句失败,则change的值永远为0)。

3.1.3、get

用法:get(sql,[param,...],[callback])。

功能:运行指定参数的SQL语句,完成过后调用回调函数。如果执行成功,则回调函数中的第一个参数为null,第二个参数为结果集中的第一行数据,反之则回调函数中只有一个参数,只参数为一个错误的对象。

3.1.4、all

用法:all(sql,[param,...],[callback])。

功能:运行指定参数的SQL语句,完成过后调用回调函数。如果执行成功,则回调函数中的第一个参数为null,第二个参数为查询的结果集,反之,则只有一个参数,且参数的值为一个错误的对象。

3.1.5、prepare

用法:prepare(sql,[param,...],[callback])。

功能:预执行绑定指定参数的SQL语句,返回一个Statement对象,如果执行成功,则回调函数的第一个参数为null,反之为一个错误的对象。

4、具体事例

由于sqlite3 API具体使用过程中重复代码量较多,所以进行了简单封装,在使用过程中如果第一次创建数据库和表,紧接着插入数据的话,可能导致表还未创建完成就查询出现错误(Nodejs是基于异步的且顺序不可控),所以在表创建和插入数据时使用同步方式操作来保证表已经存在。封装的代码如下:

/**
 * File: sqlite.js.
 * Author: W A P.
 * Email: 610585613@qq.com.
 * Datetime: 2018/07/24.
 */

var fs = require('fs');
var sqlite3 = require('sqlite3').verbose();

var DB = DB || {};

DB.SqliteDB = function(file){
    DB.db = new sqlite3.Database(file);

    DB.exist = fs.existsSync(file);
    if(!DB.exist){
        console.log("Creating db file!");
        fs.openSync(file, 'w');
    };
};

DB.printErrorInfo = function(err){
    console.log("Error Message:" + err.message + " ErrorNumber:" + errno);
};

DB.SqliteDB.prototype.createTable = function(sql){
    DB.db.serialize(function(){
        DB.db.run(sql, function(err){
            if(null != err){
                DB.printErrorInfo(err);
                return;
            }
        });
    });
};

/// tilesData format; [[level, column, row, content], [level, column, row, content]]
DB.SqliteDB.prototype.insertData = function(sql, objects){
    DB.db.serialize(function(){
        var stmt = DB.db.prepare(sql);
        for(var i = 0; i < objects.length; ++i){
            stmt.run(objects[i]);
        }
    
        stmt.finalize();
    });
};

DB.SqliteDB.prototype.queryData = function(sql, callback){
    DB.db.all(sql, function(err, rows){
        if(null != err){
            DB.printErrorInfo(err);
            return;
        }

        /// deal query data.
        if(callback){
            callback(rows);
        }
    });
};

DB.SqliteDB.prototype.executeSql = function(sql){
    DB.db.run(sql, function(err){
        if(null != err){
            DB.printErrorInfo(err);
        }
    });
};

DB.SqliteDB.prototype.close = function(){
    DB.db.close();
};

/// export SqliteDB.
exports.SqliteDB = DB.SqliteDB;

 

针对以上封装接口的调用代码如下:

/**

 * File: callSqlite.js.

 * Author: W A P.

 * Email: 610585613@qq.com.

 * Datetime: 2018/07/24.

 */



/// Import SqliteDB.

var SqliteDB = require('./sqlite.js').SqliteDB;



var file = "Gis1.db";

var sqliteDB = new SqliteDB(file);



/// create table.

var createTileTableSql = "create table if not exists tiles(level INTEGER, column INTEGER, row INTEGER, content BLOB);";

var createLabelTableSql = "create table if not exists labels(level INTEGER, longitude REAL, latitude REAL, content BLOB);";

sqliteDB.createTable(createTileTableSql);

sqliteDB.createTable(createLabelTableSql);



/// insert data.

var tileData = [[1, 10, 10], [1, 11, 11], [1, 10, 9], [1, 11, 9]];

var insertTileSql = "insert into tiles(level, column, row) values(?, ?, ?)";

sqliteDB.insertData(insertTileSql, tileData);



/// query data.

var querySql = 'select * from tiles where level = 1 and column >= 10 and column <= 11 and row >= 10 and row <=11';

sqliteDB.queryData(querySql, dataDeal);



/// update data.

var updateSql = 'update tiles set level = 2 where level = 1 and column = 10 and row = 10';

sqliteDB.executeSql(updateSql);



/// query data after update.

querySql = "select * from tiles where level = 2";

sqliteDB.queryData(querySql, dataDeal);



sqliteDB.close();



function dataDeal(objects){

    for(var i = 0; i < objects.length; ++i){

        console.log(objects[i]);

    }

}

测试代码结果如下:

Object {level: 1, column: 10, row: 10, content: null}        

Object {level: 1, column: 11, row: 11, content: null}       

Object {level: 2, column: 10, row: 10, content: null}      

其中前两行是第一次查询的结果,最后一行结果是执行update结果之后查询的结果。

5、注意事项

由于Node-Sqlite3是基于回调的异步编程思想,这样会导致表还不存在就增删改数据,导致错误,所以创建表时操作和插入数据操作需要采用控制,保证在操作时表已经存在。

Sqlite3的接口都是基于回调函数,所以查询数据的结果并不能直接拿到,所以常规做法都是传入参数或者回调函数,等到查询结果执行之后通过传入的参数保存该结果或者回调函数处理结果。

6、改进工作

从以上测试代码可以看到,其中调用代码比较杂乱,所以为了项目实际需要,可以根据自己业务需求,对Sqlite操作做进一步封装调用,方便开发人员使用,使开发人员集中精力实现业务需求。

7、代码下载

  https://download.csdn.net/download/wap1981314/10561075

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页