- SQLite 介绍
- 创建表
- 删除表
- 查询数据中所有表
- 添加列
- 删除列
- 插入数据
- 更新数据
- 删除数据
- 查询数据
- SQLite 占位符写法
- Electron 中使用 SQLite
- Electron 中为什么要这样使用?
- sqlite3 使用步骤
- electron 使用步骤
- 完整代码
SQLite 介绍
SQLite 是一个轻量级的数据库系统,通常用于嵌入式系统和桌面应用程序。
创建表
CREATE TABLE 表名 (
列 1 数据类型,
列 2 数据类型,
列 3 数据类型,
...
);
create table users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name text,
age INTEGER
);
注:建表的时候确定不了该表是否存在
CREATE TABLE IF NOT EXISTS users;
删除表
DROP TABLE 表名;
DROP TABLE users;
查询数据中所有表
SELECT * FROM sqlite_master WHERE type = 'table';
添加列
ALTER TABLE 表名 ADD COLUMN 列名 数据类型;
ALTER TABLE users ADD COLUMN age INT;
删除列
ALTER TABLE 表名 DROP COLUMN 列名;
ALTER TABLE users DROP COLUMN age;
插入数据
INSERT INTO 表名 (列 1, 列 2, 列 3, ...) VALUES (值 1, 值 2, 值 3, ...);
INSERT INTO users (id, name, age) VALUES (3, 'John3', 325);
注:不是数字的值需要单引号或双引号包括
更新数据
UPDATE 表名 SET 列 1=值 1, 列 2=值 2, ... WHERE 条件;
UPDATE users SET age=26 WHERE id=1;
删除数据
DELETE FROM 表名 WHERE 条件;
DELETE FROM users WHERE id=1;
查询数据
查询所有数据
SELECT * FROM 表名;
SELECT * FROM users;
查询特定列的数据
SELECT 列名 1, 列名 2 FROM 表名;
SELECT name, age FROM users;
查询筛选条件数据
SELECT * FROM 表名 WHERE 条件;
SELECT * FROM users WHERE id=1;
分页查询
SELECT * FROM 要查询的表名 LIMIT 每页的行数 OFFSET 起始行号;
SELECT * FROM users LIMIT page_size OFFSET start_row;
SQLite 占位符写法
db.run("UPDATE tbl SET name = ? WHERE id = ?", "bar", 2);
db.run("UPDATE tbl SET name = ? WHERE id = ?", [ "bar", 2 ]);
db.run("UPDATE tbl SET name = $name WHERE id = $id", { $id: 2, $name: "bar"
});
Electron 中使用 SQLite
在 Electron 应用中,SQLite 数据库的逻辑通常写在主进程中,而不是渲染进程。
Electron 中为什么要这样使用?
安全性
在 Electron 应用中,主进程和渲染进程通常具有不同的职责和安全性考虑。主进程负责管理应用的生命周期、创建和与数据库进行交互等任务,而渲染进程则负责显示用户界面和处理用户输入。将数据库逻辑放在主进程中可以增加安全性,因为主进程通常具有更严格的权限和访问控制。
资源管理
SQLite 数据库的连接和操作需要资源管理。将数据库逻辑放在主进程中可以更好地控制这些资源,避免在渲染进程中产生资源泄漏或竞争条件。
异步操作
SQLite 数据库操作通常是异步的,需要回调函数或 Promises 来处理结果。将数据库逻辑放在主进程中可以更好地处理这些异步操作,避免在渲染进程中产生阻塞或延迟。
简化应用结构
将数据库逻辑放在主进程中可以简化应用的结构,使代码更易于维护和调试。这样可以确保应用的不同部分(如渲染进程和主进程)能够更好地分离和独立工作。
渲染进程中:通过主进程、渲染进程的 IPC 通信进行调用。
sqlite3 使用步骤
安装依赖
npm install sqlite3
# or
yarn install sqlite3
数据库实例以及数据库本地文件
// 实例
let db
// 数据库表本地文件
const db_path = path.join(app.getAppPath(), '/db-config/sqlite3.db')
连接数据库
// 连接数据库(electron初始化完成时调用)
db = new sqlite3.Database(db_path, (err) => { // err错误信息 })
运行 SQL 语句
run(sql [, param, ...] [, callback])
参数运行 SQL 查询,然后调用回调
db.run(sql, ...(params || []), (err) => {
// err 错误信息
// rows返回值
})
all(sql [, param, ...] [, callback])
参数运行 SQL 查询,然后调用所有结果行的回调
db.all(sql, ...(params || []), (err, rows) => {
// err 错误信息
// rows返回值
})
关闭数据库
// 关闭数据库(electron应用程序开始关闭窗口时调用)
db && db.close()
electron 使用步骤
preload 预加载
ipcRenderer.invoke
主要用于在渲染进程中发送消息给主进程,并接收主进程的返回结果。
它比传统的 ipcRenderer.send 和 ipcMain.on 方式更为方便,因为使用 invoke 可以直接收到主进程返回的信息,而不需要在主进程中再发送一个返回结果。
/** sqlite */
onExecSQL: (params: SqliteType) => {
return IPC_R2M2R.invoke('sqlite:execSQL', params)
}
主进程
ipcMain.handle
是 Electron 中主进程用来处理渲染进程发送过来的异步或同步消息的方法。这个方法可以接收一个事件和一个回调函数,事件是由渲染进程发送过来的消息,回调函数则是用来处理这个消息的函数。
ipcMain.handle
方法支持异步,触发的方法是 ipcRenderer.invoke
ipcMain.handle('sqlite:execSQL', (e, params) => {
return Promise.resolve(execSQL(params))
})
渲染进程
window.electronIPC.onExecSQL(data).then((res) => {
// res返回值
})
完整代码
import { onSplicingQuotation } from '@/utils'
import { SqlTypeMap } from '@/views/EDB/utils/variable'
/**
* @Author: LGJ
* @Description: 日志
* @Date: 2024/1/2 13:41
*/
}
export const errorger = (strs: any[]) => {
console.error('【error】', ...strs)
}
/**
* @Author: LGJ
* @Description: ERROR记录
* @Date: 2024/1/2 16:04
*/
export const onCheckExecSQLRes = (data: {
fun?: string,
sql: string,
params?: any,
}) => {
return new Promise((resolve, reject) => {
window.electronIPC
.onExecSQL(data)
.then((res: any) => {
const { data, status, message } = res
status === 0 ? resolve(data) : reject(message)
})
.catch((e) => {
errorger([e, data])
})
}).catch((e) => {
errorger([e, data])
})
}
/**
* @Author: LGJ
* @Description: 创建表格
* @Date: 2023/12/29 10:31
*/
export const onCreateTable = (table_name: string) => {
const sql: string =
'CREATE TABLE IF NOT EXISTS ' +
table_name +
' (id INT PRIMARY KEY, company TEXT);'
return onCheckExecSQLRes({ sql })
}
/**
* @Author: LGJ
* @Description: 删除表格
* @Date: 2023/12/29 10:31
*/
export const onDeleteTable = (table_name: string) => {
const sql: string = 'DROP TABLE ' + table_name + ';'
return onCheckExecSQLRes({ sql })
}
/**
* @Author: LGJ
* @Description: 查询数据库有哪些表
* @Date: 2024/1/2 11:24
*/
export const onSelectTable = () => {
const sql: string = "SELECT * FROM sqlite_master WHERE type = 'table';"
return onCheckExecSQLRes({ fun: 'all', sql })
}
/**
* @Author: LGJ
* @Description:
* @Date: 2024/1/9 18:55
*/
export const onSelectTableColumn = (table_name: string) => {
const sql: string = 'PRAGMA table_info(' + table_name + ');'
return onCheckExecSQLRes({ fun: 'all', sql })
}
/**
* @Author: LGJ
* @Description: 添加列,SQLite不支持批量
* @Date: 2023/12/29 10:59
*/
export const onAddTableColumn = (
table_name: string,
column_name: string,
column_type: string
) => {
const sql: string =
'ALTER TABLE ' +
table_name +
' ADD COLUMN ' +
column_name +
' ' +
SqlTypeMap[column_type || 'string'] +
';'
return onCheckExecSQLRes({ sql })
}
/**
* @Author: LGJ
* @Description: 删除列,SQLite不支持批量
* @Date: 2024/1/2 09:48
*/
export const onDeleteTableColumn = (
table_name: string,
column_name: string
) => {
const sql: string =
'ALTER TABLE ' + table_name + ' DROP COLUMN ' + column_name + ';'
return onCheckExecSQLRes({ sql })
}
/**
* @Author: LGJ
* @Description: 添加表格数据
* @Date: 2024/1/2 10:14
*/
export const onAddTableData = (
table_name: string,
table_data: Record<string, any>
) => {
const columns: string[] = Object.keys(table_data)
if (!columns.length) return
const params: string[] = Object.values(table_data)
const values: any = Array(params.length)
.fill(null)
.map((item: any) => '?')
const sql: string =
'INSERT INTO ' +
table_name +
' (' +
columns.join(',') +
') VALUES (' +
values.join(',') +
');'
return onCheckExecSQLRes({ sql, params })
}
/**
* @Author: LGJ
* @Description: 删除表格数据(id)
* @Date: 2024/1/2 10:19
*/
export const onDeleteTableData = (table_name: string, row_id: number) => {
const sql: string =
'DELETE FROM ' +
table_name +
' WHERE id = ' +
onSplicingQuotation(row_id) +
';'
return onCheckExecSQLRes({ sql })
}
/**
* @Author: LGJ
* @Description: 修改表格数据(id)
* @Date: 2024/1/2 14:47
*/
export const onUpdateTableData = (
table_name: string,
row_id: number,
update_data: Record<string, any>
) => {
const columns: string[] = Object.keys(update_data)
if (!columns.length) return
const params: string[] = Object.values(update_data)
const set_sql: string[] = []
columns.forEach((key: string) => {
set_sql.push(key + '= ?')
})
const sql: string =
'UPDATE ' +
table_name +
' SET ' +
set_sql.join(',') +
' WHERE id = ' +
onSplicingQuotation(row_id) +
';'
return onCheckExecSQLRes({ sql, params })
}
/**
* @Author: LGJ
* @Description: 运行指定sql
* @Date: 2024/2/21 11:11
*/
export const onRunAppointSql = (sql: string) => {
return onCheckExecSQLRes({ fun: 'all', sql })
}
京ICP备2022027737号
Copyright © 2022 - present @wangxiang