<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>SQLite on Dev TLDRLSS</title>
        <link>https://dev.tldrlss.com/ru/tags/sqlite/</link>
        <description>Recent content in SQLite on Dev TLDRLSS</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>ru</language>
        <lastBuildDate>Tue, 19 May 2026 18:10:00 +0800</lastBuildDate><atom:link href="https://dev.tldrlss.com/ru/tags/sqlite/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Не позволяйте непринужденности SQLite обмануть вас! В чем подвох динамической типизации? Почему ALTER TABLE неполноценен? Как построить архитектуру оборонительного программирования на Node.js для безболезненного обновления схем?</title>
        <link>https://dev.tldrlss.com/ru/article/2026/05/sqlite-pitfall-intro/</link>
        <pubDate>Tue, 19 May 2026 18:10:00 +0800</pubDate>
        
        <guid>https://dev.tldrlss.com/ru/article/2026/05/sqlite-pitfall-intro/</guid>
        <description>&lt;img src="https://dev.tldrlss.com/global-assets/images/database/sqlite-type-pitfall-1.jpg" alt="Featured image of post Не позволяйте непринужденности SQLite обмануть вас! В чем подвох динамической типизации? Почему ALTER TABLE неполноценен? Как построить архитектуру оборонительного программирования на Node.js для безболезненного обновления схем?" /&gt;&lt;p&gt;Представьте себе мусорный бак для вторсырья, на который вы четко наклеили этикетку с надписью «Только пластиковые бутылки», но когда кто-то бросает туда кусок бумаги, он молча принимает его без единого слова протеста?&lt;/p&gt;
&lt;p&gt;Это тот самый леденящий душу опыт, с которым сталкиваются разработчики, когда впервые знакомятся с системой типов &lt;code&gt;SQLite&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Если вы привыкли к строгому стилю таможенника &lt;code&gt;PostgreSQL&lt;/code&gt; (где некорректные типы данных немедленно депортируются обратно), непринужденность &lt;code&gt;SQLite&lt;/code&gt; может заставить вас усомниться в своей жизни.&lt;/p&gt;
&lt;p&gt;Что еще более пугающе, когда вы захотите &lt;strong&gt;изменить структуру таблицы&lt;/strong&gt;, база данных скажет вам:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;«Таблицу нельзя изменить напрямую. Пожалуйста, постройте новый дом, перевезите туда мебель, а затем взорвите старый дом».&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;под-капотом-у-sqlite-всего-5-классов-хранения&#34;&gt;Под капотом у SQLite всего 5 классов хранения
&lt;/h2&gt;&lt;p&gt;Независимо от того, какие изысканные названия типов вы объявляете в &lt;code&gt;CREATE TABLE&lt;/code&gt; (&lt;code&gt;VARCHAR(255)&lt;/code&gt;, &lt;code&gt;BIGINT&lt;/code&gt;, &lt;code&gt;DECIMAL&lt;/code&gt;), &lt;code&gt;SQLite&lt;/code&gt; под капотом распознает только эти &lt;strong&gt;5 классов хранения&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Класс хранения&lt;/th&gt;
          &lt;th&gt;Описание&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;NULL&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Пустое значение&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;INTEGER&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Целое число (автоматически занимает от 1 до 8 байт в зависимости от величины значения)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;REAL&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Число с плавающей запятой (фиксированные 8 байт)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;TEXT&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Текстовая строка (по умолчанию кодировка UTF-8)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;BLOB&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Большой двоичный объект (хранится точно в том виде, в каком был введен)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Типы, которые вы устанавливаете для столбцов, &lt;strong&gt;являются лишь «рекомендациями» для &lt;code&gt;SQLite&lt;/code&gt;, а не «обязательными правилами»&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Это называется &lt;strong&gt;«Type Affinity» (Родство типов)&lt;/strong&gt;. &lt;code&gt;SQLite&lt;/code&gt; попытается преобразовать ваши данные в рекомендуемый тип, но если не сможет, то просто вставит исходные данные в любом случае без вызова ошибки.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Вы можете объявить столбец &lt;code&gt;age INTEGER&lt;/code&gt; в &lt;code&gt;SQLite&lt;/code&gt; и затем вставить строку &lt;code&gt;&#39;вечно восемнадцать&#39;&lt;/code&gt;; база данных с радостью примет ее.&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;три-ловушки-типов-в-которые-легче-всего-угодить&#34;&gt;Три ловушки типов, в которые легче всего угодить
&lt;/h2&gt;&lt;h3 id=&#34;ловушка-1-отсутствие-встроенного-boolean&#34;&gt;Ловушка 1: Отсутствие встроенного Boolean
&lt;/h3&gt;&lt;p&gt;В &lt;code&gt;SQLite&lt;/code&gt; &lt;strong&gt;нет типа данных boolean&lt;/strong&gt;. Значения &lt;code&gt;True&lt;/code&gt; и &lt;code&gt;False&lt;/code&gt; могут быть представлены только целыми числами &lt;code&gt;1&lt;/code&gt; и &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Когда вы извлекаете данные из &lt;code&gt;SQLite&lt;/code&gt; с помощью &lt;code&gt;Node.js&lt;/code&gt;, вы получаете число &lt;code&gt;1&lt;/code&gt; или &lt;code&gt;0&lt;/code&gt;, а не &lt;code&gt;true&lt;/code&gt; или &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Если вы напрямую выполните проверку вида &lt;code&gt;if (user.is_admin === true)&lt;/code&gt;, она никогда не будет истинной.&lt;/p&gt;
&lt;h3 id=&#34;ловушка-2-отсутствие-типа-datetime&#34;&gt;Ловушка 2: Отсутствие типа Date/Time
&lt;/h3&gt;&lt;p&gt;В &lt;code&gt;SQLite&lt;/code&gt; &lt;strong&gt;нет типа данных даты/времени&lt;/strong&gt;. Вы можете хранить время только следующими способами:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Способ хранения&lt;/th&gt;
          &lt;th&gt;Пример&lt;/th&gt;
          &lt;th&gt;Плюсы и минусы&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;TEXT (строка ISO-8601)&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&#39;2026-05-19T18:00:00Z&#39;&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Наиболее рекомендуемый&lt;/strong&gt;, высокая читаемость, бесшовное преобразование при переходе на PostgreSQL в будущем&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;INTEGER (Unix Timestamp)&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;1747656000&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Малый размер, но не читается человеком&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Никогда не храните даты в произвольных пользовательских форматах, таких как &lt;code&gt;19.05.2026 18:00&lt;/code&gt;, иначе будущая миграция данных обернется катастрофой.&lt;/p&gt;
&lt;h3 id=&#34;ловушка-3-вставка-строки-в-столбец-integer-не-вызовет-ошибку&#34;&gt;Ловушка 3: Вставка строки в столбец Integer не вызовет ошибку
&lt;/h3&gt;&lt;p&gt;В &lt;code&gt;PostgreSQL&lt;/code&gt; вставка строки в столбец &lt;code&gt;INTEGER&lt;/code&gt; сразу же вызывает ошибку. Но &lt;code&gt;SQLite&lt;/code&gt; лишь попытается тихо преобразовать ее, а в случае неудачи примет как есть.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Это означает, что &lt;strong&gt;грязные данные могут незаметно просочиться в вашу базу данных&lt;/strong&gt;, пока в один прекрасный день ваша программа не упадет из-за получения неожиданного типа. Только тогда вы обнаружите проблему.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;оборонительное-программирование-отношение-к-непринужденной-базе-данных-со-строгой-позиции&#34;&gt;Оборонительное программирование: Отношение к непринужденной базе данных со строгой позиции
&lt;/h2&gt;&lt;p&gt;Столкнувшись с непринужденностью &lt;code&gt;SQLite&lt;/code&gt;, вы должны выстроить &lt;strong&gt;строгие механизмы защиты&lt;/strong&gt; при разработке на &lt;code&gt;Node.js&lt;/code&gt;:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Уровень защиты&lt;/th&gt;
          &lt;th&gt;Инструмент&lt;/th&gt;
          &lt;th&gt;Роль&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Страж времени компиляции&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Перехват некорректных типов на этапе написания кода&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Валидация на входе API&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Zod&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Строгая проверка входящих данных (гарантия того, что age всегда является числом)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Неявное преобразование типов&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Prisma / Drizzle ORM&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Автоматическая обработка различий типов между SQLite и PostgreSQL&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;Перенос &lt;strong&gt;«вышибалы валидации данных»&lt;/strong&gt; с уровня базы данных на уровень приложения &lt;code&gt;Node.js&lt;/code&gt; — ключевая стратегия для использования преимуществ высокой скорости разработки SQLite при обеспечении будущей масштабируемости.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;При использовании ORM, если вы объявите &lt;code&gt;type: &#39;boolean&#39;&lt;/code&gt; в своем коде, ORM автоматически преобразует его в &lt;code&gt;1/0&lt;/code&gt; при сохранении в &lt;code&gt;SQLite&lt;/code&gt; и обратно в &lt;code&gt;true/false&lt;/code&gt; при чтении, идеально скрывая различия базовых типов.&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;alter-table-неполноценен-что-можно-и-что-нельзя-изменять&#34;&gt;ALTER TABLE неполноценен: Что можно и что нельзя изменять
&lt;/h2&gt;&lt;p&gt;Поддержка изменения структуры таблиц в &lt;code&gt;SQLite&lt;/code&gt; крайне ограничена:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Операция&lt;/th&gt;
          &lt;th&gt;Поддерживается&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Добавление столбца (&lt;code&gt;ADD COLUMN&lt;/code&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Да&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Переименование столбца (&lt;code&gt;RENAME COLUMN&lt;/code&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Да&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Удаление столбца (&lt;code&gt;DROP COLUMN&lt;/code&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Да&lt;/strong&gt; (в более новых версиях)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Переименование таблицы (&lt;code&gt;RENAME TO&lt;/code&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Да&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Изменение типа столбца&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Нет&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Добавление/удаление ограничений &lt;code&gt;UNIQUE&lt;/code&gt;, &lt;code&gt;NOT NULL&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Нет&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Изменение первичного ключа (Primary Key)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Нет&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Изменение внешнего ключа (Foreign Key)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Нет&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;Как только вам понадобится выполнить любое из «неподдерживаемых» изменений, &lt;code&gt;SQLite&lt;/code&gt; потребует от вас выполнения стратегии &lt;strong&gt;«пересоздания и переноса»&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;четыре-шага-пересоздания-и-переноса-метод-обновления-таблиц-sqlite&#34;&gt;Четыре шага пересоздания и переноса: Метод обновления таблиц SQLite
&lt;/h2&gt;&lt;p&gt;Поскольку прямое изменение невозможно, стандартная процедура, рекомендуемая официальной документацией, выглядит так: &lt;strong&gt;построить новый дом, перевезти мебель, взорвать старый дом и повесить новую табличку на дверь&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Шаг&lt;/th&gt;
          &lt;th&gt;Действие&lt;/th&gt;
          &lt;th&gt;Описание&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;Создание новой таблицы&lt;/td&gt;
          &lt;td&gt;Создать &lt;code&gt;CREATE TABLE users_new (...)&lt;/code&gt; с правильной структурой&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2&lt;/td&gt;
          &lt;td&gt;Копирование данных&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;INSERT INTO users_new SELECT ... FROM users&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;Удаление старой таблицы&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;DROP TABLE users&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;4&lt;/td&gt;
          &lt;td&gt;Переименование таблицы&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;ALTER TABLE users_new RENAME TO users&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Эти четыре шага должны быть выполнены &lt;strong&gt;на одном дыхании&lt;/strong&gt;; любое отключение электричества или сбой приложения на полпути приведет к потере данных.&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;гарантия-обновления-без-потери-данных-две-линии-безопасности&#34;&gt;Гарантия обновления без потери данных: Две линии безопасности
&lt;/h2&gt;&lt;h3 id=&#34;линия-безопасности-1-физическая-защита-прямое-копирование-файла&#34;&gt;Линия безопасности 1: Физическая защита, прямое копирование файла
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;SQLite&lt;/code&gt; по сути представляет собой один-единственный файл. Перед выполнением любых изменений схемы просто скопируйте файл &lt;code&gt;.db&lt;/code&gt; в качестве резервной копии.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;fs&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;fs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;copyFileSync&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;my_project.db&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;my_project_backup.db&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Если что-то пойдет не так, перезапись файла восстановит всё в мгновение ока. Это преимущество, которое не могут предоставить другие крупные базы данных.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;линия-безопасности-2-обертка-в-transaction-машина-времени-базы-данных&#34;&gt;Линия безопасности 2: Обертка в Transaction, машина времени базы данных
&lt;/h3&gt;&lt;p&gt;Оберните все шаги миграции в одну транзакцию &lt;code&gt;Transaction&lt;/code&gt;; если какой-либо шаг завершится неудачей, весь процесс будет &lt;strong&gt;автоматически отменен (Rollback)&lt;/strong&gt;, как будто ничего и не было.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Database&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;better-sqlite3&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Database&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;my_project.db&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;migrateData&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;transaction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    CREATE TABLE users_new (
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      id INTEGER PRIMARY KEY AUTOINCREMENT,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      name TEXT NOT NULL,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      age INTEGER NOT NULL DEFAULT 18
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;  `&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    INSERT INTO users_new (id, name, age)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    SELECT id, name, COALESCE(age, 18) FROM users
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;  `&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;DROP TABLE users&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;ALTER TABLE users_new RENAME TO users&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;migrateData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Обновление таблицы завершено&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;catch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Ошибка обновления, данные безопасно восстановлены:&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;«Резервная копия файла + привязка транзакции»&lt;/strong&gt; — это подушка безопасности для миграции вашей базы данных.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;контролируйте-непринужденную-sqlite-со-строгой-позиции&#34;&gt;Контролируйте непринужденную SQLite со строгой позиции
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;Укротите непринужденную &lt;code&gt;SQLite&lt;/code&gt; с помощью &lt;strong&gt;строгой архитектуры на уровне приложения&lt;/strong&gt;, чтобы наслаждаться молниеносной скоростью разработки и одновременно избегать технического долга в будущем.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Система типов SQLite очень непринужденная, а &lt;code&gt;ALTER TABLE&lt;/code&gt; имеет множество ограничений.&lt;/p&gt;
&lt;p&gt;Однако, пока вы добросовестно используете &lt;strong&gt;проверку типов TypeScript + валидацию Zod + ORM-абстракцию&lt;/strong&gt; на стороне &lt;code&gt;Node.js&lt;/code&gt; в сочетании со стратегией безопасности &lt;strong&gt;физического резервного копирования + транзакций&lt;/strong&gt;, вы можете спокойно наслаждаться высокой эффективностью разработки, которую предлагает &lt;code&gt;SQLite&lt;/code&gt;, одновременно подготавливая путь к гладкому переходу на &lt;code&gt;PostgreSQL&lt;/code&gt; в будущем.&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;reference&#34;&gt;Reference
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://sqlite.org/datatype3.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Datatypes In SQLite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.runoob.com/sqlite/sqlite-data-types.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQLite 数据类型 | 菜鸟教程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.sqlite.org/lang_transaction.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Transaction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://sqlite.org/lang.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Query Language Understood by SQLite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/SQLite&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQLite - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Не используйте PostgreSQL для всего! В чем преимущества встроенной архитектуры и нулевой конфигурации SQLite? Где пределы SQLite? Когда выбирать SQLite, а когда PostgreSQL?</title>
        <link>https://dev.tldrlss.com/ru/article/2026/05/sqlite-intro/</link>
        <pubDate>Tue, 19 May 2026 18:00:00 +0800</pubDate>
        
        <guid>https://dev.tldrlss.com/ru/article/2026/05/sqlite-intro/</guid>
        <description>&lt;img src="https://dev.tldrlss.com/global-assets/images/database/sqlite-vs-postgresql-choice-2.jpg" alt="Featured image of post Не используйте PostgreSQL для всего! В чем преимущества встроенной архитектуры и нулевой конфигурации SQLite? Где пределы SQLite? Когда выбирать SQLite, а когда PostgreSQL?" /&gt;&lt;p&gt;Задумывались ли вы когда-нибудь о том, что браузер, который вы открываете каждый день, приложение для общения на телефоне и даже инструмент для заметок на компьютере скрывают одну и ту же легковесную базу данных?&lt;/p&gt;
&lt;p&gt;Она не требует установки серверного ПО, не нуждается в настройке учетной записи или пароля и даже не требует подключения к Интернету. Это просто &lt;strong&gt;файл&lt;/strong&gt;, который тихо лежит на вашем жестком диске, готовый служить вам в любое время.&lt;/p&gt;
&lt;p&gt;Это скромное существование и есть &lt;code&gt;SQLite&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;что-такое-sqlite-самая-распространенная-база-данных-в-мире&#34;&gt;Что такое SQLite? Самая распространенная база данных в мире
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;SQLite&lt;/code&gt; — это &lt;strong&gt;встроенный движок реляционной базы данных&lt;/strong&gt;, написанный на C.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;У нее &lt;strong&gt;нет независимого серверного процесса&lt;/strong&gt;, она встраивается непосредственно в ваше приложение для работы.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Это совершенно отличается от привычных вам &lt;code&gt;PostgreSQL&lt;/code&gt; или &lt;code&gt;MySQL&lt;/code&gt;. Традиционные базы данных — это &lt;strong&gt;независимые серверы&lt;/strong&gt;, которые работают отдельно, и ваша программа должна &amp;ldquo;общаться&amp;rdquo; с ними по &lt;strong&gt;сетевому протоколу (TCP/IP)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;SQLite&lt;/code&gt; устроена иначе; это просто блок кода, работающий прямо внутри вашего приложения, который читает и записывает файл &lt;code&gt;.db&lt;/code&gt; на вашем жестком диске.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Параметр сравнения&lt;/th&gt;
          &lt;th&gt;SQLite (Встроенная)&lt;/th&gt;
          &lt;th&gt;PostgreSQL (Клиент-Сервер)&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Режим работы&lt;/td&gt;
          &lt;td&gt;Встроена прямо в приложение, без отдельного сервера&lt;/td&gt;
          &lt;td&gt;Независимый серверный процесс, через сетевое подключение&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Конфигурация&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Нулевая конфигурация&lt;/strong&gt;, без установки и учетных записей&lt;/td&gt;
          &lt;td&gt;Требует установки, настройки учетной записи/пароля и файрвола&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Хранение данных&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Один кроссплатформенный файл&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Множество файлов в директории сервера&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Резервное копирование&lt;/td&gt;
          &lt;td&gt;Прямое копирование этого файла&lt;/td&gt;
          &lt;td&gt;Требует специальных инструментов, таких как pg_dump&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Именно благодаря этой особенности &lt;strong&gt;&amp;ldquo;подключи и работай&amp;rdquo;&lt;/strong&gt; &lt;code&gt;SQLite&lt;/code&gt; стала самым распространенным движком баз данных в мире.&lt;/p&gt;
&lt;p&gt;От операционных систем Android и iOS, браузеров Chrome и Firefox до Adobe Lightroom, WhatsApp и даже авиационной системы Airbus A350 — она присутствует везде.&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;использование-sqlite-in-nodejs&#34;&gt;Использование SQLite in Node.js
&lt;/h2&gt;&lt;p&gt;Если вы являетесь Node.js-разработчиком, использовать &lt;code&gt;SQLite&lt;/code&gt; чрезвычайно просто. Вам не нужно устанавливать серверное ПО базы данных на свой компьютер, достаточно просто установить npm-пакет для начала работы.&lt;/p&gt;
&lt;p&gt;Наиболее часто используемые варианты в индустрии сегодня:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Название пакета&lt;/th&gt;
          &lt;th&gt;Особенности&lt;/th&gt;
          &lt;th&gt;Рекомендуемый сценарий&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;sqlite3&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Самый старый, поддерживает асинхронные API&lt;/td&gt;
          &lt;td&gt;Когда нужно обрабатывать много асинхронных задач одновременно&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;better-sqlite3&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Отличная производительность&lt;/strong&gt;, интуитивный API, очень быстрый&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;Главная рекомендация&lt;/strong&gt; для эффективности разработки и скорости работы&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Создание базы данных и выполнение запросов с помощью &lt;code&gt;better-sqlite3&lt;/code&gt; занимает меньше пяти минут:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Database&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;better-sqlite3&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Database&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;my_project.db&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER)&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;insert&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;INSERT INTO users (name, age) VALUES (?, ?)&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;insert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;SELECT * FROM users WHERE name = ?&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// { name: &amp;#39;John&amp;#39;, age: 25 }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Если файл не существует, &lt;code&gt;better-sqlite3&lt;/code&gt; &lt;strong&gt;создаст его автоматически&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;sqlite-поддерживает-более-мощный-sql-синтаксис-чем-вы-думаете&#34;&gt;SQLite поддерживает более мощный SQL-синтаксис, чем вы думаете
&lt;/h2&gt;&lt;p&gt;Многие думают, что &lt;code&gt;SQLite&lt;/code&gt; очень проста, но она поддерживает подавляющее большинство стандартов SQL-синтаксиса, включая множество продвинутых функций:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Категория синтаксиса&lt;/th&gt;
          &lt;th&gt;Поддерживаемые элементы&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Базовые операции&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;SELECT&lt;/code&gt;, &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Определение данных&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;CREATE TABLE&lt;/code&gt;, &lt;code&gt;CREATE INDEX&lt;/code&gt;, &lt;code&gt;CREATE VIEW&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Сложные запросы&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;WITH&lt;/code&gt; (рекурсивные CTE), оконные функции (Window Functions)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Обработка конфликтов&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;UPSERT&lt;/code&gt; (&lt;code&gt;INSERT ... ON CONFLICT DO UPDATE&lt;/code&gt;)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Обработка JSON&lt;/td&gt;
          &lt;td&gt;Встроенные функции, такие как &lt;code&gt;json_extract&lt;/code&gt;, &lt;code&gt;json_array&lt;/code&gt;, &lt;code&gt;json_object&lt;/code&gt; и др.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Управление транзакциями&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;BEGIN&lt;/code&gt;, &lt;code&gt;COMMIT&lt;/code&gt;, &lt;code&gt;ROLLBACK&lt;/code&gt;, &lt;code&gt;SAVEPOINT&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Запросы слияния&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;INNER JOIN&lt;/code&gt;, &lt;code&gt;LEFT JOIN&lt;/code&gt;, &lt;code&gt;RIGHT JOIN&lt;/code&gt; и &lt;code&gt;FULL OUTER JOIN&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Основная философия SQLite — &amp;ldquo;мало и изящно&amp;rdquo;&lt;/strong&gt;, она поддерживает большинство возможностей SQL, необходимых каждый день, оставаясь при этом невероятно легкой.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;где-пределы-sqlite&#34;&gt;Где пределы SQLite?
&lt;/h2&gt;&lt;p&gt;Легкость имеет свою цену. Если сравнить &lt;code&gt;SQLite&lt;/code&gt; со &lt;strong&gt;стильным фермерским магазинчиком с одной кассой&lt;/strong&gt;, то &lt;code&gt;PostgreSQL&lt;/code&gt; — это &lt;strong&gt;Costco с 50 кассами&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&#34;1-пробки-при-записи-данных&#34;&gt;1. Пробки при записи данных
&lt;/h3&gt;&lt;p&gt;Когда &lt;code&gt;SQLite&lt;/code&gt; записывает данные, она &lt;strong&gt;блокирует&lt;/strong&gt; весь файл базы данных.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Представьте &lt;strong&gt;ресторан с одним туалетом&lt;/strong&gt;: 100 человек могут одновременно изучать меню снаружи (читать), но как только 1 человек заходит внутрь и запирает дверь (запись), все остальные могут только стоять в очереди и ждать.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Хотя включение &lt;strong&gt;режима WAL (Write-Ahead Logging)&lt;/strong&gt; может улучшить производительность одновременного чтения/записи, фундаментально запись в разные строки данных несколькими потоками одновременно остается невозможной.&lt;/p&gt;
&lt;h3 id=&#34;2-не-может-работать-на-нескольких-серверах&#34;&gt;2. Не может работать на нескольких серверах
&lt;/h3&gt;&lt;p&gt;Суть &lt;code&gt;SQLite&lt;/code&gt; — это физический файл. Если ваша система развернута на нескольких серверах (горизонтальное масштабирование), эти серверы &lt;strong&gt;не могут безопасно использовать один и тот же файл совместно&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&#34;3-отсутствие-детального-управления-правами-доступа&#34;&gt;3. Отсутствие детального управления правами доступа
&lt;/h3&gt;&lt;p&gt;В &lt;code&gt;SQLite&lt;/code&gt; нет понятия &amp;ldquo;учетных записей пользователей&amp;rdquo;. Любой, кто может прочитать файл &lt;code&gt;.db&lt;/code&gt; на уровне операционной системы, может просматривать и изменять все данные.&lt;/p&gt;
&lt;p&gt;Для &lt;strong&gt;бизнес-систем, требующих строгого аудита личных данных&lt;/strong&gt;, это абсолютно неприемлемо.&lt;/p&gt;
&lt;h2 id=&#34;sqlite-vs-postgresql-принятие-технологического-решения&#34;&gt;SQLite vs. PostgreSQL: Принятие технологического решения
&lt;/h2&gt;&lt;p&gt;Нет плохих или хороших инструментов, есть только подходящие или нет. Вот окончательный контрольный список, который поможет вам определиться:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Вопрос&lt;/th&gt;
          &lt;th&gt;Ответ &amp;ldquo;Да&amp;rdquo; → Выбирайте SQLite&lt;/th&gt;
          &lt;th&gt;Ответ &amp;ldquo;Нет&amp;rdquo; → Выбирайте PostgreSQL&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Имеется только один бэкенд-сервер или запуск полностью локальный?&lt;/td&gt;
          &lt;td&gt;Да&lt;/td&gt;
          &lt;td&gt;Нет (требуется горизонтальное масштабирование, много серверов)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Поведение системы в основном ориентировано на чтение без частой одновременной записи?&lt;/td&gt;
          &lt;td&gt;Да&lt;/td&gt;
          &lt;td&gt;Нет (пользователи будут конкурировать за одновременную запись)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Не требуются детальные права доступа к БД или продвинутое индексирование?&lt;/td&gt;
          &lt;td&gt;Да&lt;/td&gt;
          &lt;td&gt;Нет (сильно зависит от продвинутых функций)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Сравнение более конкретных сценариев:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Сценарий&lt;/th&gt;
          &lt;th&gt;Рекомендуемый выбор&lt;/th&gt;
          &lt;th&gt;Причина&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Настольное ПО, мобильные приложения, IoT-устройства&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Данные перемещаются с устройством, без установки&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Личные блоги, сайты-визитки&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Много чтения, мало записи, экономия на обслуживании сервера&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Быстрое создание прототипов, демо&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Просто создайте файл, чтобы начать&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Форумы сообществ, платформы электронной коммерции&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Высокая частота одновременной записи, нужна блокировка строк&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Распределенное развертывание на нескольких серверах&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Необходимо совместно использовать данные на разных машинах&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Высокочувствительные системы (медицина, финансы)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Требуется строгий ролевой контроль доступа&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;ваша-база-данных--это-карманный-блокнот-или-центральная-телефонная-станция&#34;&gt;Ваша база данных — это карманный блокнот или центральная телефонная станция?
&lt;/h2&gt;&lt;p&gt;Если данные представляют собой &lt;strong&gt;&amp;ldquo;один компьютер, статика, один владелец&amp;rdquo;&lt;/strong&gt;, выбирайте &lt;code&gt;SQLite&lt;/code&gt; для максимальной легкости и свободы;&lt;/p&gt;
&lt;p&gt;Если данные — это &lt;strong&gt;&amp;ldquo;облако, динамика, высокая интерактивность&amp;rdquo;&lt;/strong&gt;, пусть управление возьмет на себя &lt;code&gt;PostgreSQL&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Основная философия &lt;code&gt;SQLite&lt;/code&gt; — &lt;strong&gt;&amp;ldquo;внутренний компонент приложения&amp;rdquo;&lt;/strong&gt;, в то время как &lt;code&gt;PostgreSQL&lt;/code&gt; позиционируется как &lt;strong&gt;&amp;ldquo;независимый центр системной архитектуры&amp;rdquo;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;В следующий раз, принимая архитектурное решение, не спешите доставать &lt;code&gt;PostgreSQL&lt;/code&gt;. Сначала спросите себя:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;Моя база данных — это карманный блокнот или центральная телефонная станция?&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Когда ответ станет ясен, выбор определится сам собой.&lt;/p&gt;
&lt;h2 id=&#34;reference&#34;&gt;Reference
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://sqlite.org/lang.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Query Language Understood by SQLite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://sqlite.org/docs.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQLite Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.sqlitetutorial.net/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQLite Tutorial - An Easy Way to Master SQLite Fast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/SQLite&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQLite - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
    </channel>
</rss>
