Ubuntu 22.04下Node.js与SQLite集成完全指南

简介

SQLite是一种流行的开源SQL数据库引擎,用于存储数据。它是无服务器的,意味着它不需要服务器运行,而是将数据读写到计算机硬盘上的文件中。此外,SQLite不需要任何配置,这使它更加便携,成为嵌入式系统、桌面/移动应用和原型制作等领域的流行选择。

要在Node.js中使用SQLite,您需要一个连接到SQLite数据库并将应用程序中的SQL语句发送到数据库以执行的数据库客户端。其中一个受欢迎的选择是node-sqlite3包,它提供了SQLite 3的异步绑定。

在本教程中,您将使用node-sqlite3创建与SQLite数据库的连接。接下来,您将创建一个Node.js应用程序,在数据库中创建一个表并插入数据。最后,您将修改应用程序,使用node-sqlite3从数据库中检索、更新和删除数据。

先决条件

要按照这个教程进行操作,您需要准备以下物品:

  • 在您的系统上设置Node.js开发环境。如果您使用的是Ubuntu 22.04,请按照我们的教程《如何在Ubuntu 22.04上安装Node.js》中的选项3安装最新版本的Node.js。对于其他系统,请参考我们的教程系列《如何安装Node.js并创建本地开发环境》。
  • 在您的开发环境中安装SQLite3。请按照我们的教程《如何在Ubuntu 20.04上安装和使用SQLite》的步骤1进行操作。
  • 具备创建表和编写SQL查询以检索和修改表中数据的基本知识。请按照我们的教程《如何在Ubuntu 20.04上安装和使用SQLite》的步骤2至步骤6进行操作。
  • 熟悉如何编写Node.js程序,您可以在我们的教程《如何在Node.js中编写和运行您的第一个程序》中找到相关信息。

第一步 – 设置项目目录

在这个步骤中,您将创建项目目录并将node-sqlite3作为依赖下载。

首先,使用mkdir命令创建一个目录。这个教程将其称为sqlite_demo,但你可以用你选择的名称替换它。

  1. mkdir sqlite_demo

 

接下来,使用cd命令切换到新创建的目录。

  1. cd sqlite_demo

 

使用npm命令将项目目录初始化为npm包。

  1. npm init -y

 

该命令创建一个package.json文件,其中包含了项目的重要元数据。-y选项告诉npm接受所有默认设置。

运行命令后,以下输出将显示在您的屏幕上:

输出

已写入 /home/sammy/sqlite_demo/package.json: { “name”: “sqlite_demo”, “version”: “1.0.0”, “description”: “”, “main”: “index.js”, “scripts”: { “test”: “echo \”Error: no test specified\” && exit 1″ }, “keywords”: [], “author”: “”, “license”: “ISC” }

输出结果表明已创建了package.json文件,其中包含记录项目重要元数据的属性。其中一些重要选项包括:

  • name: 您的项目名称。
  • version: 您的项目版本。
  • main: 您项目的起始点。

您可以保留默认选项,但可以根据个人喜好修改属性值。如需了解更多属性信息,请参考npm的package.json文档。

接下来,使用npm install命令安装node-sqlite3软件包。

  1. npm install sqlite3

 

安装软件包后,输出将如下显示:

输出

添加了104个包,并在9秒内审计了105个包 5个包正在寻找资金 运行 `npm fund` 了解详情 发现0个漏洞

现在你已经安装了node-sqlite3,你将在下一节中使用它来连接SQLite数据库。

步骤2 – 连接到SQLite数据库

在这一步中,您将使用node-sqlite3将您的Node.js程序与一个包含不同鲨鱼及其属性的SQLite数据库连接起来。要建立数据库连接,node-sqlite3包提供了一个Database类。当实例化该类时,该类会在您的计算机硬盘上创建一个SQLite数据库文件并连接到它。一旦建立了连接,您将为应用程序创建一个表,在后面的部分中您将使用该表来插入、检索或更新数据。

使用nano或者你喜欢的文本编辑器,创建并打开db.js文件。

  1. nano db.js

 

在你的db.js文件中,添加以下代码来建立与SQLite数据库的连接。

sqlite_demo/db.js文件

这是文章《如何在Ubuntu 22.04上使用Node.js使用SQLite》的第2部分(共15部分)。

const sqlite3 = require("sqlite3").verbose();
const filepath = "./fish.db";

function createDbConnection() {
  const db = new sqlite3.Database(filepath, (error) => {
    if (error) {
      return console.error(error.message);
    }
  });
  console.log("与SQLite的连接已建立");
  return db;
}

在第一行中,将node-sqlite3模块引入到您的程序文件中。在第二行中,使用您想要SQLite数据库所在的路径和数据库文件的名称(在这种情况下是fish.db)设置变量filepath。

在下一行中,您定义了createDbConnection()函数,该函数与SQLite数据库建立连接。在函数内部,您使用new关键字实例化了sqlite3.Database()类。该类接受两个参数:文件路径和回调函数。

第一个参数是文件路径,接受SQLite数据库的名称和路径,这里是./fish.db。第二个参数是回调函数,在数据库被创建并建立数据库连接后运行。回调函数接受一个错误参数,如果尝试建立数据库连接时发生错误,这个参数将被设为一个错误对象。在回调函数中,你可以使用if语句检查是否有错误发生。如果条件为真,你可以使用console.error()方法记录错误消息。

现在,当你使用sqlite3.Database()类创建一个实例时,它会在你的项目目录中创建一个SQLite数据库文件,并返回一个存储在db变量中的数据库对象。该数据库对象提供了可以用来传递SQL语句来创建表格以及插入、检索或修改数据的方法。

最后,你使用console.log()来输出成功消息,并将db变量中的数据库对象返回。

接下来,将高亮代码添加到创建表格的函数中。

sqlite_demo/db.js 的中文翻译:sqlite_demo/数据库.js
...
function createDbConnection() {
    ...
}

function createTable(db) {
  db.exec(`
  CREATE TABLE sharks
  (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    name   VARCHAR(50) NOT NULL,
    color   VARCHAR(50) NOT NULL,
    weight INTEGER NOT NULL
  );
`);
}

createTable() 函数在 SQLite 数据库中创建一个表。它以数据库对象 db 作为参数。在 createTable() 函数内部,你调用了 db 数据库对象的 exec() 方法,将给定的 SQL 语句发送到数据库以供执行。exec() 方法仅用于不返回结果行的查询。

传递给exec()方法的CREATE TABLE sharks… SQL语句创建了一个名为sharks的表,该表具有以下字段:

  • ID: 存储INTEGER数据类型的值。PRIMARY KEY约束将该列指定为主键,AUTOINCREMENT指示SQLite自动为表中的每一行增加ID列的值。
  • name: 使用最大长度为50个字符的VARCHAR数据类型详细记录鲨鱼的名称。NOT NULL约束确保该字段不能存储NULL值。
  • color: 使用最大长度为50个字符的VARCHAR数据类型表示鲨鱼的颜色。NOT NULL约束表示该字段不应接受NULL值。
  • weight: 使用INTEGER数据类型存储鲨鱼的重量(以千克为单位),并使用NOT NULL约束确保不允许NULL值。

在同一个db.js文件中,添加以下突出显示的代码来调用createTable()函数:

sqlite_demo/db.js 文件。
function createDbConnection() {
  const db = new sqlite3.Database(filepath, (error) => {
    if (error) {
      return console.error(error.message);
    }
    createTable(db);
  });
  console.log("与SQLite的连接已建立");
  return db;
}


function createTable(db) {
    ...
}

当回调函数运行时,你调用createTable()函数,并将数据库对象作为参数传递进去。

接下来,将以下代码行添加到调用createDbConnection()函数的地方:

...
function createDbConnection() {
    ...
}


function createTable(db) {
    ...
}

module.exports = createDbConnection();

在之前的代码中,你调用了createDbConnection()函数,该函数建立了与数据库的连接并返回一个数据库对象。然后你使用module.exports将数据库对象导出,这样你就可以在其他文件中引用它。

你的文件现在将包含以下内容:

sqlite_demo/db.js的中文释义
const sqlite3 = require("sqlite3").verbose();
const filepath = "./fish.db";

function createDbConnection() {
  const db = new sqlite3.Database(filepath, (error) => {
    if (error) {
      return console.error(error.message);
    }
    createTable(db);
  });
  console.log("与SQLite的连接已建立");
  return db;
}

function createTable(db) {
  db.exec(`
  CREATE TABLE sharks
  (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    name   VARCHAR(50) NOT NULL,
    color   VARCHAR(50) NOT NULL,
    weight INTEGER NOT NULL
  );
`);
}

module.exports = createDbConnection();

保存并退出文件。如果使用nano编辑器,请按下CTRL+X退出,按下y保存你所做的更改,并按下ENTER键确认文件名。

使用node命令运行db.js文件。

  1. node db.js

输出结果将显示数据库连接已成功建立。

输出

与SQLite的连接已建立

接下来,使用ls命令检查是否已创建fish.db数据库文件。

  1. ls
输出

db.js fish.db node_modules package-lock.json package.json

鱼.db数据库文件在输出中的出现证实了数据库的成功创建。

现在,每次运行db.js文件,都会调用createTable()函数在数据库中创建一张表。尝试创建已经存在的表会触发SQLite抛出一个错误。要查看这一点,请使用节点命令重新运行db.js文件。

  1. node db.js

 

这一次,在接下来的输出中,你将会得到一个错误。

输出

已建立与SQLite的连接 undefined:0 [错误: SQLITE_ERROR: 鲨鱼表已存在 在数据库实例上发出’error’事件: ] { errno: 1, code: ‘SQLITE_ERROR’ } Node.js v17.6.0

错误信息表明鲨鱼表已经存在。这是因为当您第一次运行节点命令时,鱼数据库和鲨鱼表已经创建。当您重新运行该命令时,createTable() 函数会再次运行,这将触发错误,因为该表已经存在。

每当您想要在其他文件中使用数据库对象方法操作数据库时,也会触发此错误。例如,在下一步中,您将创建一个将数据插入数据库的文件。为了使用数据库对象,您将导入 db.js 文件并调用相应的插入数据方法。当您运行该文件时,它将依次运行 db.js,从而触发相同的错误。

为了解决这个问题,你可以使用fs模块的existsSync()方法检查项目目录中是否存在名为fish.db的数据库文件。如果数据库文件存在,你将建立与数据库的连接而不调用createTable()函数。如果不存在,你将建立连接并调用createTable()函数。

为了做到这一点,请再次在您的编辑器中打开db.js文件。

  1. nano db.js

 

在你的db.js文件中,添加标记代码以检查数据库文件的存在。

const fs = require("fs");
const sqlite3 = require("sqlite3").verbose();
const filepath = "./fish.db";

function createDbConnection() {
  if (fs.existsSync(filepath)) {
    return new sqlite3.Database(filepath);
  } else {
    const db = new sqlite3.Database(filepath, (error) => {
      if (error) {
        return console.error(error.message);
      }
      createTable(db);
    });
    console.log("与SQLite的连接已经建立");
    return db;
  }
}

首先,您导入用于与文件系统交互的fs模块。其次,在添加的if语句中,您调用fs.existsSync()方法来检查给定参数中文件(此处为./fish.db)是否存在。如果文件存在,您会使用数据库文件路径调用sqlite3.Database(),并省略回调函数。然而,如果文件不存在,您将在回调函数中创建数据库实例,并调用createTable()函数来创建数据库中的表。

此时,完整的文件将会如下所示:

sqlite_demo/db.js

SQLite_demo/db.js

这是文章《如何在Ubuntu 22.04上使用Node.js使用SQLite》的第8部分(共15部分)。

const fs = require("fs");
const sqlite3 = require("sqlite3").verbose();
const filepath = "./fish.db";

function createDbConnection() {
  if (fs.existsSync(filepath)) {
    return new sqlite3.Database(filepath);
  } else {
    const db = new sqlite3.Database(filepath, (error) => {
      if (error) {
        return console.error(error.message);
      }
      createTable(db);
    });
    console.log("已成功建立与SQLite的连接");
    return db;
  }
}

function createTable(db) {
  db.exec(`
  CREATE TABLE sharks
  (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    name   VARCHAR(50) NOT NULL,
    color   VARCHAR(50) NOT NULL,
    weight INTEGER NOT NULL
  );
`);
}

module.exports = createDbConnection();

完成更改后,请保存并关闭您的文件。

为确保多次运行db.js文件时不会出错,请使用rm命令删除fish.db文件以重新开始。

  1. rm fish.db

运行db.js文件。

  1. node db.js
输出

已建立与SQLite的连接

现在,运行db.js文件以确认其是否连接到数据库,并且在所有后续重新运行db.js文件时不会再次尝试创建表格。

  1. node db.js

 

你现在会注意到,你再也不会遇到错误了。

既然你已经建立了与SQLite数据库的连接并创建了一个表格,那么接下来你将向数据库插入数据。

第三步 – 将数据插入SQLite数据库

在这一步中,您将使用node-sqlite3模块创建一个函数,以将数据插入SQLite数据库。您将通过命令行参数将要插入的数据传递给程序。

在你的文本编辑器中创建并打开insertData.js文件。

  1. nano insertData.js

 

在你的insertData.js文件中,添加以下代码以获取命令行参数:

sqlite_demo/insertData.js文件将用于插入数据到SQLite数据库。

const db = require("./db");

function insertRow() {
  const [name, color, weight] = process.argv.slice(2);
}

在第一行中,你导入了在上一步中在db.js文件中导出的数据库对象。在第二行中,你定义了函数insertRow(),你将很快用它来插入数据到表中。在这个函数中,process.argv以数组的形式返回所有的命令行参数。在索引0上的第一个元素包含Node的路径。在索引1上的第二个元素存储了JavaScript程序文件的名称。从索引2开始的所有后续元素包含你传递给文件的命令行参数。为了跳过前两个参数,你使用JavaScript的slice()方法来创建数组的一个浅拷贝,并从索引2开始返回数组的末尾处的元素。

接下来,将以下代码添加到数据库中以插入数据:

sqlite_demo/insertData.js文件演示了如何插入数据到SQLite数据库。

const db = require("./db");

function insertRow() {
  const [name, color, weight] = process.argv.slice(2);
  db.run(
    `INSERT INTO sharks (name, color, weight) VALUES (?, ?, ?)`,
    [name, color, weight],
    function (error) {
      if (error) {
        console.error(error.message);
      }
      console.log(`Inserted a row with the ID: ${this.lastID}`);
    }
  );
}

在前面的代码中,您调用了db.run()方法,它接受三个参数:SQL语句、一个数组和一个回调函数。第一个参数INSERT INTO sharks…是一个将数据插入数据库的SQL语句。在INSERT语句中的VALUES语句中,您传递一个用逗号分隔的值列表,这些值需要被插入。请注意,您传递的是?占位符,而不是直接传递值。这是为了避免SQL注入攻击。在执行过程中,SQLite会自动用db.run()方法的第二个参数中包含的命令行参数值替换占位符,该参数是一个包含值的数组。

最后,db.run() 方法的第三个参数是一个回调函数,在数据成功插入表格后运行。如果出现错误,错误消息会被记录在控制台中。如果插入成功,你将使用返回的 this.lastID 记录新插入行的 ID,同时打印出成功的信息。

现在,将高亮的行添加到调用insertRow()函数的位置。

sqlite_demo/insertData.js的中文释义
const db = require("./db");

function insertRow() {
  const [name, color, weight] = process.argv.slice(2);
  db.run(
    `INSERT INTO sharks (name, color, weight) VALUES (?, ?, ?)`,
    [name, color, weight],
    function (error) {
      if (error) {
        console.error(error.message);
      }
      console.log(`插入了一行数据,ID为: ${this.lastID}`);
    }
  );
}

insertRow();

保存并关闭您的文件,然后使用鲨鱼名称、颜色和重量参数运行文件。

  1. node insertData.js sammy blue 1900

 

输出表明已将行插入到具有主要ID 1的表中。

输出

插入了一行数据,ID为: 1

用不同的参数再次运行该命令。

  1. node insertData.js max white 2100

 

输出

插入了一行数据,ID为: 2

当您运行前面的命令时,将在sharks表中创建两行记录。

现在,你已经可以将数据插入到SQLite数据库中了,接下来你将从数据库中检索数据。

第四步 – 从SQLite数据库中检索数据

在这一步中,您将使用node-sqlite3模块从SQLite数据库中检索存储在sharks表中的所有数据,并将它们记录在控制台中。

首先,打开listData.js文件。

  1. nano listData.js

 

在你的sqlite_demo/listData.js文件中,添加以下代码以检索所有行:

这是文章《如何在Ubuntu 22.04上使用Node.js使用SQLite》的第12部分(共15部分)。

const db = require("./db");

function selectRows() {
  db.each(`SELECT * FROM sharks`, (error, row) => {
    if (error) {
      throw new Error(error.message);
    }
    console.log(row);
  });
}

首先,从db.js文件中导入数据库对象。其次,定义selectRows()函数,该函数从SQLite数据库中检索所有行。在函数内部,使用数据库对象db的each()方法逐行检索数据库中的行。each()方法接受两个参数:SQL语句和回调函数。

第一个参数SELECT返回sharks表中的所有行。第二个参数是一个回调函数,它在从数据库检索每一行时运行。在回调函数中,您检查是否有错误。如果有错误,您使用throw语句创建一个自定义错误。如果在检索过程中没有发生错误,则将数据记录在控制台中。

现在,将高亮显示的代码添加到调用selectRows()函数的位置。

sqlite_demo/listData.js 的中文翻译为:”SQLite演示/列表数据.js”。
const db = require("./db");

function selectRows() {
  db.each(`SELECT * FROM sharks`, (error, row) => {
    if (error) {
      throw new Error(error.message);
    }
    console.log(row);
  });
}

selectRows();

保存并退出你的文件,然后运行文件。

  1. node listData.js

 

执行该命令后,您会注意到以下显示的输出。

输出

{ ID: 1, name: ‘sammy’, color: ‘blue’, weight: 1900 } { ID: 2, name: ‘max’, color: ‘white’, weight: 2100 }

在前一步中,输出显示了您在鲨鱼表中插入的所有行。node-sqlite3模块将每个SQL结果转换为JavaScript对象。

现在你已经可以从SQLite数据库中检索数据,你将更新SQLite数据库中的数据。

第五步 —— 在SQLite数据库中修改数据

在这个步骤中,您将使用node-sqlite3模块更新SQLite数据库中的一行。为了做到这一点,您将向程序传递一个包含您想要修改的行的主要ID以及您想要将该行更新为的值的命令行参数。

在您的文本编辑器中创建并打开updateData.js文件。

  1. nano updateData.js

 

在您的updateData.js文件中,添加以下代码来更新一条记录:

文件路径:sqlite_demo/updateData.js

const db = require("./db");

function updateRow() {
  const [id, name] = process.argv.slice(2);
  db.run(
    `UPDATE sharks SET name = ? WHERE id = ?`,
    [name, id],
    function (error) {
      if (error) {
        console.error(error.message);
      }
      console.log(`${id} 已被更新`);
    }
  );
}

updateRow();

首先,你从db.js文件中导入数据库对象。其次,你定义了一个名为updateRow的函数,该函数用于更新数据库中的某一行。在函数内部,你将命令行参数解包到id和name变量中。id变量包含你想要更新的行的主键ID,而name变量则包含你想要将name字段更新为的值。

接下来,您使用以下参数调用db.run()函数:一个SQL语句和一个回调函数。UPDATE SQL语句将名称列从当前值更改为name变量中传递的值。WHERE子句确保只有ID变量中的行被更新。db.run()方法接受第二个参数,这是一个在值更新后运行的回调函数。

最后,你调用 updateRow() 函数。

当您完成了更改后,请保存并关闭文件。

用要更改的行的id和新名称运行updateData.js文件。

  1. node updateData.js 2 sonny

 

输出

第2行已更新

确认姓名已经更改

  1. node listData.js

 

当您运行该命令时,输出将类似于以下内容:

输出

{ ID: 1, name: ‘sammy’, color: ‘blue’, weight: 1900 } { ID: 2, name: ‘sonny‘, color: ‘white’, weight: 2100 }

输出表明,具有ID 2的行现在将”Sonny”作为其姓名字段的值。

通过以上操作,您已经可以在数据库中更新一行数据。接下来,您将从SQLite数据库中删除数据。

步骤6 — 删除 SQLite 数据库中的数据

在本节中,您将使用node-sqlite3从SQLite数据库中选择并删除表中的一行数据。

在文本编辑器中创建并打开 deleteData.js 文件。

  1. nano deleteData.js

 

在您的deleteData.js文件中,添加以下代码以删除数据库中的一行数据:

删除数据演示的JavaScript文件:sqlite_demo/deleteData.js。

在Node.js中删除SQLite数据

这是文章《如何在Ubuntu 22.04上使用Node.js使用SQLite》的第15部分(共15部分)。

const db = require("./db");

async function deleteRow() {
  const [id] = process.argv.slice(2);
  db.run(`DELETE FROM sharks WHERE id = ?`, [id], function (error) {
    if (error) {
      return console.error(error.message);
    }
    console.log(`ID为 ${id} 的行已被删除`);
  });
}

deleteRow();

首先,在db.js文件中导入数据库对象。其次,你定义了一个deleteRow()函数,该函数用于删除表sharks中的一行。在函数内部,你解构主键ID并将其存储在id变量中。接下来,你调用db.run()方法,该方法需要两个参数。第一个参数是SQL语句DELETE from sharks...,它用于删除表sharks中的一行。WHERE子句确保只删除id变量中包含的主键ID的行。第二个参数是一个回调函数,它会在行被删除后运行。如果删除成功,该函数会记录一条成功消息;否则,它会将错误记录在控制台中。

最后,你调用deleteRow()函数。

保存并关闭您的文件,然后运行以下命令:

  1. node deleteData.js 2
输出

ID为 2 的行已被删除

接下来,请确认该行已被删除:

  1. node listData.js

当你运行该命令时,你的输出将以类似以下的方式显示:

输出

{ ID: 1, name: 'sammy', color: 'blue', weight: 1900 }

ID为2的行已经不在结果中了。这证实了该行已被删除。

有了这个,你现在可以使用node-sqlite3模块在SQLite数据库中删除行了。

结论

在本文中,您创建了一个使用node-sqlite3模块连接到SQLite数据库并创建表的Node.js应用程序。接下来,您修改了该应用程序以在数据库中插入、检索和更新数据。最后,您修改了该应用程序以删除数据库中的数据。

想要深入了解node-sqlite3方法,请访问node-sqlite3维基页面。要了解SQLite,请查阅SQLite文档。如果你想了解SQLite与其他SQL数据库的比较,请参阅我们的教程:《SQLite vs MySQL vs PostgreSQL:关系数据库管理系统的比较》。要继续学习Node.js的旅程,请访问《如何在Node.js中编码》系列教程。

bannerAds