node操作本地?cái)?shù)據(jù)庫(kù)-SQLite方案

SQLite是一款輕量級(jí)的數(shù)據(jù)庫(kù),SQLite的第一個(gè)版本是2000年就發(fā)布了的,經(jīng)過(guò)十多年的歷練,顯然SQLite目前已經(jīng)相當(dāng)成熟。SQLite最大的特點(diǎn)就是沒(méi)有任何數(shù)據(jù)庫(kù)服務(wù)器,無(wú)論是C、javanode.js,只需要相應(yīng)的驅(qū)動(dòng),就可以直接對(duì)數(shù)據(jù)庫(kù)進(jìn)行讀寫(xiě),速度是相當(dāng)?shù)目?。這里我們通過(guò)SQLite3實(shí)現(xiàn)對(duì)SQLite的一些操作。SQLite3非常小,輕量級(jí),就幾百K大??;不需要用戶名,密碼,直接就可以對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作。

注:這里使用是配合Electron。而且需要前端對(duì)數(shù)據(jù)庫(kù)sql語(yǔ)句有一定了解。

一、安裝SQLite3數(shù)據(jù)庫(kù)

cnpm install sqlite3 --save

二、建立數(shù)據(jù)庫(kù)鏈接

const sqlite3 = require('sqlite3').verbose(),
    DB = new sqlite3.Database('data.db', {});
這里必須指定.db文件位置,建議和這個(gè)js文件放在一個(gè)目錄,而后這個(gè)鏈接數(shù)據(jù)庫(kù)的js文件要在Electron主進(jìn)程js文件里面調(diào)用。
// 關(guān)閉數(shù)據(jù)庫(kù)鏈接
DB.close((err, res) => {
    if (err) {
        console.log('數(shù)據(jù)庫(kù)鏈接關(guān)閉失敗::');
        console.log(err)
        return;
    }
    console.log('數(shù)據(jù)庫(kù)鏈接關(guān)閉成功::');
    console.log(res)
})

三、操作數(shù)據(jù)庫(kù)

  1. run方法
    用法:run(sql,param,...],[callback]),多用于新增、修改、刪除等不需要返回?cái)?shù)據(jù)的場(chǎng)景。
    功能:運(yùn)行指定參數(shù)的SQL語(yǔ)句,完成之后調(diào)用回調(diào)函數(shù),它不返回任何數(shù)據(jù),在回調(diào)函數(shù)里面有一個(gè)參數(shù),SQL語(yǔ)句執(zhí)行成功,則參數(shù)的值為null,反之為一個(gè)錯(cuò)誤的對(duì)象,它返回的是數(shù)據(jù)庫(kù)的操作對(duì)象。在這個(gè)回調(diào)函數(shù)里面當(dāng)中的this,里面包含有lastId(插入的ID)和change(操作影響的行數(shù),如果執(zhí)行SQL語(yǔ)句失敗,則change的值永遠(yuǎn)為0)。

  2. all方法
    用法:all(sql,[param,...],[callback]),多用于查詢等需要返回?cái)?shù)據(jù)的場(chǎng)景。
    功能:運(yùn)行指定參數(shù)的SQL語(yǔ)句,完成過(guò)后調(diào)用回調(diào)函數(shù)。如果執(zhí)行成功,則回調(diào)函數(shù)中的第一個(gè)參數(shù)為null,第二個(gè)參數(shù)為查詢的結(jié)果集,反之,則只有一個(gè)參數(shù),且參數(shù)的值為一個(gè)錯(cuò)誤的對(duì)象。

  3. 基礎(chǔ)操作示例
    3.1. 創(chuàng)建數(shù)據(jù)表

const CREATE_TABLE_SQL = `CREATE TABLE  IF NOT EXISTS  user
    (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(64),
    age INTEGER
    );`;
DB.run(CREATE_TABLE_SQL, (err, res) => {
    if (err) {
        console.log('創(chuàng)建表失敗::');
        console.log(err)
        return;
    }
    console.log('創(chuàng)建表成功::');
    console.log(res)
});
創(chuàng)建數(shù)據(jù)表

3.2. 新增數(shù)據(jù)

const _user_info = {
    name: 'cuiht-' + Math.ceil(Math.random() * 100),
    age: Math.ceil(Math.random() * 100)
}, TEST_INSERT_SQL = `INSERT INTO user (name, age)  VALUES('${_user_info.name}','${_user_info.age}')`;
DB.all(TEST_INSERT_SQL, (err, res) => {
    if (err) {
        console.log('新增數(shù)據(jù)失敗::');
        console.log(err)
        return;
    }
    console.log('新增數(shù)據(jù)成功::');
    console.log(res)
});
新增數(shù)據(jù)

3.3. 修改數(shù)據(jù)

const _user_info_u = {
    name: 'cuiht-' + Math.ceil(Math.random() * 100),
    age: Math.ceil(Math.random() * 100)
}, TEST_UPT_SQL = `UPDATE user
    SET name = '${_user_info_u.name}', age = '${_user_info_u.age}'
    WHERE id = '2'`;
DB.all(TEST_UPT_SQL, (err, res) => {
    if (err) {
        console.log('修改數(shù)據(jù)失敗::');
        console.log(err)
        return;
    }
    console.log('修改數(shù)據(jù)成功::');
    console.log(res)
});
修改數(shù)據(jù)

3.4. 刪除數(shù)據(jù)

const TEST_DEL_SQL = `DELETE FROM user WHERE id = '3'`;
DB.all(TEST_DEL_SQL, (err, res) => {
    if (err) {
        console.log('刪除數(shù)據(jù)失敗::');
        console.log(err)
        return;
    }
    console.log('刪除數(shù)據(jù)成功::');
    console.log(res)
});
刪除數(shù)據(jù)

3.5. 查詢數(shù)據(jù)列表

const TEST_LIST_SQL = `SELECT * FROM user ORDER BY id DESC`;
DB.all(TEST_LIST_SQL, (err, res) => {
    if (err) {
        console.log('查詢數(shù)據(jù)列表失敗::');
        console.log(err)
        return;
    }
    console.log('查詢數(shù)據(jù)列表成功::');
    console.log(res)
});
查詢數(shù)據(jù)列表

3.6. 查詢數(shù)據(jù)

const TEST_GET_SQL = `SELECT * FROM user WHERE id = '3'`;
DB.all(TEST_GET_SQL, (err, res) => {
    if (err) {
        console.log('查詢數(shù)據(jù)失敗::');
        console.log(err)
        return;
    }
    console.log('查詢數(shù)據(jù)成功::');
    console.log(res)
});
查詢數(shù)據(jù)

四、 使用案例

注:這里是在Electron+vue中的使用案例。
  1. 新建文件src/DB/index.js,同時(shí)在相同的目錄新建data.db文件。
/*
 * @Author: cuiht
 * @Date: 2022-04-22 18:31:27
 * @LastEditors: cuiht
 * @LastEditTime: 2022-04-25 17:28:13
 * @Description: 數(shù)據(jù)庫(kù)鏈接 及 數(shù)據(jù)庫(kù)操作方法封裝
 */
const { ipcMain } = require('electron'),
    sqlite3 = require('sqlite3').verbose(),
    DB = new sqlite3.Database('data.db', {});

export const DBserve = (arg) => {
    return new Promise((resolve) => {
        const { tableName = '', order = '', option = {} } = arg;
        if (!tableName) {
            return resolve({
                code: 0,
                msg: '未獲取數(shù)據(jù)表名!'
            })
        }
        if (!order) {
            return resolve({
                code: 0,
                msg: '未獲取到指令!'
            })
        }
        switch (order) {
            case 'insert':
                const TEST_INSERT_SQL = `INSERT INTO ${tableName} (name, age)  VALUES('${option.name}','${option.age}')`;
                DB.all(TEST_INSERT_SQL, (err, data) => {
                    if (err) {
                        return resolve({
                            code: 0,
                            msg: err
                        })
                    }
                    return resolve({
                        code: 200,
                        msg: "新增成功!",
                        data,
                    })
                });
                break;
            case 'find':
                const TEST_LIST_SQL = `SELECT * FROM ${tableName} ORDER BY id DESC`;
                DB.all(TEST_LIST_SQL, (err, data) => {
                    if (err) {
                        return resolve({
                            code: 0,
                            msg: err
                        })
                    }
                    return resolve({
                        code: 200,
                        msg: "查詢列表成功!",
                        data,
                    })
                });
                break;
            case 'findOne':
                let findOne_str = '', findOne_i = 0;
                for (const key in option) {
                    if (findOne_i > 0) {
                        findOne_str += ` and `;
                    }
                    findOne_str += `${key} = ${option[key]}`;
                    findOne_i++;
                }
                const TEST_GET_SQL = `SELECT * FROM ${tableName} WHERE ${findOne_str}`;
                DB.all(TEST_GET_SQL, (err, data) => {
                    if (err) {
                        return resolve({
                            code: 0,
                            msg: err
                        })
                    }
                    return resolve({
                        code: 200,
                        msg: "查詢成功!",
                        data,
                    })
                });
                break;
            case 'update':
                if (!option.id) {
                    return resolve({
                        code: 0,
                        msg: '未獲取到id'
                    })
                }
                let update_str = '', update_i = 0;
                for (const key in option) {
                    if (key!=='id') {
                        if (update_i > 0) {
                            update_str += `,`;
                        }
                        update_str += `${key} = '${option[key]}'`;
                        update_i++;
                    }
                }
                const TEST_UPT_SQL = `UPDATE ${tableName} SET ${update_str} WHERE id = ${option.id}`;
                DB.all(TEST_UPT_SQL, (err, data) => {
                    if (err) {
                        return resolve({
                            code: 0,
                            msg: err
                        })
                    }
                    return resolve({
                        code: 200,
                        msg: "更新成功!",
                        data,
                    })
                });
                break;
            case 'remove':
                if (!option.id) {
                    return resolve({
                        code: 0,
                        msg: '未獲取到id'
                    })
                }
                const TEST_DEL_SQL = `DELETE FROM ${tableName} WHERE id = ${option.id}`;
                DB.all(TEST_DEL_SQL, (err, data) => {
                    if (err) {
                        return resolve({
                            code: 0,
                            msg: err
                        })
                    }
                    return resolve({
                        code: 200,
                        msg: "刪除成功!",
                        data,
                    })
                });
                break;
            default:
                break;
        }
    })
};

export const DBrunSql = (sql) => {
    return new Promise((resolve) => {
        if (!sql) {
            return resolve({
                code: 0,
                msg: '未獲取到sql!'
            })
        }
        DB.run(sql, (err, data) => {
            if (err) {
                return resolve({
                    code: 0,
                    msg: err
                })
            }
            return resolve({
                code: 200,
                msg: 'sql執(zhí)行成功!',
                data
            })
        })
    })
};

ipcMain.on('DBserve', (event, arg) => {
    DBserve(arg).then(res => {
        event.returnValue = res
    })
});
ipcMain.on('DBrunSql', (event, arg) => {
    DBrunSql(arg).then(res => {
        event.returnValue = res
    })
});
  1. 新建文件public/ipcRenderer.js。
window.ipcRenderer = require("electron").ipcRenderer;
  1. 修改Electron主進(jìn)程js文件。
// 引入數(shù)據(jù)庫(kù)入口文件
import './DB'
// ... 其他代碼
async function createWindow() {
  const win = new BrowserWindow({
    // ...
    webPreferences: {
      // ...
      nodeIntegration: true,
      contextIsolation: false,
      preload: `${__static}/ipcRenderer.js`
      // ...
    },
    // ...
  })
  // ...
}
// ... 其他代碼
  1. 新建src/network/dataServes.js
/*
 * @Author: cuiht
 * @Date: 2022-04-25 14:44:40
 * @LastEditors: cuiht
 * @LastEditTime: 2022-04-25 17:37:46
 * @Description: 調(diào)用數(shù)據(jù)庫(kù)方法封裝
 */

// 創(chuàng)建數(shù)據(jù)表
const CREATE_TABLE_SQL = `CREATE TABLE  IF NOT EXISTS  users
    (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name VARCHAR(64),
        age INTEGER
    );`;
window.ipcRenderer.sendSync('DBrunSql', CREATE_TABLE_SQL)

const DBserve = ({ order = '', option = '' }) => {
    return new Promise((resolve) => {
        const res = window.ipcRenderer.sendSync('DBserve', {
            tableName: 'users',
            order,
            option
        })
        resolve(res)
    });
}

export const
    // 新增記錄
    userAdd = data => DBserve({
        order: 'insert',
        option: {
            ...data,
            createTime: new Date().getTime()
        }
    }),
    // 查詢記錄列表
    userList = data => DBserve({
        order: 'find',
        option: data
    }),
    // 查詢記錄
    userGet = data => DBserve({
        order: 'findOne',
        option: data
    }),
    // 修改記錄
    userUpt = data => DBserve({
        order: 'update',
        option: data
    }),
    // 刪除記錄
    userDel = data => DBserve({
        order: 'remove',
        option: data
    });
  1. 新建一個(gè)vue頁(yè)面。
<!--
 * @Author: cuiht
 * @Date: 2022-04-22 18:41:07
 * @LastEditors: cuiht
 * @LastEditTime: 2022-04-25 17:39:03
 * @Description: 使用示例
-->
<template>
  <div id="text-page">
    <table class="list">
      <tr>
        <td><button @click="Add">新增</button></td>
      </tr>
      <tr v-for="item in list" :key="item.id">
        <td>
          {{ item }}
        </td>
        <td style="width: 150px">
          <button @click="Upt(item)">修改</button>
          <button @click="Del(item)">刪除</button>
          <button @click="Get(item)">查看</button>
        </td>
      </tr>
    </table>
  </div>
</template>

<script>
import {
  userAdd,
  userList,
  userGet,
  userUpt,
  userDel,
} from "@/network/dataServes";
export default {
  name: "test",
  data() {
    return {
      list: [],
    };
  },
  mounted() {
    this.List();
  },
  methods: {
    Add() {
      const reqData = {
        age: this.list.length + 1,
        name: "cuiht-" + new Date().getTime(),
      };
      userAdd(reqData).then((res) => {
        console.log(res);
        if (res.code !== 200) {
          return;
        }
        this.List();
      });
    },
    List() {
      userList().then((res) => {
        console.log(res);
        if (res.code !== 200) {
          return;
        }
        this.list = res.data;
      });
    },
    Get(item) {
      userGet({
        id: item.id,
      }).then((res) => {
        console.log(res);
        if (res.code !== 200) {
          return;
        }
        alert(JSON.stringify(res.data));
      });
    },
    Upt(item) {
      const reqData = {
        id: item.id,
        age: this.list.length + 1,
        name: "undate-" + new Date().getTime(),
      };
      userUpt(reqData).then((res) => {
        console.log(res);
        if (res.code !== 200) {
          return;
        }
        this.List();
      });
    },
    Del(item) {
      userDel({
        id: item.id,
      }).then((res) => {
        console.log(res);
        if (res.code !== 200) {
          return;
        }
        this.List();
      });
    },
  },
};
</script>

<style lang="scss">
#text-page {
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
}
</style>
效果圖

無(wú)論你將來(lái)想去哪里,想過(guò)怎樣的生活,請(qǐng)現(xiàn)在就為自己蓄積能量。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容