<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>バックエンド開発 on Dev TLDRLSS</title>
        <link>https://dev.tldrlss.com/ja/categories/%E3%83%90%E3%83%83%E3%82%AF%E3%82%A8%E3%83%B3%E3%83%89%E9%96%8B%E7%99%BA/</link>
        <description>Recent content in バックエンド開発 on Dev TLDRLSS</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>ja</language>
        <lastBuildDate>Tue, 19 May 2026 18:10:00 +0800</lastBuildDate><atom:link href="https://dev.tldrlss.com/ja/categories/%E3%83%90%E3%83%83%E3%82%AF%E3%82%A8%E3%83%B3%E3%83%89%E9%96%8B%E7%99%BA/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>SQLiteの気まぐれに騙されるな！動的型の罠とは？なぜ ALTER TABLE は不完全なのか？Node.jsで防御的プログラミングを行いスムーズなテーブル移行を実現する方法</title>
        <link>https://dev.tldrlss.com/ja/article/2026/05/sqlite-pitfall-intro/</link>
        <pubDate>Tue, 19 May 2026 18:10:00 +0800</pubDate>
        
        <guid>https://dev.tldrlss.com/ja/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;code&gt;SQLite&lt;/code&gt; にとって &lt;strong&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;SQLite&lt;/code&gt; にとって &lt;strong&gt;単なる「推奨」であり、「強制ルール」ではありません&lt;/strong&gt;。&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;最も陥りやすい3つの型の罠&#34;&gt;最も陥りやすい3つの型の罠
&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;Node.js&lt;/code&gt; を使って &lt;code&gt;SQLite&lt;/code&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;if (user.is_admin === true)&lt;/code&gt; のようなチェックを直接行うと、永遠に真になりません。&lt;/p&gt;
&lt;h3 id=&#34;罠2datetime型がない&#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タイムスタンプ）&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;2026/5/19 午後6時&lt;/code&gt; のような独自のカスタム形式で保存してはいけません。将来のデータマイグレーションで悲劇が起こります。&lt;/p&gt;
&lt;h3 id=&#34;罠3integerカラムに文字列を挿入してもエラーにならない&#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;code&gt;Node.js&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;コンパイル時のガード&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;SQLite&lt;/code&gt; への保存時に自動的に &lt;code&gt;1/0&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;プライマリキーの変更&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;/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;再作成移行の4ステップsqlite流のテーブルアップグレード方法&#34;&gt;再作成＆移行の4ステップ：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;これら4つのステップは &lt;strong&gt;一気に行う&lt;/strong&gt; 必要があり、途中で停電やアプリケーションのクラッシュが発生するとデータ損失につながります。&lt;/p&gt;
&lt;!--adsense--&gt;
&lt;h2 id=&#34;アップグレードでデータを失わないための確保2つの安全防衛線&#34;&gt;アップグレードでデータを失わないための確保：2つの安全防衛線
&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トランザクションによるカプセル化データベースのタイムマシン&#34;&gt;防衛線2：トランザクションによるカプセル化、データベースのタイムマシン
&lt;/h3&gt;&lt;p&gt;すべての移行ステップを単一の &lt;code&gt;Transaction&lt;/code&gt; 内でカプセル化します。いずれかのステップが失敗した場合、プロセス全体が &lt;strong&gt;自動的にロールバック&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;code&gt;Node.js&lt;/code&gt; 側で &lt;strong&gt;TypeScript の型チェック ＋ Zod のバリデーション ＋ ORM の抽象化&lt;/strong&gt; をしっかりと行い、&lt;strong&gt;物理バックアップ ＋ トランザクション&lt;/strong&gt; の安全戦略と組み合わせることで、&lt;code&gt;SQLite&lt;/code&gt; がもたらす開発効率を安心して享受しつつ、将来 PostgreSQL に移行するための道筋を整えることができます。&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/ja/article/2026/05/sqlite-intro/</link>
        <pubDate>Tue, 19 May 2026 18:00:00 +0800</pubDate>
        
        <guid>https://dev.tldrlss.com/ja/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; は、C 言語で書かれた &lt;strong&gt;組み込み型関係データベースエンジン&lt;/strong&gt; です。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&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; であり、プログラムは &lt;strong&gt;ネットワークプロトコル（TCP/IP）&lt;/strong&gt; を介してそれと「通信」する必要があります。&lt;/p&gt;
&lt;p&gt;しかし、&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;「プラグアンドプレイ」&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;nodejs-での-sqlite-の使用&#34;&gt;Node.js での SQLite の使用
&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;多数 of 非同期タスクを同時に処理する必要がある場合&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; を使ってデータベースを作成し、クエリを実行するのに 5 分もかかりません：&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 のコア哲学は「スモール・イズ・ビューティフル」&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;レジが 1 つしかない個人経営の雑貨店&lt;/strong&gt; に例えるなら、&lt;code&gt;PostgreSQL&lt;/code&gt; は &lt;strong&gt;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;トイレが 1 つしかないレストラン&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; には「ユーザーアカウント」という概念がありません。OS レベルでその &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;回答が「はい」 → 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;バックエンドサーバーは 1 台だけ、またはローカルのみで動作していますか？&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;コミュニティフォーラム、EC サイト&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;「シングルマシン、静的、単一の所有者」&lt;/strong&gt; であるなら、&lt;code&gt;SQLite&lt;/code&gt; を選んで究極の軽快さと自由を享受しましょう。&lt;/p&gt;
&lt;p&gt;データが &lt;strong&gt;「クラウド、動的、高度なインタラクティブ」&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;「アプリケーション of 内部コンポーネント」&lt;/strong&gt; であるのに対し、&lt;code&gt;PostgreSQL&lt;/code&gt; は &lt;strong&gt;「システムアーキテクチャ of 独立した中心」&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;「私のデータベースは、ポケットのメモ帳ですか、それとも中央交換手ですか？」&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>
