Поиск по сайту:

Как использовать SQLite с Node.js в Ubuntu 22.04


Автор выбрал программу Write for DOnations.

Введение

SQLite — это популярный механизм базы данных SQL с открытым исходным кодом для хранения данных. Он бессерверный, то есть для его работы не нужен сервер; вместо этого он читает и записывает данные в файл, который находится на диске компьютера. Кроме того, SQLite не требует никаких настроек; это делает его более портативным и популярным выбором для встраиваемых систем, настольных/мобильных приложений и прототипирования, среди прочего.

Чтобы использовать SQLite с Node.js, вам нужен клиент базы данных, который подключается к базе данных SQLite и отправляет операторы SQL из вашего приложения в базу данных для выполнения. Одним из популярных вариантов является пакет node-sqlite3, предоставляющий асинхронные привязки для SQLite 3.

В этом руководстве вы будете использовать node-sqlite3 для создания соединения с базой данных SQLite. Далее вы создадите приложение Node.js, которое создает таблицу и вставляет данные в базу данных. Наконец, вы измените приложение, чтобы использовать node-sqlite3 для извлечения, обновления и удаления данных из базы данных.

Предпосылки

Чтобы следовать этому руководству, вам понадобятся:

  • Среда разработки Node.js, настроенная в вашей системе. Если вы используете Ubuntu 22.04, установите последнюю версию Node.js, следуя варианту 3 нашего руководства «Как установить Node.js и создать локальную среду разработки».
  • SQLite3 установлен в вашей среде разработки. Следуйте шагу 1 нашего руководства «Как установить и использовать SQLite в Ubuntu 20.04». Базовые знания о том, как создавать таблицы и писать SQL-запросы для извлечения и изменения данных в таблице. Выполните шаги со 2 по 6 нашего руководства Как установить и использовать SQLite в Ubuntu 20.04.
  • Знакомство с тем, как написать программу Node.js, которую вы можете найти в нашем руководстве «Как написать и запустить свою первую программу в Node.js».

Шаг 1 — Настройка каталога проекта

На этом шаге вы создадите каталог проекта и загрузите node-sqlite3 в качестве зависимости.

Для начала создайте каталог с помощью команды mkdir. Для этого руководства он называется sqlite_demo, но вы можете заменить его на любое другое по вашему выбору:

  1. mkdir sqlite_demo

Затем перейдите во вновь созданный каталог с помощью команды cd:

  1. cd sqlite_demo

Инициализируйте каталог проекта как пакет npm с помощью команды npm:

  1. npm init -y

Команда создает файл package.json, содержащий важные метаданные для вашего проекта. Параметр -y указывает npm принять все значения по умолчанию.

После выполнения команды на экране отобразится следующий вывод:

Output
Wrote to /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: название вашего проекта.
  • версия: версия вашего проекта.
  • main: отправная точка вашего проекта.

Вы можете оставить параметры по умолчанию такими, какие они есть, но не стесняйтесь изменять значения свойств в соответствии со своими предпочтениями. Для получения дополнительной информации о свойствах обратитесь к документации package.json npm.

Затем установите пакет node-sqlite3 с помощью npm install:

  1. npm install sqlite3

После установки пакета вывод будет выглядеть следующим образом:

Output
added 104 packages, and audited 105 packages in 9s 5 packages are looking for funding run `npm fund` for details found 0 vulnerabilities

Теперь, когда вы установили node-sqlite3, вы будете использовать его для подключения к базе данных SQLite в следующем разделе.

Шаг 2 — Подключение к базе данных SQLite

На этом шаге вы будете использовать node-sqlite3 для подключения вашей программы Node.js к созданной вами базе данных SQLite, которая содержит различные акулы и их атрибуты. Чтобы установить соединение с базой данных, пакет node-sqlite3 предоставляет класс Database. При создании экземпляра класса создается файл базы данных SQLite на диске вашего компьютера и подключается к нему. Как только соединение будет установлено, вы создадите таблицу для своего приложения, которую в следующих разделах вы будете использовать для вставки, извлечения или обновления данных.

Используя nano или ваш любимый текстовый редактор, создайте и откройте файл db.js:

  1. nano db.js

В файле db.js добавьте следующий код, чтобы установить соединение с базой данных SQLite:

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("Connection with SQLite has been established");
  return db;
}

В первой строке вы импортируете модуль node-sqlite3 в файл программы. Во второй строке вы устанавливаете переменную filepath с путем, по которому вы хотите, чтобы ваша база данных SQLite находилась, и именем файла базы данных, в данном случае это fish.db.

В следующей строке вы определяете функцию createDbConnection(), которая устанавливает соединение с базой данных SQLite. Внутри функции вы создаете экземпляр класса sqlite3.Database() с ключевым словом new. Класс принимает два аргумента: filepath и обратный вызов.

Первый аргумент, filepath, принимает имя и путь к базе данных SQLite, которой здесь является ./fish.db. Второй аргумент — это обратный вызов, который запускается после создания базы данных и установления соединения с базой данных. Обратный вызов принимает параметр error, который устанавливается в объект error, если при попытке установить соединение с базой данных возникает ошибка. В обратном вызове вы используете оператор if, чтобы проверить, есть ли ошибка. Если условие истинно, вы используете метод console.error() для регистрации сообщения об ошибке.

Теперь, когда вы создаете экземпляр с помощью класса sqlite3.Database(), он создает файл базы данных SQLite в каталоге вашего проекта и возвращает объект базы данных, который хранится в db переменная. Объект базы данных предоставляет методы, которые можно использовать для передачи операторов SQL, создающих таблицы и вставляющих, извлекающих или изменяющих данные.

Наконец, вы вызываете console.log(), чтобы зарегистрировать сообщение об успешном выполнении и вернуть объект базы данных в переменной db.

Затем добавьте выделенный код для создания функции, создающей таблицу:

...
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() вы вызываете метод exec() объекта базы данных db, который отправляет данный оператор SQL в базу данных для быть казненным. Метод exec() используется только для запросов, которые не возвращают строки результатов.

Оператор SQL CREATE TABLE sharks..., переданный методу exec(), создает таблицу sharks со следующими полями:

  • ID: сохраняет значения типа данных INTEGER. Ограничение PRIMARY KEY назначает столбец первичным ключом, а AUTOINCREMENT указывает SQLite автоматически увеличивать значения столбца ID для каждой строки в таблице.
  • name: детализирует имя акулы, используя тип данных VARCHAR, содержащий не более 50 символов. Ограничение NOT NULL гарантирует, что поле не может хранить значения NULL.
  • color: представляет цвет акулы с использованием типа данных VARCHAR с максимальным количеством символов 50. Ограничение NOT NULL означает, что поле не должно принимать значения NULL.
  • weight: сохраняет вес акулы в килограммах с использованием типа данных INTEGER и использует ограничение NOT NULL, чтобы гарантировать, что значения NULL не допускаются.

В тот же файл db.js добавьте выделенный код для вызова функции createTable():

function createDbConnection() {
  const db = new sqlite3.Database(filepath, (error) => {
    if (error) {
      return console.error(error.message);
    }
    createTable(db);
  });
  console.log("Connection with SQLite has been established");
  return db;
}


function createTable(db) {
    ...
}

При выполнении обратного вызова вы вызываете функцию createTable() с объектом базы данных db в качестве аргумента.

Затем добавьте следующую строку для вызова функции createDbConnection():

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


function createTable(db) {
    ...
}

module.exports = createDbConnection();

В предыдущем коде вы вызываете функцию createDbConnection(), которая устанавливает соединение с базой данных и возвращает объект базы данных. Затем вы используете module.exports для экспорта объекта базы данных, чтобы вы могли ссылаться на него в других файлах.

Теперь ваш файл будет содержать следующее:

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("Connection with SQLite has been established");
  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 для подтверждения имени файла.

Запустите файл db.js с помощью команды node:

  1. node db.js

Вывод покажет, что соединение с базой данных установлено успешно:

Output
Connection with SQLite has been established

Затем проверьте, был ли создан файл базы данных fish.db с помощью команды ls:

  1. ls
Output
db.js fish.db node_modules package-lock.json package.json

Появление файла базы данных fish.db в выходных данных подтверждает, что база данных была создана успешно.

Теперь каждый раз, когда вы запускаете файл db.js, он будет вызывать функцию createTable() для создания таблицы в базе данных. Попытка создать уже существующую таблицу приводит к тому, что SQLite выдает ошибку. Чтобы увидеть это, повторно запустите файл db.js с помощью команды node:

  1. node db.js

На этот раз вы получите сообщение об ошибке, показанное в следующем выводе:

Output
Connection with SQLite has been established undefined:0 [Error: SQLITE_ERROR: table sharks already exists Emitted 'error' event on Database instance at: ] { errno: 1, code: 'SQLITE_ERROR' } Node.js v17.6.0

Сообщение об ошибке указывает, что таблица sharks уже существует. Это связано с тем, что при первом запуске команды node создается база данных fish, а также таблица sharks. При повторном запуске команды функция createTable() запускается снова во второй раз, что вызывает ошибку, поскольку таблица уже существует.

Эта ошибка также будет вызвана в любое время, когда вы захотите использовать методы объекта базы данных для управления базой данных в других файлах. Например, на следующем шаге вы создадите файл, который вставляет данные в базу данных. Чтобы использовать объект базы данных, вы импортируете файл db.js и вызываете соответствующий метод для вставки данных в базу данных. Когда вы запускаете файл, он, в свою очередь, запускает db.js, что вызывает ту же ошибку.

Чтобы исправить это, вы будете использовать метод existsSync() модуля fs для проверки существования файла базы данных 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("Connection with SQLite has been established");
    return db;
  }
}

Сначала вы импортируете модуль fs, используемый для взаимодействия с файловой системой. Во-вторых, в добавленном операторе if вы вызываете метод fs.existSync() для проверки существования файла в заданном аргументе, который является файлом базы данных ./fish.db здесь. Если файл существует, вы вызываете sqlite3.Database() с путем к файлу базы данных и опускаете обратный вызов. Однако, если файл не существует, вы создаете экземпляр базы данных и вызываете функцию createTable() в обратном вызове, чтобы создать таблицу в базе данных.

На этом этапе полный файл теперь будет отображаться следующим образом:

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("Connection with SQLite has been established");
    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 не выдает ошибку при многократном запуске, удалите файл fish.db с помощью rm команда, чтобы начать заново:

  1. rm fish.db

Запустите файл db.js:

  1. node db.js
Output
Connection with SQLite has been established

Теперь убедитесь, что db.js подключается к базе данных и не пытается снова создать таблицу для всех последующих повторных запусков файла db.js, запустив файл снова:

  1. node db.js

Теперь вы заметите, что больше не будете получать ошибку.

Теперь, когда вы установили соединение с базой данных SQLite и создали таблицу, вы вставите данные в базу данных.

Шаг 3 — Вставка данных в базу данных SQLite

На этом шаге вы создадите функцию, которая вставляет данные в базу данных SQLite с помощью модуля node-sqlite3. Вы передадите программе данные, которые хотите вставить, в качестве аргументов командной строки.

Создайте и откройте файл insertData.js в текстовом редакторе:

  1. nano insertData.js

В файле insertData.js добавьте следующий код для получения аргументов командной строки:

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 в конец массива.

Затем добавьте выделенный код для вставки данных в базу данных:

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, которая вставляет данные в базу данных. Оператор VALUES в операторе INSERT принимает список значений, разделенных запятыми, которые необходимо вставить. Обратите внимание, что вы передаете заполнители ? вместо того, чтобы передавать значения напрямую. Это сделано для того, чтобы избежать атак путем внедрения SQL-кода. Во время выполнения SQLite автоматически заменит заполнители значениями, переданными во втором аргументе метода db.run(), который представляет собой массив, содержащий значения аргументов командной строки.

Наконец, третий аргумент метода db.run() — это обратный вызов, который запускается после успешной вставки данных в таблицу. В случае ошибки сообщение об ошибке регистрируется в консоли. Если вставка прошла успешно, вы регистрируете сообщение об успешном выполнении с идентификатором вновь вставленной строки, возвращенным this.lastID.

Теперь добавьте выделенную строку для вызова функции insertRow():

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}`);
    }
  );
}

insertRow();

Сохраните и закройте файл, затем запустите файл с аргументами имени, цвета и веса акулы:

  1. node insertData.js sammy blue 1900

Вывод показывает, что строка была вставлена в таблицу с основным идентификатором 1:

Output
Inserted a row with the ID: 1

Запустите команду еще раз с другими аргументами:

  1. node insertData.js max white 2100
Output
Inserted a row with the ID: 2

При выполнении предыдущих команд в таблице sharks будут созданы две строки.

Теперь, когда вы можете вставлять данные в базу данных SQLite, теперь вы будете извлекать данные из базы данных.

Шаг 4 — Извлечение данных из базы данных SQLite

На этом шаге вы будете использовать модуль node-sqlite3 для извлечения всех данных, хранящихся в таблице sharks в базе данных SQLite, и занести их в консоль.

Сначала откройте файл listData.js:

  1. nano listData.js

В файле listData.js добавьте следующий код для получения всех строк:

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. Внутри функции вы используете метод each() объекта базы данных db для извлечения строк из базы данных одну за другой. Метод each() принимает два аргумента: оператор SQL и обратный вызов.

Первый аргумент SELECT возвращает все строки в таблице sharks. Второй аргумент — это обратный вызов, который запускается каждый раз, когда строка извлекается из базы данных. В обратном вызове вы проверяете наличие ошибки. Если есть ошибка, вы используете оператор throw для создания пользовательской ошибки. Если во время извлечения ошибок не возникло, данные записываются в консоль.

Теперь добавьте выделенный код для вызова функции selectRows():

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

После запуска команды вы увидите вывод, который выглядит следующим образом:

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

На выходе отображаются все строки, которые вы вставили в таблицу sharks на предыдущем шаге. Модуль node-sqlite3 преобразует каждый результат SQL в объект JavaScript.

Теперь, когда вы можете получать данные из базы данных SQLite, вы обновите данные в базе данных SQLite.

Шаг 5 — Изменение данных в базе данных SQLite

На этом шаге вы будете использовать модуль node-sqlite3 для обновления строки в базе данных SQLite. Для этого вы передадите программе аргумент командной строки, содержащий первичный идентификатор строки, которую вы хотите изменить, а также значение, до которого вы хотите обновить строку.

Создайте и откройте файл updateData.js в текстовом редакторе:

  1. nano updateData.js

В файле 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(`Row ${id} has been updated`);
    }
  );
}

updateRow();

Сначала вы импортируете объект базы данных из файла db.js. Во-вторых, вы определяете функцию updateRow, которая обновляет строку в базе данных. Внутри функции вы распаковываете аргументы командной строки в переменные id и name. Переменная id содержит основной идентификатор строки, которую вы хотите обновить, а name содержит значение, которое должно отображаться в поле имени.

Затем вы вызываете функцию db.run() со следующими аргументами: оператор SQL и обратный вызов. Оператор SQL UPDATE изменяет столбец name с текущего значения на значение, переданное в переменной name. Предложение WHERE гарантирует, что будет обновлена только строка с идентификатором в переменной id. Метод db.run() принимает второй аргумент, представляющий собой обратный вызов, который запускается после обновления значения.

Наконец, вы вызываете функцию updateRow().

Сохраните и закройте файл, когда закончите вносить изменения.

Запустите файл updateData.js с id строки, которую вы хотите изменить, и новым названием:

  1. node updateData.js 2 sonny
Output
Row 2 has been updated

Убедитесь, что имя было изменено:

  1. node listData.js

Когда вы запустите команду, ваш вывод будет выглядеть следующим образом:

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

Вывод показывает, что строка с идентификатором 2 теперь имеет sonny в качестве значения поля name.

Теперь вы можете обновить строку в базе данных. Далее вы удалите данные из базы данных SQLite.

Шаг 6 — Удаление данных в базе данных SQLite

В этом разделе вы будете использовать node-sqlite3 для выбора и удаления строки из таблицы в базе данных SQLite.

Создайте и откройте файл deleteData.js в текстовом редакторе:

  1. nano deleteData.js

В файл deleteData.js добавьте следующий код, чтобы удалить строку в базе данных:

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(`Row with the ID ${id} has been deleted`);
  });
}

deleteRow();

Сначала вы импортируете объект базы данных в файл db.js. Во-вторых, вы определяете deleteRow(), который удаляет строку в таблице sharks. Внутри функции вы распаковываете идентификатор первичного ключа и сохраняете его в переменной id. Затем вы вызываете db.run(), который принимает два аргумента. Первый аргумент — это оператор SQL DELETE from sharks..., который удаляет строку в таблице sharks. Предложение WHERE гарантирует, что будет удалена только строка с идентификатором в переменной id. Второй аргумент — это обратный вызов, который запускается после удаления строки. В случае успеха функция регистрирует сообщение об успехе; в противном случае он регистрирует ошибку в консоли.

Наконец, вы вызываете функцию deleteRow().

Сохраните и закройте файл, затем выполните следующую команду:

  1. node deleteData.js 2
Output
Row with the ID 2 has been deleted

Затем подтвердите, что строка была удалена:

  1. node listData.js

Когда вы запустите команду, ваш вывод будет выглядеть примерно так:

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

Строки с идентификатором 2 больше нет в результатах. Это подтверждает, что строка была удалена.

При этом теперь вы можете удалять строки в базе данных SQLite с помощью модуля node-sqlite3.

Заключение

В этой статье вы создали приложение Node.js, которое использует модуль node-sqlite3 для подключения и создания таблицы в базе данных SQLite. Затем вы изменили приложение для вставки, извлечения и обновления данных в базе данных. Наконец, вы изменили приложение, чтобы удалить данные из базы данных.

Дополнительные сведения о методах node-sqlite3 см. в серии статей How To Code in Node.js.