---
title: "データベースとマイグレーション"
description: "マルチドライバーのデータベースアダプター、スキーマ駆動型モデル生成、および番号付けされたSQLマイグレーション。"
---

Nibiru は、統一された `Db` アダプターの背後で **5つのデータベースドライバー** を搭載しており、[CLI](/cli/migrations/) によって駆動される番号付き SQL マイグレーションランナーも含まれています。

## ドライバー選択

INI の `[DATABASE] driver` でアクティブなドライバーを設定します。

| ドライバー | バックエンド | 備考 |
|---|---|---|
| `mysql` | Native MySQL/MariaDB (`mysqli`) | 最速で、PDO のオーバーヘッドがありません。 |
| `pdo` | PDO MySQL | 推奨されるデフォルトです。準備されたステートメント、ドライバーが広く使用されています。 |
| `postgres` | PostgreSQL via **ODBC** | サーバーにのみ ODBC しか利用できない場合です。 |
| `psql` | PostgreSQL via libpq (`pg_*`) | Native PostgreSQL です。 |
| `postgresql` | ランタイム時に最適な PostgreSQL トランスポートを選択するラッパーです。 | |
```ini
[DATABASE]
driver   = "pdo"
hostname = "localhost"
port     = 3306
username = "nibiru"
password = "secret"
basename = "nibiru_dev"
encoding = "utf8mb4"
is.active = true
```
ディスパッチャーはブート時にドライバーを初期化します。ドライバーの切り替えには、構成の変更と再起動のみが必要です。

## データベースアダプター

生成されたすべてのモデルは、ドライバー固有の `Db` アダプター（`Adapter\MySQL\Db`, `Adapter\PostgreSQL\Db`, `Adapter\Odbc\Db`）を拡張します。すべてのアダプターは同じインターフェースを持っています：
```php
use Nibiru\Pdo;

// Read a single row by primary-key columns
$row = Pdo::fetchRowInArrayById('users', ['user_id' => 42]);

// Run a parameterised query
$rows = Pdo::fetchAll(
    'SELECT * FROM products WHERE category = :cat',
    [':cat' => 'gold-plating']
);

// Insert
Pdo::insert('products', [
    'name' => 'Marduk Gold Plating',
    'price' => 99.0,
]);

// Update
Pdo::update('products',
    ['price' => 89.0],
    ['id' => 1]);

// Delete
Pdo::delete('products', ['id' => 1]);

// Last insert id
Pdo::lastInsertId();
```
ドライバ固有のヘルパーは、アダプタークラス自体に存在します（`\Nibiru\Mysql::query()`、`\Nibiru\Postgresql::pgQuery()`、…）。生のアクセスが必要な場合です。

## スキーマファーストモデル

`[GENERATOR] database = true` の場合、ディスパッチャは毎回リクエストごとに1つのPHPクラスをテーブルごとに再生成します。詳細については [Models](/core/models/) を参照してください。

本番環境で：
```ini
[GENERATOR]
database          = false
database.overwrite = false
```
スキーマを移行するときのみ再生成してください。

## マイグレーション

マイグレーションは `application/settings/config/database/` に配置され、実行順序用に番号が付けられた **プレーンなSQLファイル** です。
```
application/settings/config/database/
├── 001-acl.sql
├── 002-account.sql
├── 003-api_registry.sql
├── 004-timeanddate.sql
├── 005-user.sql
├── 006-user_to_account.sql
├── 011-acl-data.sql
├── 012-add-unique-key-user.sql
└── 013-add-account-email.sql
```
CLI はそれらを適用します：
```bash
./nibiru -mi local
APPLICATION_ENV=staging   ./nibiru -mi staging
APPLICATION_ENV=production ./nibiru -mi production
```
実行者は（ドライバ名ごとに）`_migrations` テーブルを作成し、既に適用済みのファイルはスキップします。各ファイルは単一のバッチとして実行され、途中でステートメントがエラーになる場合は、SQL を修正して再実行してください。

### ファイル名の命名規則

- 3桁ゼロ埋めの数値プレフィックス: `NNN-<slug>.sql`。
- スラッグは変更を説明します（`-add-account-email`、`-drop-wrong-constraints`）。
- 1ファイルにつき1つの論理的な変更を行います。圧縮しないでください。
- データのみのシードの場合、`-data.sql`サフィックスを使用してください（`011-acl-data.sql`）。

### Idempotency

`IF NOT EXISTS` と `IF EXISTS` を使用して、ファイルを安全に再実行できるようにします：
```sql
CREATE TABLE IF NOT EXISTS api_registry (
    api_registry_id     INT(11) NOT NULL AUTO_INCREMENT,
    api_registry_name   VARCHAR(255) NOT NULL,
    api_registry_token  VARCHAR(64)  NOT NULL,
    PRIMARY KEY (api_registry_id),
    UNIQUE KEY api_registry_token_uk (api_registry_token)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
``````sql
ALTER TABLE user
    ADD UNIQUE KEY user_login_uk (user_login)
    /* skip if exists; on MySQL 8 you can wrap with IF NOT EXISTS */;
```
### リセットコマンド（注意して使用してください）
```bash
./nibiru -mi-reset local                    # forget all applied migrations
./nibiru -mi-reset-file 005-user.sql local  # forget a single file's run record
```
これらのコマンドはテーブルを削除しません——のみ `_migrations` 監査テーブルが削除されます。完全に初期化したい場合は、手動で `DROP` を実行してください。

## PostgreSQL の特定点

`driver = "psql"` または `"postgresql"` の場合:

- `SERIAL` / `BIGSERIAL` を代わりに使用します。
- `information_schema.tables` のテーブルを使用するのではなく、`SHOW TABLES` を使用します。
- 引用符：識別子はダブルクォートで囲みます（`"user"` が正しい形式です。なぜなら `user` が予約語だからです）。
- CLI の条件付きコンパイルフラグは、libpq がコンパイル時に存在しない場合でも PostgreSQL ビルドが優雅に劣化します — サポートを確認するには `./nibiru -v` を実行してください。

## コネクションプーリング

組み込みのプールはありません。高トラフィックなアプリケーションでは使用してください：

- **MariaDB / MySQL:** プロキシーサーバー（ProxySQL または HAProxy）をデータベースの前に配置します。
- **PostgreSQL:** PgBouncer をトランザクションプールモードで使用します。

Nibiru は1リクエストにつき1つの接続を開きますので、通常はプーラーだけが必要です。

## 一般的な落とし穴

- **`is.active = false`**は静かに接続を無効にします — クエリが`null`を返す場合、これを確認してください。
- **プロダクションでのジェネレータのオン。** `[GENERATOR] database = true`で、すべてのリクエストがモデルファイルを再書き込みします。デプロイ後には必ずオフにしてください。
- **混在するドライバー。** PostgreSQLを実行しているときに`mysql`を選択すると、成功した`Pdo::fetchAll`が`[]`を返します — 接続は静かに失敗します。スモークテストで必ず`SELECT 1`で確認してください。
