---
title: "データベース"
version: 5.2
locale: ja
source: https://docs.djangoproject.com/ja/5.2/ref/databases/
canonical: https://djangodocs.dev/ja/5.2/ref/databases/
---
# データベース

Django は次のデータベースを公式にサポートしています。

- [PostgreSQL](#postgresql-notes)
- [MariaDB](#mariadb-notes)
- [MySQL](#mysql-notes)
- [Oracle](#oracle-notes)
- [SQLite](#sqlite-notes)

[サードパーティから提供されているデータベースバックエンド](#third-party-notes) も多数あります。

Django はすべてのデータベースで可能な限り多くの機能をサポートするように努めています。しかし、すべてのデータベースバックエンドが似ているわけではないため、どの機能をサポートし、どのような前提なら安全に想定できるのかについて、設計上の決断を下す必要がありました。

このファイルは Django の利用に関係する可能性のある一部の機能を説明しています。サーバー固有のドキュメントやリファレンスマニュアルを置換することを意図したものではありません。

## 一般的なメモ

### 持続的 (persistent) な接続

持続的な接続は HTTP リクエストごとにデータベースへの接続を再確立するオーバーヘッドを回避します。持続的な接続は接続の最大寿命を定義する [`CONN_MAX_AGE`](/ja/5.2/ref/settings/#std-setting-CONN_MAX_AGE) パラメータによって制御されます。このパラメータはデータベースごとに個別に設定できます。

デフォルト値は `0` で、各リクエストの終了時にデータベース接続をクローズするという従来の動作を維持します。持続的な接続を有効にするには、 [`CONN_MAX_AGE`](/ja/5.2/ref/settings/#std-setting-CONN_MAX_AGE) に秒単位の正の整数を設定します。持続的な接続を無制限にするには、`None` に設定します。

ASGI を使用する場合、永続的なデータベース接続は無効にすべきです。代わりに、利用可能であればデータベースバックエンドが提供する接続プーリング機能を使用するか、必要に応じてサードパーティ製の接続プーリングの利用を検討してください。

#### 接続管理

Django は、最初にデータベースへの問い合わせを行うときに、データベースへの接続をオープンします。Django はこの接続をオープンしたままにしておき、その後のリクエストで再利用します。Django は接続が [`CONN_MAX_AGE`](/ja/5.2/ref/settings/#std-setting-CONN_MAX_AGE) で定義された最大寿命を超えたり、それ以上使えなくなると接続をクローズします。

正確には、Djangoは必要なときに、または接続がない場合（これが最初の接続であるか、前の接続がクローズされていた場合）に自動的にデータベースへの接続をオープンします。

各リクエストの最初に、Django は接続が最大寿命に達した場合、接続をクローズします。もしデータベースがアイドル状態の接続をしばらくしてから終了するのであれば、 [`CONN_MAX_AGE`](/ja/5.2/ref/settings/#std-setting-CONN_MAX_AGE) を低い値に設定して、Django がデータベースサーバにすでに終了した接続を使おうとしないようにすべきです。(この問題は、非常にトラフィックの少ないサイトにしか影響しないかもしれません)。

各リクエストの終了時に、 Django は接続が最大寿命に達していたり、回復不可能なエラー状態になっていたりすると、接続をクローズします。リクエストの処理中にデータベースエラーが発生した場合、 Django は接続がまだ動作しているかどうかをチェックし、動作していなければ接続をクローズします。接続が使えなくなると、次のリクエストは新しい接続を取得します。

[`CONN_HEALTH_CHECKS`](/ja/5.2/ref/settings/#std-setting-CONN_HEALTH_CHECKS) を `True` に設定することで、接続の再利用の堅牢性を向上させ、データベースサーバーによって接続がクローズされた後に新しい接続を受け入れて提供する準備ができている場合（例えば、データベースサーバーの再起動後など）にエラーを防ぐことができます。ヘルスチェックはリクエストごとに一度だけ実行され、リクエストの処理中にデータベースがアクセスされている場合のみ実行されます。

#### 注意事項

各スレッドは独自の接続を維持するため、データベースは少なくともワーカースレッドと同数の同時接続をサポートする必要があります。

データベースが外部システムのデータベースであったり、キャッシュのおかげでビューの大部分からアクセスされないことがあります。このような場合、 [`CONN_MAX_AGE`](/ja/5.2/ref/settings/#std-setting-CONN_MAX_AGE) を低い値、あるいは `0` に設定する必要があります。これにより、このデータベースへの同時接続数を少なく保つことができます。

開発用サーバはリクエストを処理するたびに新しいスレッドを生成し、 持続的な接続の効果を無効にします。開発中は有効にしないでください。

Django がデータベースへの接続を確立するとき、使われているバックエンドに応じて適切なパラメータを設定します。持続的な接続を有効にすると、この設定はリクエストの度に繰り返されなくなります。接続の分離レベルやタイムゾーンなどのパラメータを変更した場合は、リクエストの最後に Django のデフォルトに戻すか、リクエストの最初に適切な値を設定するか、持続的な接続を無効にしてください。

長時間実行されるプロセスで接続が作成された場合、Django のリクエスト－レスポンスサイクル外では、接続は明示的に閉じるか、タイムアウトが発生するまで開いたままになります。`django.db.close_old_connections()` を使用して、すべての古いまたは使用できない接続を閉じることができます。

### エンコーディング

Django はすべてのデータベースが UTF-8 エンコーディングを使用することを想定しています。他のエンコーディングを使用すると、Django にとっては有効なデータに対して、データベースから「value too long (値が大きすぎる)」エラーなどの予期しない動作が起こる可能性があります。データベースを正しく設定する方法については、以下のデータベース固有のノートを確認してください。

## PostgreSQL に関するノート

Django は PostgreSQL 14 以上をサポートします。 [psycopg](https://www.psycopg.org/psycopg3/) 3.1.8+ または [psycopg2](https://www.psycopg.org/) 2.8.4+ が必要ですが、最新の [psycopg](https://www.psycopg.org/psycopg3/) 3.1.8+ が推奨されます。

> **Note**
>
> `psycopg2` のサポートは、将来のある時点で非推奨となり削除される可能性があります。

### PostgreSQL の接続設定

詳細は [`HOST`](/ja/5.2/ref/settings/#std-setting-HOST) を参照してください。

[connection service file](https://www.postgresql.org/docs/current/libpq-pgservice.html) のサービス名と [password file](https://www.postgresql.org/docs/current/libpq-pgpass.html) のパスワードを使用して接続するためには、それらを [`DATABASES`](/ja/5.2/ref/settings/#std-setting-DATABASES) 内のデータベース設定の [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) 部分で指定しなければなりません。

*`settings.py`*

```python
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "OPTIONS": {
            "service": "my_service",
            "passfile": ".my_pgpass",
        },
    }
}
```

*`.pg_service.conf`*

```text
[my_service]
host=localhost
user=USER
dbname=NAME
port=5432
```

*`.my_pgpass`*

```text
localhost:5432:NAME:USER:PASSWORD
```

PostgreSQLバックエンドは [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) の内容をキーワード引数として接続コンストラクタに渡します。これにより、ドライバの動作をより高度に制御できます。利用可能なすべての [parameters](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS) についてはPostgreSQLのドキュメントで詳しく説明されています。

> **Warning**
>
> テスト目的のサービス名の使用はサポートされていません。これは [将来実装される可能性があります](https://code.djangoproject.com/ticket/33685) 。

### PostgreSQL の設定を最適化する

Django はデータベース接続のために次のパラメータが必要です。

- `client_encoding`: `'UTF8'`,
- `default_transaction_isolation`: デフォルトの `'read committed'` または接続オプションで設定した値 (以下を参照)。
- **`timezone`:**

    - [`USE_TZ`](/ja/5.2/ref/settings/#std-setting-USE_TZ) が `True` のとき、デフォルトの `'UTC'` または接続のために設定した [`TIME_ZONE`](/ja/5.2/ref/settings/#std-setting-DATABASE-TIME_ZONE) の値。
    - [`USE_TZ`](/ja/5.2/ref/settings/#std-setting-USE_TZ) が `False` のとき、グローバルの [`TIME_ZONE`](/ja/5.2/ref/settings/#std-setting-TIME_ZONE) 設定の値。

これらのパラメータがすでに正しい値を持っている場合、 Django は新しい接続のたびにパラメータを設定しないので、パフォーマンスが少し改善されます。これらのパラメータは `postgresql.conf` で直接設定することもできますし、 [ALTER ROLE](https://www.postgresql.org/docs/current/sql-alterrole.html) でデータベースユーザごとに設定することもできます。

Django はこの最適化なしでも問題なく動作しますが、新しい接続のたびに、これらのパラメータを設定するために追加のクエリを実行します。

### 分離レベル (isolation level)

PostgreSQL 自体と同様に、Django のデフォルトは `READ COMMITTED` の [isolation level](https://www.postgresql.org/docs/current/transaction-iso.html) に設定されています。`REPEATABLE READ` や `SERIALIZABLE` などのより高いレベルの分離レベルが必要な場合は、[`DATABASES`](/ja/5.2/ref/settings/#std-setting-DATABASES) 内のデータベース設定の [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) 部分に指定してください。

```
from django.db.backends.postgresql.psycopg_any import IsolationLevel

DATABASES = {
    # ...
    "OPTIONS": {
        "isolation_level": IsolationLevel.SERIALIZABLE,
    },
}
```

> **Note**
>
> より高い分離レベルのもとでは、アプリケーションはシリアライズの失敗時に発生する例外を処理できるように準備しておく必要があります。このオプションは高度な利用のために設計されています。

### ロール

データベース接続のためにコネクションの確立に使用するロールとは別のロールを使用する必要がある場合は、次のように [`DATABASES`](/ja/5.2/ref/settings/#std-setting-DATABASES) 内のデータベース設定の [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) 部分で指定してください。

```
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        # ...
        "OPTIONS": {
            "assume_role": "my_application_role",
        },
    },
}
```

### 接続プール

> **New in Django 5.1**

[psycopg](https://www.psycopg.org/psycopg3/) で接続プールを使用するには、[`DATABASES`](/ja/5.2/ref/settings/#std-setting-DATABASES) のデータベース設定内の [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) 部分で `"pool"` を設定し、これを [`ConnectionPool`](https://www.psycopg.org/psycopg3/docs/api/pool.html#psycopg_pool.ConnectionPool) に渡す辞書にするか、`True` に設定して `ConnectionPool` のデフォルトを使用できます。

```
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        # ...
        "OPTIONS": {
            "pool": True,
        },
    },
}
```

このオプションは `psycopg[pool]` または [psycopg-pool](https://pypi.org/project/psycopg-pool/) がインストールされている必要があり、`psycopg2` では無視されます。

### サーバーサイド パラメータ バインディング

[psycopg](https://www.psycopg.org/psycopg3/) 3.1.8+ では、Django のデフォルトは [クライアントサイド・バインディングカーソル](https://www.psycopg.org/psycopg3/docs/advanced/cursors.html#client-side-binding-cursors) です。もし [サーバーサイド・バインディング](https://www.psycopg.org/psycopg3/docs/basic/from_pg2.html#server-side-binding) を使いたい場合は、 [`DATABASES`](/ja/5.2/ref/settings/#std-setting-DATABASES) のデータベース設定の [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) の部分で設定してください：

```
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        # ...
        "OPTIONS": {
            "server_side_binding": True,
        },
    },
}
```

このオプションは `psycopg2` では無視されます。

### `varchar` カラムと `text` カラムのインデックス

モデルフィールドに `db_index=True` を指定すると、Django は通常 1 つの `CREATE INDEX` ステートメントを出力します。しかし、フィールドのデータベースタイプが `varchar` か `text` (例えば、 `CharField`、 `FileField`、 `TextField` で使われます) の場合、Django はカラムに適切な [PostgreSQL operator class](https://www.postgresql.org/docs/current/indexes-opclass.html) を使う追加のインデックスを作成します。この追加インデックスは、 `contains` や `startswith` のような `LIKE` 演算子を SQL で使ったルックアップを正しく実行するために必要です。

### 拡張機能を追加するためのマイグレーション・オペレーション

マイグレーションを使用して PostgreSQL 拡張機能 (`hstore` や `postgis` など) を追加する必要がある場合は、 [`CreateExtension`](/ja/5.2/ref/contrib/postgres/operations/#django.contrib.postgres.operations.CreateExtension) オペレーションを使用してください。

### サーバーサイド・カーソル

[`QuerySet.iterator()`](/ja/5.2/ref/models/querysets/#django.db.models.query.QuerySet.iterator) を使うと、 Django は [サーバーサイドカーソル](https://www.psycopg.org/psycopg3/docs/advanced/cursors.html#server-side-cursors) をオープンします。デフォルトでは、PostgreSQL はカーソルクエリの結果の最初の10%だけがフェッチされると仮定しています。クエリプランナはクエリの計画に費やす時間を減らし、より速く結果を返すようになりますが、結果の10%以上が取得された場合、性能が低下する可能性があります。PostgreSQLがカーソルクエリで取得する行数に関する仮定を制御するには、 [cursor\_tuple\_fraction](https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-CURSOR-TUPLE-FRACTION) オプションを使用してください。

#### トランザクションプールとサーバーサイドカーソル

トランザクションプーリングモード（たとえば、[PgBouncer](https://www.pgbouncer.org/) ）で接続プーラを使用するには、その接続のサーバーサイドカーソルを無効にする必要があります。

サーバーサイドカーソルは接続に対してローカルに存在し、 [`AUTOCOMMIT`](/ja/5.2/ref/settings/#std-setting-DATABASE-AUTOCOMMIT) が `True` の場合、トランザクションの終了時にも接続をオープンしたままにします。後続のトランザクションはサーバーサイドカーソルからより多くの結果を取得しようとするかもしれません。トランザクションプーリングモードでは、後続のトランザクションが同じ接続を使用するという保証はありません。異なる接続が使用される場合、トランザクションがサーバーサイドカーソルを参照する時にエラーが発生します。サーバーサイドカーソルは、それが作成された接続でのみアクセス可能だからです。

一つの解決策は、 [`DATABASES`](/ja/5.2/ref/settings/#std-setting-DATABASES) で [`DISABLE_SERVER_SIDE_CURSORS`](/ja/5.2/ref/settings/#std-setting-DATABASE-DISABLE_SERVER_SIDE_CURSORS) を `True` に設定して、接続のサーバーサイドカーソルを無効にすることです。

トランザクションプーリングモードでサーバーサイドカーソルの恩恵を受けるには、サーバーサイドカーソルを使用するクエリを実行するために、[データベースへのもう1つの接続](/ja/5.2/topics/db/multi-db/) を設定します。この接続はデータベースに直接接続するか、セッションプーリングモードの接続プーラに接続する必要があります。

もう一つの方法は、サーバーサイドのカーソルを使用している `QuerySet` を [`atomic()`](/ja/5.2/topics/db/transactions/#django.db.transaction.atomic) ブロックでラップすることです。これはトランザクションの間、 `autocommit` を無効にするからです。これにより、サーバーサイドカーソルはトランザクションの間だけ生きることになります。

### 自動インクリメントの主キーの値を手動で指定する

Django は自動インクリメントの主キーを格納するために PostgreSQL の identity カラムを使います。identity カラムには、次に利用可能な値を追跡する [sequence](https://www.postgresql.org/docs/current/sql-createsequence.html) の値が代入されます。自動インクリメントのフィールドに手動で値を代入しても、フィールドのシーケンスは更新されません。たとえば下記のようになります：

```pycon
>>> from django.contrib.auth.models import User
>>> User.objects.create(username="alice", pk=1)
<User: alice>
>>> # The sequence hasn't been updated; its next value is 1.
>>> User.objects.create(username="bob")
IntegrityError: duplicate key value violates unique constraint
"auth_user_pkey" DETAIL:  Key (id)=(1) already exists.
```

そのような値を指定する必要がある場合は、既にテーブルにある値を再利用しないように、後でシーケンスをリセットしてください。 [`sqlsequencereset`](/ja/5.2/ref/django-admin/#django-admin-sqlsequencereset) 管理コマンドはそのための SQL 文を生成します。

### テストデータベースのテンプレート

[`TEST['TEMPLATE']`](/ja/5.2/ref/settings/#std-setting-TEST_TEMPLATE) 設定を使用すると、テストデータベースを作成するための [template](https://www.postgresql.org/docs/current/sql-createdatabase.html) (たとえば `'template0'`) を指定できます。

### non-durable 設定でテストの実行を高速化する

[PostgreSQL を non-durable に設定する](https://www.postgresql.org/docs/current/non-durability.html) ことで、テストの実行時間を短縮できます。

> **Warning**
>
> これは危険です。サーバがクラッシュしたり電源が切れたりした場合に、データベースがデータ損失や破損の影響を受けやすくなります。クラスタ内の全データベースの内容を簡単にリストアできる開発マシンでのみ使用してください。

## MariaDB に関するノート

Django は MariaDB 10.5 以上をサポートします。

MariaDBを使用するには、MySQLバックエンドを使用してください、これは2つの間で共有されています。詳細は [MySQL に関するノート](#mysql-notes) を参照してください。

## MySQL に関するノート

### バージョン サポート

Django は MySQL 8.0.11 以降をサポートしています。

Django の `inspectdb` 機能は `information_schema` データベースを使います。このデータベースには全てのデータベーススキーマの詳細なデータが含まれています。

Django は、データベースが Unicode (UTF-8 エンコーディング) をサポートすることを期待し、 トランザクションと参照整合性を強制するタスクを MySQL に委譲します。MyISAM ストレージエンジンを使う場合、MySQL が後者 2 つを実際には強制していないという事実に注意することが重要です。次の節を参照してください。

### ストレージ エンジン

MySQL にはいくつかの [storage engines](https://dev.mysql.com/doc/refman/en/storage-engines.html) があります。サーバ設定でデフォルトのストレージエンジンを変更できます。

MySQL のデフォルトのストレージエンジンは [InnoDB](https://dev.mysql.com/doc/refman/en/innodb-storage-engine.html) です。このエンジンは完全にトランザクショナルで、外部キー参照をサポートしています。推奨される選択です。しかし、InnoDB は `AUTO_INCREMENT` の値を記憶せず、"max(id)+1" として再作成するため、MySQL の再起動時に自動インクリメントカウンタが失われます。このため、 [`AutoField`](/ja/5.2/ref/models/fields/#django.db.models.AutoField) の値が不用意に再利用される可能性があります。

[MyISAM](https://dev.mysql.com/doc/refman/en/myisam-storage-engine.html) の主な欠点は、トランザクションをサポートしていないことと、外部キー制約を強制していないことです。

### MySQL DB API ドライバ

MySQL には [**PEP 249**](https://peps.python.org/pep-0249/) で説明されている Python Database API を実装したドライバがいくつかあります：

- [mysqlclient](https://pypi.org/project/mysqlclient/) はネイティブドライバです。 **推奨される選択肢です** 。
- [MySQL Connector/Python](https://dev.mysql.com/downloads/connector/python/) は Oracle による純粋な Python ドライバで、MySQL クライアントライブラリや標準ライブラリ以外の Python モジュールを必要としません。

DB API ドライバに加え、Django は ORM からデータベースドライバにアクセスするためのアダプタが必要です。Django は mysqlclient 用のアダプタを提供しますが、MySQL Connector/Python には内蔵のアダプタ ([its own](https://dev.mysql.com/doc/connector-python/en/connector-python-django-backend.html)) があります。

#### mysqlclient

Django には [mysqlclient](#mysqlclient) 1.4.3 以降が必要です。

#### MySQL Connector/Python

MySQL Connector/Python は [download page](https://dev.mysql.com/downloads/connector/python/) から入手できます。Django アダプタはバージョン 1.1.X 以降で利用可能です。Django の最新リリースには対応していないかもしれません。

### タイムゾーンの定義

Django の [タイムゾーンサポート](/ja/5.2/topics/i18n/timezones/) を使うつもりなら、 [mysql\_tzinfo\_to\_sql](https://dev.mysql.com/doc/refman/en/mysql-tzinfo-to-sql.html) を使って MySQL データベースにタイムゾーンテーブルを読み込んでください。これはデータベースごとではなく、MySQLサーバーに対して一度だけ行う必要があります。

### データベースを作成する

コマンドラインツールで以下のSQLを実行することで、データベースを作成 ([create your database](https://dev.mysql.com/doc/refman/en/create-database.html)) できます:

```sql
CREATE DATABASE <dbname> CHARACTER SET utf8mb4;
```

これにより、すべてのテーブルとカラムがデフォルトでUTF-8を使用するようになります。

#### 照合順序 (collation) の設定

カラムの照合順序 (collation) の設定は、どの文字列を等しいものとして比較するかだけでなく、データをソートする順序も制御します。 [`CharField`](/ja/5.2/ref/models/fields/#django.db.models.CharField.db_collation) と [`TextField`](/ja/5.2/ref/models/fields/#django.db.models.TextField.db_collation) には `db_collation` パラメータを指定して、カラムの照合順序を設定できます。

照合順序はデータベース全体およびテーブルごとに設定することもできます。これについては、MySQL ドキュメント [documented thoroughly](https://dev.mysql.com/doc/refman/en/charset.html) で詳しく説明されています。このような場合、照合順序はデータベースの設定やテーブルを直接操作して設定する必要があります。Django はそれらを変更する API を提供しません。

デフォルトでは、UTF-8 データベースでは、MySQL は `utf8mb4_0900_ai_ci` 照合順序を使用します。この結果、すべての文字列の等値比較は *大文字小文字を区別しない* 方法で行われます。つまり、`"Fred"` と `"freD"` はデータベースレベルでは等しいとみなされます。フィールドにユニーク制約がある場合、`"aa"` と `"AA"` の両方を同じカラムに挿入しようとするのは不正です。デフォルトの照合順序では等しい (つまり一意ではない) と比較されるからです。特定のカラムやテーブルで大文字小文字を区別して比較したい場合は、そのカラムやテーブルを `utf8mb4_0900_as_cs` 照合順序を使用するように変更してください。

[MySQL Unicode Character Sets](https://dev.mysql.com/doc/refman/en/charset-unicode-sets.html) によると、照合順序 `utf8mb4_general_ci` の比較は、`utf8mb4_general_ci` の比較よりも高速ですが、正しさは若干劣ることに注意してください。もしこれがあなたのアプリケーションで許容できるのであれば、 `utf8mb4_general_ci` を使うべきです。これが許容できない場合(例えば、ドイツ語の辞書の並び順が必要な場合)、より正確な `utf8mb4_general_ci` を使用してください。

> **Warning**
>
> モデルのフォームセットは大文字小文字を区別して一意なフィールドをバリデーションします。したがって、大文字小文字を区別しない照合順序を使用している場合、大文字小文字の違いだけで一意なフィールド値を持つフォームセットはバリデーションを通過しますが、 `save()` を呼び出すと `IntegrityError` が発生します。

### データベースに接続する

[設定のドキュメント](/ja/5.2/ref/settings/) を参照してください。

接続設定はこの順番で使用されます：

1. [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS).
2. [`NAME`](/ja/5.2/ref/settings/#std-setting-NAME), [`USER`](/ja/5.2/ref/settings/#std-setting-USER), [`PASSWORD`](/ja/5.2/ref/settings/#std-setting-PASSWORD), [`HOST`](/ja/5.2/ref/settings/#std-setting-HOST),
   [`PORT`](/ja/5.2/ref/settings/#std-setting-PORT)
3. MySQL オプションファイル。

言い換えると、[`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) でデータベースの名前を設定した場合、これは [`NAME`](/ja/5.2/ref/settings/#std-setting-NAME) よりも優先されます。これは [MySQL option file](https://dev.mysql.com/doc/refman/en/option-files.html) の内容を上書きすることになります。

以下は MySQL オプションファイルを使用するサンプル設定です：

```
# settings.py
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "OPTIONS": {
            "read_default_file": "/path/to/my.cnf",
        },
    }
}
```

```ini
# my.cnf
[client]
database = NAME
user = USER
password = PASSWORD
default-character-set = utf8mb4
```

他にも `ssl`、`init_command`、`sql_mode` などの [MySQLdb connection options](https://mysqlclient.readthedocs.io/user_guide.html#functions-and-attributes) が役に立ちます。

#### `sql_mode` の設定

`sql_mode` オプションのデフォルト値には `STRICT_TRANS_TABLES` が含まれています。このオプションは、挿入時にデータが切り捨てられた場合に警告をエラーにエスカレートさせるため、Djangoはデータ損失を防ぐためにMySQLで [strict mode](https://dev.mysql.com/doc/refman/en/sql-mode.html#sql-mode-strict) を有効にすることを強く推奨します (`STRICT_TRANS_TABLES` または `STRICT_ALL_TABLES` のいずれか)。

SQLモードをカスタマイズする必要がある場合は、他のMySQLオプションと同様に `sql_mode` 変数を設定できます。設定ファイル内、または [`DATABASES`](/ja/5.2/ref/settings/#std-setting-DATABASES) のデータベース設定の [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) 部分に `'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"` エントリを追加することで設定できます。

#### 分離レベル (isolation level)

並行読み込みを実行する場合、異なるセッション（例えば、異なるリクエストを処理する別々のスレッド）からのデータベース・トランザクションは互いに影響し合う可能性があります。これらの相互作用は各セッションの [transaction isolation level](https://dev.mysql.com/doc/refman/en/innodb-transaction-isolation-levels.html) の影響を受けます。接続の分離レベルは [`DATABASES`](/ja/5.2/ref/settings/#std-setting-DATABASES) の [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) 部分にある `'isolation_level'` エントリで設定できます。このエントリの有効な値は4つの標準的な分離レベルです：

- `'read uncommitted'`
- `'read committed'`
- `'repeatable read'`
- `'serializable'`

または `None` でサーバで設定された分離レベルを使用します。しかし、Djangoでは MySQL のデフォルトである repeatable read ではなく、read commited を推奨し、デフォルトとしています。repeatable read ではデータ損失が発生する可能性があります。特に、 [`get_or_create()`](/ja/5.2/ref/models/querysets/#django.db.models.query.QuerySet.get_or_create) は [`IntegrityError`](/ja/5.2/ref/exceptions/#django.db.IntegrityError) を発生させますが、その後の [`get()`](/ja/5.2/ref/models/querysets/#django.db.models.query.QuerySet.get) 呼び出しではオブジェクトが表示されないような場合があります。

### テーブルを作成する

Django はスキーマを生成するとき、ストレージエンジンを指定しないので、テーブルはデータベースサーバが設定したデフォルトのストレージエンジンで作成されます。最も簡単な解決策は、データベースサーバのデフォルトのストレージエンジンを、希望のエンジンに設定することです。

ホスティングサービスを利用していて、サーバーのデフォルトストレージエンジンを変更できない場合、いくつかの選択肢があります。

- テーブルが作成された後、 `ALTER TABLE` ステートメントを実行して、テーブルを新しいストレージエンジン（InnoDBなど）に変換します：

  ```sql
  ALTER TABLE <tablename> ENGINE=INNODB;
  ```

  これはテーブルの数が多い場合、面倒です。
- テーブルを作成する前に MySQLdb の `init_command` オプションを使用する方法もあります：

  ```
  "OPTIONS": {
      "init_command": "SET default_storage_engine=INNODB",
  }
  ```

  これは、データベース接続時のデフォルトのストレージエンジンを設定します。テーブルが作成された後は、このオプションを削除してください。テーブルの作成時にのみ必要なクエリを各データベース接続に追加することになります。

### テーブル名

MySQL の最新バージョンでも、特定の条件下で特定の SQL 文を実行すると、テーブル名の大文字と小文字が変わってしまうという既知の問題 [known issues](https://bugs.mysql.com/bug.php?id=48875) があります。この動作から発生する可能性のある問題を避けるために、可能であれば小文字のテーブル名を使うことをお勧めします。Django はモデルからテーブル名を自動生成するときに小文字のテーブル名を使うので、これは主に [`db_table`](/ja/5.2/ref/models/options/#django.db.models.Options.db_table) パラメータでテーブル名を上書きする場合に考慮すべき点です。

### セーブポイント

Django ORM と MySQL (InnoDB [ストレージエンジン](#mysql-storage-engines) を使う場合) はどちらも、データベース [セーブポイント](/ja/5.2/topics/db/transactions/#topics-db-transactions-savepoints) をサポートしています。

MyISAM ストレージエンジンを使用している場合、 [トランザクション API のセーブポイント関連メソッド](/ja/5.2/topics/db/transactions/#topics-db-transactions-savepoints) を使おとすると、データベース由来のエラーが発生することに注意してください。これは、MySQL データベース/テーブルのストレージエンジンを検出するのは高コストな操作であるため、このような検出結果に基づいてこれらのメソッドを何もしない関数に動的に変換する価値はないと判断されるためです。

### 特定のフィールドに関する注意事項

#### 文字 (Char) フィールド

フィールドに `unique=True` を使用している場合、カラムタイプが `VARCHAR` で格納されているフィールドの `max_length` が 255 文字に制限される可能性があります。これは [`CharField`](/ja/5.2/ref/models/fields/#django.db.models.CharField), [`SlugField`](/ja/5.2/ref/models/fields/#django.db.models.SlugField) に影響します。詳細は [the MySQL documentation](https://dev.mysql.com/doc/refman/en/create-index.html#create-index-column-prefixes) を参照してください。

#### `TextField` の制限

MySQL は `BLOB` または `TEXT` カラムの最初の N 文字だけをインデックス化できます。 `TextField` は定義された長さを持たないので、 `unique=True` としてマークすることはできません。MySQL は次のように報告します： "BLOB/TEXT column '\<db\_column\>' used in key specification without a key length" 。

#### Time および DateTime フィールドの 1 秒単位未満の時間のサポート

MySQL では、カラム定義に端数表示 (例: `DATETIME(6)`) が含まれていれば、秒未満の端数を格納できます。

Django は、データベースサーバがサポートしている場合、既存のカラムを秒未満の端数を含むようにアップグレードしません。既存のデータベースで秒未満のカラムを有効にしたい場合は、以下のようなコマンドを実行して、手動で対象のデータベースのカラムを更新する必要があります：

```sql
ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
```

または [データマイグレーション](/ja/5.2/topics/migrations/#data-migrations) の [`RunSQL`](/ja/5.2/ref/migration-operations/#django.db.migrations.operations.RunSQL) オペレーションを使用します。

#### `TIMESTAMP` カラム

もし `TIMESTAMP` カラムを含むレガシーデータベースを使用している場合、データの破損を避けるために、[`USE_TZ = False`](/ja/5.2/ref/settings/#std-setting-USE_TZ) を設定する必要があります。[`inspectdb`](/ja/5.2/ref/django-admin/#django-admin-inspectdb) はこれらのカラムを [`DateTimeField`](/ja/5.2/ref/models/fields/#django.db.models.DateTimeField) にマッピングし、タイムゾーンサポートを有効にすると、MySQLとDjangoの両方が値をUTCからローカル時間に変換しようと試みます。

### `QuerySet.select_for_update()` による行のロック

MySQL と MariaDB は `SELECT ... FOR UPDATE` 文のいくつかのオプションをサポートしていません。もし `select_for_update()` がサポートされていないオプションで使用された場合、 [`NotSupportedError`](/ja/5.2/ref/exceptions/#django.db.NotSupportedError) が発生します。

| オプション | MariaDB | MySQL |
| --- | --- | --- |
| `SKIP LOCKED` | X (≥10.6) | X |
| `NOWAIT` | X | X |
| `OF` |  | X |
| `NO KEY` |  |  |

MySQL で `select_for_update()` を使用する場合は、少なくともユニーク制約に含まれるフィールドのセットに対してクエリセットをフィルタリングするか、インデックスがカバーするフィールドに対してだけフィルタリングするようにしてください。そうしないと、トランザクションの間、テーブル全体に対して排他的書き込みロックがかかります。

### 自動型キャストは予期せぬ結果を引き起こすことがあります

文字列型で整数値のクエリを実行する場合、MySQL はテーブル内のすべての値の型を整数に強制的に変換してから比較を実行します。テーブルに `'abc'`, `'def'` という値があり、`WHERE mycolumn=0` というクエリを実行した場合、両方の行がマッチします。同様に、`WHERE mycolumn=1` は値 `'abc1'` にマッチします。したがって、 Django の文字列型フィールドは、クエリで使う前に必ず値を文字列にキャストします。

[`Field`](/ja/5.2/ref/models/fields/#django.db.models.Field) を直接継承したカスタムモデルフィールドを実装したり、 [`get_prep_value()`](/ja/5.2/ref/models/fields/#django.db.models.Field.get_prep_value) をオーバーライドしたり、 [`RawSQL`](/ja/5.2/ref/models/expressions/#django.db.models.expressions.RawSQL)、 [`extra()`](/ja/5.2/ref/models/querysets/#django.db.models.query.QuerySet.extra)、 [`raw()`](/ja/5.2/topics/db/sql/#django.db.models.Manager.raw) をオーバーライドする場合は、適切な型キャストを行う必要があります。

## SQLite に関するノート

Django は SQLite 3.31.0 以上をサポートします。

[SQLite](https://www.sqlite.org/) は、主に読み取り専用であったり、より小さなインストール容量を必要とするアプリケーションのための優れた開発代替手段を提供します。しかし、すべてのデータベースサーバと同様に、SQLite 固有の注意すべき違いがいくつかあります。

### 部分文字列のマッチングと大文字と小文字の区別

すべての SQLite バージョンにおいて、特定の種類の文字列を照合しようとした際に、やや直感に反する動作をします。これは、クエリセットで [`iexact`](/ja/5.2/ref/models/querysets/#std-fieldlookup-iexact) や [`contains`](/ja/5.2/ref/models/querysets/#std-fieldlookup-contains) フィルターを使用した場合に発生します。この動作は、次の二つのケースに分かれます。

\1. For substring matching, all matches are done case-insensitively. That is a
filter such as `filter(name__contains="aa")` will match a name of `"Aabb"`.

\2. For strings containing characters outside the ASCII range, all exact string
matches are performed case-sensitively, even when the case-insensitive options
are passed into the query. So the [`iexact`](/ja/5.2/ref/models/querysets/#std-fieldlookup-iexact) filter will behave exactly
the same as the [`exact`](/ja/5.2/ref/models/querysets/#std-fieldlookup-exact) filter in these cases.

この回避策はドキュメント化されています [documented at sqlite.org](https://www.sqlite.org/faq.html#q18) が、Django のデフォルトの SQLite バックエンドでは利用されていません。それらを堅牢に組み込むのはかなり難しいからです。そのため、Django はデフォルトの SQLite の動作を踏襲しており、大文字小文字を区別しないフィルタリングや部分文字列フィルタリングを行う際には、このことを意識する必要があります。

### 10進数 (Decimal) の扱い

SQLiteには本物の10進数の内部型はありません。 [SQLite datatypes documentation](https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes) で説明されているように、10進数の値は内部的に `REAL` データ型 (8バイトの IEEE 浮動小数点数) に変換されます。

### "Database is locked" エラー

SQLite は軽量なデータベースであるため、高い並行性をサポートすることはできません。 `OperationalError: database is locked` のエラーは、アプリケーションがデフォルト設定の `sqlite` で扱える以上の同時実行を試行していることを示しています。このエラーは、あるスレッドまたはプロセスがデータベース接続を排他的にロックし、別のスレッドがロックが解除されるのを待ってタイムアウトしたことを意味します。

Python の SQLite ラッパーにはデフォルトのタイムアウト値があり、2番目のスレッドがタイムアウトして `OperationalError: database is locked` というエラーを発生させるまでに、どれだけの時間ロックを待つことができるかを決めます。

このエラーが発生した場合は、次の方法で解決できます：

- 他のデータベース・バックエンドに乗り換えることです。ある段階でSQLiteは実世界のアプリケーションには "軽すぎる "ようになり、この種の同時実行エラーはその段階に達していることを示しています。
- 並行処理を減らし、データベーストランザクションが短時間で終了するようにコードを書き換えます。
- データベースオプションの `timeout` を設定することで、デフォルトのタイムアウト値を増やすことができます：

  ```
  "OPTIONS": {
      # ...
      "timeout": 20,
      # ...
  }
  ```

  これはSQLiteが "データベースがロックされています" エラーを発生させるまで少し待機させます。解決するために何かするわけではありません。

#### トランザクションの動作

> **New in Django 5.1**

SQLite は `DEFERRED`、`IMMEDIATE`、および `EXCLUSIVE` の3 種類のトランザクションモードをサポートしています。

デフォルトは `DEFERRED` です。異なるモードを使用する必要がある場合は、[`DATABASES`](/ja/5.2/ref/settings/#std-setting-DATABASES) のデータベース設定内の [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) 部分で設定します。例えば、次のように設定できます：

```
"OPTIONS": {
    # ...
    "transaction_mode": "IMMEDIATE",
    # ...
}
```

トランザクションが `timeout` の時間が経過するまで待機し、 "Database is Locked" エラーを発生させないようにするには、トランザクションモードを `IMMEDIATE` に変更してください。

`IMMEDIATE` および `EXCLUSIVE` モードで最良のパフォーマンスを得るためには、トランザクションはできるだけ短くする必要があります。すべてのビューでこれを保証するのは難しい場合があるため、この場合、[`ATOMIC_REQUESTS`](/ja/5.2/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS) の使用は推奨されません。

詳細については、[Transactions in SQLite](https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions) を参照してください。

### `QuerySet.select_for_update()` はサポートされていません。

SQLite は `SELECT ... FOR UPDATE` 構文をサポートしていません。これを呼び出しても何も起こりません。

### `QuerySet.iterator()` を使用する際の分離の問題

[`QuerySet.iterator()`](/ja/5.2/ref/models/querysets/#django.db.models.query.QuerySet.iterator) を使用してテーブルをイテレートしながらテーブルを変更する場合、 [Isolation In SQLite](https://www.sqlite.org/isolation.html) で説明されている特別な注意点があります。ループ内で行が追加、変更、削除された場合、その行はイテレータからフェッチされた後続の結果に現れるかもしれませんし、現れないかもしれません。コード内でこれを処理する必要があります。

### SQLite で JSON1 拡張機能を有効にする

SQLite で [`JSONField`](/ja/5.2/ref/models/fields/#django.db.models.JSONField) を使うには、Python の [`sqlite3`](https://docs.python.org/3/library/sqlite3.html#module-sqlite3) ライブラリで [JSON1 extension](https://www.sqlite.org/json1.html) を有効にする必要があります。拡張機能が有効になっていない場合、システムエラー (`fields.E180`) が発生します。

JSON1 拡張機能を有効にするには、 [the wiki page](https://code.djangoproject.com/wiki/JSON1Extension) の手順に従ってください。

> **Note**
>
> JSON1 拡張機能は SQLite 3.38+ ではデフォルトで有効になっています。

### PRAGMA オプションを設定する

> **New in Django 5.1**

[Pragma options](https://www.sqlite.org/pragma.html) は、接続時に [`DATABASES`](/ja/5.2/ref/settings/#std-setting-DATABASES) のデータベース設定内の [`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) 部分で `init_command` を使用して設定できます。以下の例では、同期書き込みの耐久性を強化し、`cache_size` を変更する方法を示しています：

```
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        # ...
        "OPTIONS": {
            "init_command": "PRAGMA synchronous=3; PRAGMA cache_size=2000;",
        },
    }
}
```

## Oracle に関するノート

Django は [Oracle Database Server](https://www.oracle.com/) バージョン 19c 以降をサポートしています。バージョン 2.3.0 以上の [oracledb](https://oracle.github.io/python-oracledb/) Python ドライバが必要です。

> **Deprecated since Django 5.0**
>
> バージョン 5.0 で非推奨: `cx_Oracle` のサポートは非推奨になりました。

`python manage.py migrate` コマンドを動作させるには、Oracleデータベースユーザーが以下のコマンドを実行する権限を持っている必要があります：

- CREATE TABLE
- CREATE SEQUENCE
- CREATE PROCEDURE
- CREATE TRIGGER

プロジェクトのテスト・スイートを実行するには、通常、ユーザーはこれらの *追加* 権限を必要とします：

- CREATE USER
- ALTER USER
- DROP USER
- CREATE TABLESPACE
- DROP TABLESPACE
- CREATE SESSION WITH ADMIN OPTION
- CREATE TABLE WITH ADMIN OPTION
- CREATE SEQUENCE WITH ADMIN OPTION
- CREATE PROCEDURE WITH ADMIN OPTION
- CREATE TRIGGER WITH ADMIN OPTION

`RESOURCE` ロールは `CREATE TABLE`, `CREATE SEQUENCE`, `CREATE PROCEDURE`, `CREATE TRIGGER` の権限を持っており、`RESOURCE WITH ADMIN OPTION` を与えられたユーザは `RESOURCE` を与えることができますが、個々の権限 (例えば `CREATE TABLE`) を与えることはできません。そのため、`RESOURCE WITH ADMIN OPTION` は通常テストの実行には十分ではありません。

これらを実行するには、ユーザは `CREATE VIEW WITH ADMIN OPTION` と `CREATE MATERIALIZED VIEW WITH ADMIN OPTION` 権限も必要です。特に、これは Django 自身のテストスイートに必要です。

これらの権限はすべて DBA ロールに含まれており、プライベートな開発者のデータベースで使用するのに適しています。

Oracle データベースのバックエンドは `SYS.DBMS_LOB` パッケージと `SYS.DBMS_RANDOM` パッケージを使用しているので、ユーザーには実行パーミッションが必要です。通常はデフォルトですべてのユーザーがアクセス可能ですが、そうでない場合は以下のようにパーミッションを付与する必要があります：

```sql
GRANT EXECUTE ON SYS.DBMS_LOB TO user;
GRANT EXECUTE ON SYS.DBMS_RANDOM TO user;
```

### データベースに接続する

Oracle データベースのサービス名を使用して接続するには、`settings.py` ファイルを次のように設定します：

```
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.oracle",
        "NAME": "xe",
        "USER": "a_user",
        "PASSWORD": "a_password",
        "HOST": "",
        "PORT": "",
    }
}
```

この場合、[`HOST`](/ja/5.2/ref/settings/#std-setting-HOST) と [`PORT`](/ja/5.2/ref/settings/#std-setting-PORT) の両方を空のままにします。しかし、`tnsnames.ora` ファイルや同様の命名メソッドを使用せず、SID（この例では "xe"）を使用して接続したい場合は、次のように [`HOST`](/ja/5.2/ref/settings/#std-setting-HOST) と [`PORT`](/ja/5.2/ref/settings/#std-setting-PORT) の両方を入力します：

```
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.oracle",
        "NAME": "xe",
        "USER": "a_user",
        "PASSWORD": "a_password",
        "HOST": "dbprod01ned.mycompany.com",
        "PORT": "1540",
    }
}
```

[`HOST`](/ja/5.2/ref/settings/#std-setting-HOST) と [`PORT`](/ja/5.2/ref/settings/#std-setting-PORT) の両方を指定するか、両方を空文字列のままにしてください。Django はその選択によって異なる接続記述子を使います。

#### Full DSN と Easy Connect

[`HOST`](/ja/5.2/ref/settings/#std-setting-HOST) と [`PORT`](/ja/5.2/ref/settings/#std-setting-PORT) の両方が空の場合、[`NAME`](/ja/5.2/ref/settings/#std-setting-NAME) に Full DSN または Easy Connect 文字列を使用できます。このフォーマットは、例えば `tnsnames.ora` のない RAC やプラガブル (pluggable) なデータベースを使用する場合に必要です。

Easy Connect 文字列の例：

```
"NAME": "localhost:1521/orclpdb1"
```

Full DSN 文字列の例：

```
"NAME": (
    "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))"
    "(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))"
)
```

### 接続プール

> **New in Django 5.2**

To use a connection pool with [oracledb](https://oracle.github.io/python-oracledb/), set `"pool"` to `True` in the
[`OPTIONS`](/ja/5.2/ref/settings/#std-setting-OPTIONS) part of your database configuration. This uses the driver's
[create\_pool()](https://python-oracledb.readthedocs.io/en/latest/user_guide/connection_handling.html#connection-pooling) default values:

```
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.oracle",
        # ...
        "OPTIONS": {
            "pool": True,
        },
    },
}
```

ドライバの [create\_pool()](https://python-oracledb.readthedocs.io/en/latest/user_guide/connection_handling.html#connection-pooling) 関数にカスタムパラメータを渡したい場合は、代わりに `"pool"` を辞書として設定することができます。

```
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.oracle",
        # ...
        "OPTIONS": {
            "pool": {
                "min": 1,
                "max": 10,
                # ...
            }
        },
    },
}
```

### スレッド (threaded) オプション

Django をマルチスレッド環境 (例えば、最近のオペレーティングシステムでデフォルトの MPM モジュールを使った Apache など) で動作させたい場合は、 Oracle データベースの設定の `threaded` オプションを `True` に設定する必要があります：

```
"OPTIONS": {
    "threaded": True,
}
```

これを行わないと、クラッシュその他の異常な動作が発生する可能性があります。

### INSERT ... RETURNING INTO

デフォルトでは、Oracle バックエンドは新しい行を挿入するときに `AutoField` の値を効率的に取得するために `RETURNING INTO` 句を使用します。 この動作は、リモートテーブルへの挿入や `INSTEAD OF` トリガを使用したビューへの挿入など、特殊なセットアップの場合に `DatabaseError` を引き起こす可能性があります。 `RETURNING INTO` 句は、データベース設定の `use_returning_into` オプションを `False` に設定することで無効にできます：

```
"OPTIONS": {
    "use_returning_into": False,
}
```

この場合、Oracle バックエンドは個別の `SELECT` クエリを使って `AutoField` の値を取得します。

### 命名に関する問題

Oracle では、名前の長さに 30 文字という制限があります。これに対応するため、バックエンドはデータベース識別子を適当な長さに切り詰め、切り詰めた名前の最後の4文字を繰り返し使用可能なMD5ハッシュ値に置き換えます。さらに、バックエンドはデータベース識別子をすべて大文字にします。

このような変換を防ぐには（通常、レガシーデータベースを扱う場合や、他のユーザーのテーブルにアクセスする場合にのみ必要です）、`db_table` の値として引用符で囲まれた名前を使用します：

```
class LegacyModel(models.Model):
    class Meta:
        db_table = '"name_left_in_lowercase"'

class ForeignModel(models.Model):
    class Meta:
        db_table = '"OTHER_USER"."NAME_ONLY_SEEMS_OVER_30"'
```

引用符で囲まれた名前は、Django がサポートしている Oracle 以外の他のデータベースバックエンドでも使用できます。ただし、引用符には効果がありません。

`migrate` を実行すると、特定の Oracle キーワードがモデルフィールド名や `db_column` オプションの値として使われた場合に、 `ORA-06552` エラーが発生することがあります。 Django はクエリで使われる全ての識別子を引用符で囲むことで、このような問題のほとんどを 防ぎますが、Oracle のデータ型がカラム名として使われると、このエラーが発生する可能性が あります。 特に、フィールド名として `date`, `timestamp`, `number`, `float` を使わないように注意してください。

### NULL と空の文字列

Django は通常、 `NULL` よりも空文字列 (`''`) を好んで使いますが、 Oracle はどちらも同じように扱います。これを回避するために、 Oracle バックエンドは、空の文字列を値とするフィールドの明示的な `null` オプションを無視し、 `null=True` であるかのように DDL を生成します。データベースから取得する際、これらのフィールドの `NULL` 値は本当に空の文字列を意味すると仮定され、この仮定を反映するようにデータは静かに変換されます。

### `TextField` の制限

Oracle バックエンドでは、それぞれの `TextField` を `NCLOB` カラムとして保存します。一般に、Oracle はこのような LOB カラムの使用にいくつかの制限を課しています。

- LOBカラムは主キーとして使用できません。
- LOB 列はインデックスでは使用できません。
- LOB 列は `SELECT DISTINCT` リストでは使用できません。つまり、Oracle に対して `TextField` 列を含むモデルで `QuerySet.distinct` メソッドを使用すると、`ORA-00932` エラーが発生します。回避策として、 `QuerySet.defer` メソッドと `distinct()` を併用して、 `TextField` 列が `SELECT DISTINCT` リストに含まれないようにしてください。

## 組み込みデータベース・バックエンドをサブクラス化する

Django には組み込みのデータベースバックエンドが付属しています。既存のデータベースバックエンドをサブクラス化して、その動作や機能、設定を変更できます。

たとえば、データベースの機能を一つだけ変更する必要があるとします。まず、`base` モジュールを含む新しいディレクトリを作成します。たとえば：

```text
mysite/
    ...
    mydbengine/
        __init__.py
        base.py
```

`base.py` モジュールには、 `django.db.backends` モジュールの既存のエンジンをサブクラス化した `DatabaseWrapper` というクラスを含める必要があります。以下は、PostgreSQL エンジンをサブクラス化して `allows_group_by_selected_pks_on_model` という機能を変更する例です：

*`mysite/mydbengine/base.py`*

```python
from django.db.backends.postgresql import base, features

class DatabaseFeatures(features.DatabaseFeatures):
    def allows_group_by_selected_pks_on_model(self, model):
        return True

class DatabaseWrapper(base.DatabaseWrapper):
    features_class = DatabaseFeatures
```

最後に、`settings.py` ファイルで [`DATABASE-ENGINE`](/ja/5.2/ref/settings/#std-setting-DATABASE-ENGINE) を指定する必要があります：

```
DATABASES = {
    "default": {
        "ENGINE": "mydbengine",
        # ...
    },
}
```

現在のデータベースエンジンのリストは [django/db/backends](https://github.com/django/django/blob/stable/5.2.x/django/db/backends) で見ることができます。

## サードパーティのデータベース・バックエンドを使う

公式にサポートされているデータベースに加え、サードパーティが提供するバックエンドがあり、Django で他のデータベースを使うことができます：

- [CockroachDB](https://pypi.org/project/django-cockroachdb/)
- [Firebird](https://pypi.org/project/django-firebird/)
- [Google Cloud Spanner](https://pypi.org/project/django-google-spanner/)
- [Microsoft SQL Server](https://pypi.org/project/mssql-django/)
- [MongoDB](https://pypi.org/project/django-mongodb-backend/)
- [Snowflake](https://pypi.org/project/django-snowflake/)
- [TiDB](https://pypi.org/project/django-tidb/)
- [YugabyteDB](https://pypi.org/project/django-yugabytedb/)

これらの非公式のバックエンドがサポートする Django のバージョンと ORM の機能は、バックエンドによって大きく異なります。これらの非公式なバックエンドの特定の機能に関する質問や、サポートに関する質問は、各サードパーティプロジェクトが提供するサポートチャンネルに直接問い合わせてください。
