---
title: "Basisdata"
version: 5.2
locale: id
source: https://docs.djangoproject.com/id/5.2/ref/databases/
canonical: https://djangodocs.dev/id/5.2/ref/databases/
---
# Basisdata

Django officially supports the following databases:

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

There are also a number of [database backends provided by third parties](#third-party-notes).

Django berusaha mendukung sebanyak mungkin fitur-fitur pada semua backend basisdata. bagaimanapun, tidak semua backend basisdata sama, dan kami harus membuat perancangan keputusan pada dimana fitur-fitur untuk mendukung dan dimana anggapan kami dapat membuat aman.

This file describes some of the features that might be relevant to Django
usage. It is not intended as a replacement for server-specific documentation or
reference manuals.

## Catatan umum

### Hubungan tetap

Persistent connections avoid the overhead of reestablishing a connection to
the database in each HTTP request. They're controlled by the
[`CONN_MAX_AGE`](/id/5.2/ref/settings/#std-setting-CONN_MAX_AGE) parameter which defines the maximum lifetime of a
connection. It can be set independently for each database.

The default value is `0`, preserving the historical behavior of closing the
database connection at the end of each request. To enable persistent
connections, set [`CONN_MAX_AGE`](/id/5.2/ref/settings/#std-setting-CONN_MAX_AGE) to a positive integer of seconds. For
unlimited persistent connections, set it to `None`.

When using ASGI, persistent connections should be disabled. Instead, use your
database backend's built-in connection pooling if available, or investigate a
third-party connection pooling option if required.

#### Pengelolaan hubungan

Django membua sebuah hubungan pada basisdata ketika itu pertama kali membuat sebuah permintaan basisdata. Itu menjaga hubungan ini tetap terbuka dan menggunakan kembali itu dalam permintaan selanjutnya. Django menutup hubungan sekali itu melampau batas umur maksimal ditentukan oleh [`CONN_MAX_AGE`](/id/5.2/ref/settings/#std-setting-CONN_MAX_AGE) atau ketika itu tidak digunakan lagi.

Secara terperinci, Django otomatis membuha sebuah hubungan pada basisdata kapanpun dia membutuhkan satu dan tidak mempunyai satu -- baik karena ini adalah hubungan pertama, atau karena hubungan sebelumnya telah ditutup.

Pada permulaan dari setiap permintaan, Django menutup hubungan jika itu telah mencapai umur maksimal. Jika basisdata anda memutuskan hubungan diam setelah beberapa waktu, anda harus menyetel [`CONN_MAX_AGE`](/id/5.2/ref/settings/#std-setting-CONN_MAX_AGE) pada nilai terendah, sehingga Django tidak berusaha menggunakan hubungan yang telah diputus oleh peladen basisdata. (Masalah ini mungkin hanya berpengaruh situs lalu lintas sangat rendah.)

At the end of each request, Django closes the connection if it has reached its
maximum age or if it is in an unrecoverable error state. If any database
errors have occurred while processing the requests, Django checks whether the
connection still works, and closes it if it doesn't. Thus, database errors
affect at most one request per each application's worker thread; if the
connection becomes unusable, the next request gets a fresh connection.

Setting [`CONN_HEALTH_CHECKS`](/id/5.2/ref/settings/#std-setting-CONN_HEALTH_CHECKS) to `True` can be used to improve the
robustness of connection reuse and prevent errors when a connection has been
closed by the database server which is now ready to accept and serve new
connections, e.g. after database server restart. The health check is performed
only once per request and only if the database is being accessed during the
handling of the request.

#### Peringatan

Sejak setiap thread merawat hubungan dia sendiri, basisdata anda harus mendukung setidaknya sebanyak hubungan serentak ketika anda memiliki thread pekerja.

Terkadang sebuah basisdata tidak mau diakses oleh kebanyakan dari tampilan anda, sebagai contoh karena itu adalah basisdata dari sebuah sistem luar, atau terima kasih ke penyimpanan sementara. Dalam kasus-kasus itu, anda harus mensetel [`CONN_MAX_AGE`](/id/5.2/ref/settings/#std-setting-CONN_MAX_AGE) menjadi nilai rendah atau bahkan `0`, karena itu tidak masuk akal merawat sebuah hubungan untuk digunakan kembali. Ini akan membantu menjaga sejumlah hubungan serentak pada basisdata kecil ini.

Peladen pengembangan membuat sebuah thread baru untuk setiap permintaan dia tangani, meniadakan pengaruh dari hubungan tetap. Jangan mengadakan mereka selama pengembangan.

Ketika Django membangun sebuah hubungan ke basisdata, dia menyetel parameter yang sesuai, tergantung pada backend sedang digunakan. Jika anda mengadakan hubungan tetap, pengaturan ini tidak lagi berulang setiap permintaan. jika anda merubah parameter seperti tingkat pemisahan hubungan atau zona waktu, anda harus baik menyimpan kembali awalan Django pada akhir setiap permintaan, memaksa sebuah nilai sesuai pada permulaan dari setiap permintaan, atau meniadakan hubungan tetap.

If a connection is created in a long-running process, outside of Django’s
request-response cycle, the connection will remain open until explicitly
closed, or timeout occurs. You can use `django.db.close_old_connections()` to
close all old or unusable connections.

### Penyandian

Django menganggap bahwa semua basisdata menggunakan penyandian UTF-8. Menggunakan penyandian lain mungkn menghasilkan perilaku tidak diharapkan seperti kesalahan "nilai terlalu panjang" dari basisdata anda untuk data yang sah dalam Django. Lihat basisdata catatan khusus dibawah untuk informasi pada bagaimana menyetel basisdata anda dengan benar.

## Catatan PostgreSQL

Django supports PostgreSQL 14 and higher. [psycopg](https://www.psycopg.org/psycopg3/) 3.1.8+ or [psycopg2](https://www.psycopg.org/)
2.8.4+ is required, though the latest [psycopg](https://www.psycopg.org/psycopg3/) 3.1.8+ is recommended.

> **Note**
>
> Support for `psycopg2` is likely to be deprecated and removed at some
> point in the future.

### Pengaturan hubungan PostgreSQL

Lihat [`HOST`](/id/5.2/ref/settings/#std-setting-HOST) untuk rincian.

To connect using a service name from the [connection service file](https://www.postgresql.org/docs/current/libpq-pgservice.html) and a
password from the [password file](https://www.postgresql.org/docs/current/libpq-pgpass.html), you must specify them in the
[`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS) part of your database configuration in [`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES):

*`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
```

The PostgreSQL backend passes the content of [`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS) as keyword
arguments to the connection constructor, allowing for more advanced control
of driver behavior. All available [parameters](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS) are described in detail in the
PostgreSQL documentation.

> **Warning**
>
> Using a service name for testing purposes is not supported. This
> [may be implemented later](https://code.djangoproject.com/ticket/33685).

### Mengoptimalkan konfigurasi PostgreSQL

Django butuh parameter berikut untuk hubungan basisdatanya:

- `client_encoding`: `'UTF8'`,
- `default_transaction_isolation`: `'read committed'` secara awalan, atau nilai disetel dalam pilihan hubungan (lihat dibawah),
- **`timezone`:**

    - when [`USE_TZ`](/id/5.2/ref/settings/#std-setting-USE_TZ) is `True`, `'UTC'` by default, or the
      [`TIME_ZONE`](/id/5.2/ref/settings/#std-setting-DATABASE-TIME_ZONE) value set for the connection,
    - when [`USE_TZ`](/id/5.2/ref/settings/#std-setting-USE_TZ) is `False`, the value of the global
      [`TIME_ZONE`](/id/5.2/ref/settings/#std-setting-TIME_ZONE) setting.

Jika parameter ini sudah memiliki nilai benar, Django tidak akan mensetel mereka untuk setiap hubugan baru, yang which memperbaiki sedikit penampilan. Anda dapat menkonfigurasi mereka langsung dalam `postgresql.conf` atau lebih nyaman per pengguna basisdata [ALTER ROLE](https://www.postgresql.org/docs/current/sql-alterrole.html).

Django akan bekerja baik tanpa optimalisasi ini, tetapi setiap hubungan baru akan melakukan beberapa permintaan untuk mensetel parameter ini.

### Tingkat terpencil

Seperti PostgreSQL itu sendiri, awalan Django pada `READ COMMITTED` [isolation level](https://www.postgresql.org/docs/current/transaction-iso.html). Jika anda butuh tingkat terpencil tertinggi seperti `REPEATABLE READ` atau `SERIALIZABLE`, setel itu dalam bagian [`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS) dari konfigurasi basisdata anda dalam [`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES):

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

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

> **Note**
>
> Dibawah tingkat terpencil tertinggi, aplikasi anda harus dipersiapkan menangani pengecualian dimunculkan pada kegagalan serialisasi. Pilihan ini dirancang untuk pengguna lanjut.

### Peran

If you need to use a different role for database connections than the role used
to establish the connection, set it in the [`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS) part of your
database configuration in [`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES):

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

### Connection pool

> **New in Django 5.1**

To use a connection pool with [psycopg](https://www.psycopg.org/psycopg3/), you can either set `"pool"` in the
[`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS) part of your database configuration in [`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES)
to be a dict to be passed to [`ConnectionPool`](https://www.psycopg.org/psycopg3/docs/api/pool.html#psycopg_pool.ConnectionPool), or
to `True` to use the `ConnectionPool` defaults:

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

This option requires `psycopg[pool]` or [psycopg-pool](https://pypi.org/project/psycopg-pool/) to be installed
and is ignored with `psycopg2`.

### Server-side parameters binding

With [psycopg](https://www.psycopg.org/psycopg3/) 3.1.8+, Django defaults to the [client-side binding
cursors](https://www.psycopg.org/psycopg3/docs/advanced/cursors.html#client-side-binding-cursors). If you want to use the
[server-side binding](https://www.psycopg.org/psycopg3/docs/basic/from_pg2.html#server-side-binding) set it in the
[`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS) part of your database configuration in
[`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES):

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

This option is ignored with `psycopg2`.

### Indeks untuk kolom `varchar` dan `text`

Ketika menentukan `db_index=True` pada bidang model anda, Django khususnya mengeluarkan pernyataan tunggal `CREATE INDEX`. Bagaimanapun, jika jenis basisdata untuk bidang adalah baik salah satu `varchar` atau `text` (misalnya, digunakan oleh `CharField`, `FileField`, dan `TextField`), kemudian Django akan membuat sebuah indeks tambahan yang menggunakan [PostgreSQL operator class](https://www.postgresql.org/docs/current/indexes-opclass.html) untuk kolom. Indeks tambahan diperlukan untuk dengan benar melakukan pencarian yang menggunakan penghubung `LIKE` dalam SQL mereka, ketika selesai dengan jenis pencarian `contains` dan `startswith`.

### Tindakan perpindahan untuk menambahkan tambahan.

Jika anda butuh menambahkan sebuah tambahan PostgreSQL (seperti `hstore`, `postgis`, dll.) menggunakan perpindahan, gunakan tindakan [`CreateExtension`](/id/5.2/ref/contrib/postgres/operations/#django.contrib.postgres.operations.CreateExtension).

### Kursor sisi-peladen

When using [`QuerySet.iterator()`](/id/5.2/ref/models/querysets/#django.db.models.query.QuerySet.iterator), Django opens a [server-side
cursor](https://www.psycopg.org/psycopg3/docs/advanced/cursors.html#server-side-cursors). By default, PostgreSQL assumes that
only the first 10% of the results of cursor queries will be fetched. The query
planner spends less time planning the query and starts returning results
faster, but this could diminish performance if more than 10% of the results are
retrieved. PostgreSQL's assumptions on the number of rows retrieved for a
cursor query is controlled with the [cursor\_tuple\_fraction](https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-CURSOR-TUPLE-FRACTION) option.

#### Menggabungkan transaksi dan kursor sisi-peladen

Using a connection pooler in transaction pooling mode (e.g. [PgBouncer](https://www.pgbouncer.org/))
requires disabling server-side cursors for that connection.

Kursos sisi-peladen adalah lokal terhadap sebuah hubungan dan tetap terbuka pada akhir dari sebuah transaksi ketika [`AUTOCOMMIT`](/id/5.2/ref/settings/#std-setting-DATABASE-AUTOCOMMIT) adalah `True`. Sebuah transaksi seanjutnya mungkin berusaha mengambil hasil lebih dari kursor sisi-peladen. Dalam suasana pengumpulan transaksi, tidak ada jaminan bahwa transaksi sebelumnya akan menggunakan hubungan sama. Jika sebuah hubungan berbeda digunakan, sebuah kesalahan dimunculkan ketika transaksi  mengacu kursor sisi-peladen, karena kursos sisi-peladen hanya tersedia dalam hubungan dimana mereka dibuat.

Satu pemecahan adalah untuk meniadakan kursor sisi peladen untuk sebuah hubungan adalah [`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES) by setting [`DISABLE_SERVER_SIDE_CURSORS`](/id/5.2/ref/settings/#std-setting-DATABASE-DISABLE_SERVER_SIDE_CURSORS) menjadi `True`.

Keuntungan dari kursor sisi-peladen dalam suasana penggabungan transaksi, anda dapat menyetel [another connection to the database](/id/5.2/topics/db/multi-db/) untuk melakukan permintaan yang menggunakan kursor sisi-peladen. Hubungan ini butuh salah satu langsung ke basisdata atau ke hubungan pengumpulan dalam suasana sesi pengumpulan.

Pilihan lain adalah membungkus setiap `QuerySet` menggunakan kursor sisi-peladen dalam sebuah blok [`atomic()`](/id/5.2/topics/db/transactions/#django.db.transaction.atomic), karena itu meniadakan `autocommit` untuk lamanya transaksi. Cara ini, kursor sisi-peladen akan hanya tinggal untuk selama transaksi.

### Manual-menentukan nilai-nilai dari primary key peningkatan-otomatis

Django uses PostgreSQL's identity columns to store auto-incrementing primary
keys. An identity column is populated with values from a [sequence](https://www.postgresql.org/docs/current/sql-createsequence.html) that keeps
track of the next available value. Manually assigning a value to an
auto-incrementing field doesn't update the field's sequence, which might later
cause a conflict. For example:

```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.
```

If you need to specify such values, reset the sequence afterward to avoid
reusing a value that's already in the table. The [`sqlsequencereset`](/id/5.2/ref/django-admin/#django-admin-sqlsequencereset)
management command generates the SQL statements to do that.

### Cetakan percobaan basisdata

Anda dapat menggunakan pengaturan [`TEST['TEMPLATE']`](/id/5.2/ref/settings/#std-setting-TEST_TEMPLATE) untuk menentukan  [template](https://www.postgresql.org/docs/current/sql-createdatabase.html) (misalnya `'template0'`) dari mana membuat basis data percobaan.

### Mempercepat penjalanan percobaan dengan pengaturan tidak-tahan-lama

Anda dapat mempercepat waktu penjalanan percobaan dengan [configuring PostgreSQL to be non-durable](https://www.postgresql.org/docs/current/non-durability.html).

> **Warning**
>
> Ini sangat berbahaya: itu akan membuat basisdata anda lebih rentan terhadap kehilangan data atau korupsi dalam kasus dari peladen roboh atau kehilangan daya. Gunakan ini hanya pada mesin pengembangan dimana anda dapat dengan mudah menyimpan kembali seluruh isi dari semua basisdata dalam gugus.

## MariaDB notes

Django supports MariaDB 10.5 and higher.

To use MariaDB, use the MySQL backend, which is shared between the two. See the
[MySQL notes](#mysql-notes) for more details.

## Catatan MySQL

### Versi dukungan

Django supports MySQL 8.0.11 and higher.

Fitur `inspectdb` Django menggunakan basisdata `information_schema`, yang mengandung rincian data pada semua skema basisdata.

Django mengharapkan basisdata untuk mendukung Unicode (UTF-8 encoding) dan menugaskan ke itu tugas dari memaksa transaksi dan keutuhan referensial. itu adalah penting untuk waspada dari fakta bahwa dua terakhir sebenarnya tidak dipaksa oleh MySQL ketika menggunakan mesin penyimpanan, lihat bagian selanjutnya.

### Mesin penyimpanan

MySQL mempunyai beberapa [storage engines](https://dev.mysql.com/doc/refman/en/storage-engines.html). Anda dapat merubah mesin penyimpanan awalan dalam konfigurasi peladen.

Mesin penyimpanan awalan MySQL adalah [InnoDB](https://dev.mysql.com/doc/refman/en/innodb-storage-engine.html). Mesin ini sepenuhnya transaksional dan mendukung acuan foreign key. Itu adalah pilihan dianjurkan. Bagaimanapun penghitung peningkatan otomatis InnoDB hilang pada pemulaian kembali MySQL karena itu tidak ingat nilai `AUTO_INCREMENT`, daripada membuat kembali itu sebagai "max(id)+1". Ini mungkin menghasilkan sebuah penggunaan kembali tidak sengaja dari nilai [`AutoField`](/id/5.2/ref/models/fields/#django.db.models.AutoField).

Kekurangan utama dari [MyISAM](https://dev.mysql.com/doc/refman/en/myisam-storage-engine.html) adalah bahwa itu tidak mendukung transaksi atau memaksa batasan foreign-key.

### Driver API DB MySQL

MySQL mempunyai sepasang driver yang menerapkan API Basisdata Python digambarkan dalam [**PEP 249**](https://peps.python.org/pep-0249/):

- [mysqlclient](https://pypi.org/project/mysqlclient/) is a native driver. It's **the recommended choice**.
- [MySQL Connector/Python](https://dev.mysql.com/downloads/connector/python/) adalah murni pengemudi Python dari Oracle yang tidak mewajibkan pustaka klien MySQL atau modul Python apapun diluar dari pustaka standar.

Sebagai tambahan pada pengemudi API DB, Django butuh sebuah penyadur mengakses pengemudi basisdata dari ORM nya. Django menyediakan sebuah penyadur untuk mysqlclient selagi Penghubung/Python MySQL termasuk [its own](https://dev.mysql.com/doc/connector-python/en/connector-python-django-backend.html).

#### mysqlclient

Django requires [mysqlclient](#mysqlclient) 1.4.3 or later.

#### Penghubung MySQL/Python

Penghubung/Python MySQL tersedia dari [download page](https://dev.mysql.com/downloads/connector/python/). Penyadur Django tersedia dalam versi 1.1.X dan terakhir. itu mungkin tidak mendukung kebanyakan terbitan terakhir dari Django.

### Pengertian zona waktu

Jika anda berencana menggunakan dukungan [timezone Django](/id/5.2/topics/i18n/timezones/), gunakan [mysql\_tzinfo\_to\_sql](https://dev.mysql.com/doc/refman/en/mysql-tzinfo-to-sql.html) untuk memuat tabel zona waktu kedalam basisdata MySQL. Ini harus dilakukan hanya sekali untuk peladen MySQL anda, bukan per basisdata.

### Membuat basisdata anda

You can [create your database](https://dev.mysql.com/doc/refman/en/create-database.html) using the command-line tools and this SQL:

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

Ini memastikan semua tabel dan kolom akan menggunakan UTF-8 secara awal.

#### Pengaturan pemeriksaan

The collation setting for a column controls the order in which data is sorted
as well as what strings compare as equal. You can specify the `db_collation`
parameter to set the collation name of the column for
[`CharField`](/id/5.2/ref/models/fields/#django.db.models.CharField.db_collation) and
[`TextField`](/id/5.2/ref/models/fields/#django.db.models.TextField.db_collation).

The collation can also be set on a database-wide level and per-table. This is
[documented thoroughly](https://dev.mysql.com/doc/refman/en/charset.html) in the MySQL documentation. In such cases, you must
set the collation by directly manipulating the database settings or tables.
Django doesn't provide an API to change them.

By default, with a UTF-8 database, MySQL will use the
`utf8mb4_0900_ai_ci` collation. This results in all string equality
comparisons being done in a *case-insensitive* manner. That is, `"Fred"` and
`"freD"` are considered equal at the database level. If you have a unique
constraint on a field, it would be illegal to try to insert both `"aa"` and
`"AA"` into the same column, since they compare as equal (and, hence,
non-unique) with the default collation. If you want case-sensitive comparisons
on a particular column or table, change the column or table to use the
`utf8mb4_0900_as_cs` collation.

Please note that according to [MySQL Unicode Character Sets](https://dev.mysql.com/doc/refman/en/charset-unicode-sets.html), comparisons for
the `utf8mb4_general_ci` collation are faster, but slightly less correct,
than comparisons for `utf8mb4_unicode_ci`. If this is acceptable for your
application, you should use `utf8mb4_general_ci` because it is faster. If
this is not acceptable (for example, if you require German dictionary order),
use `utf8mb4_unicode_ci` because it is more accurate.

> **Warning**
>
> Model formsets validate unique fields in a case-sensitive manner. Thus when
> using a case-insensitive collation, a formset with unique field values that
> differ only by case will pass validation, but upon calling `save()`, an
> `IntegrityError` will be raised.

### Menyambung ke basisdata

Mengacu ke [pengaturan dokumentasi](/id/5.2/ref/settings/).

Pengaturan hubungan digunakan dalam urutan ini:

1. [`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS).
2. [`NAME`](/id/5.2/ref/settings/#std-setting-NAME), [`USER`](/id/5.2/ref/settings/#std-setting-USER), [`PASSWORD`](/id/5.2/ref/settings/#std-setting-PASSWORD), [`HOST`](/id/5.2/ref/settings/#std-setting-HOST),
   [`PORT`](/id/5.2/ref/settings/#std-setting-PORT)
3. Berkas pilihan MySQL.

Dengan kata lain, jika anda mensetel nama dari basisdata dalam [`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS), ini akan mengambil hak lebih tinggi terhadap [`NAME`](/id/5.2/ref/settings/#std-setting-NAME), yang akan menimpa apapin dalam [MySQL option file](https://dev.mysql.com/doc/refman/en/option-files.html).

Ini adalah contoh konfigurasi yang menggunakan berkas pilihan 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
```

Beberapa [MySQLdb connection options](https://mysqlclient.readthedocs.io/user_guide.html#functions-and-attributes) lain mungkin berguna, seperti `ssl`, `init_command`, dan `sql_mode`.

#### Mengatur `sql_mode`

The default value of the `sql_mode` option contains `STRICT_TRANS_TABLES`.
That option escalates warnings into errors when data are truncated upon
insertion, so Django highly recommends activating a [strict mode](https://dev.mysql.com/doc/refman/en/sql-mode.html#sql-mode-strict) for MySQL to
prevent data loss (either `STRICT_TRANS_TABLES` or `STRICT_ALL_TABLES`).

Jika anda butuh menyesuaiakan suasana SQL, anda dapat mensetel variabel `sql_mode` seperti pilihan MySQL lain: antara dalam berkas konfigurasi atau dengan masukan `'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"` dalam bagian [`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS) dari konfigurasi basisdata anda dalam [`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES).

#### Tingkat terpencil

Ketika menjalankan pemuatan yang bersamaan, transaksi basisdata dari sesi-sesi berbeda (katakan, urutan lain menangani permintaan berbeda) mungkin berinteraksi dengan satu sama lain. Interaksi ini mungkin dipengaruhi oleh setiap [transaction isolation level](https://dev.mysql.com/doc/refman/en/innodb-transaction-isolation-levels.html) sesi. Anda dapat mensetel tingkat terpencil hubungan dengan sebuah masukan `'isolation_level'` dalam [`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS) bagian dari konfigurasi basisdata anda dalam [`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES). Nilai sah untuk masukan ini adalah empat sandar tingkat terpencil:

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

or `None` to use the server's configured isolation level. However, Django
works best with and defaults to read committed rather than MySQL's default,
repeatable read. Data loss is possible with repeatable read. In particular,
you may see cases where [`get_or_create()`](/id/5.2/ref/models/querysets/#django.db.models.query.QuerySet.get_or_create)
will raise an [`IntegrityError`](/id/5.2/ref/exceptions/#django.db.IntegrityError) but the object won't appear in
a subsequent [`get()`](/id/5.2/ref/models/querysets/#django.db.models.query.QuerySet.get) call.

### Membuat tabel anda

Ketika Django membangkitkan skema, itu tidak menentukan sebuah mesin penyimpanan, jadi tabel-tabel akan dibuat dengan apapun mesin penyimpanan awalan paladen basisdata anda dikonfigurasikan. Pemecahan paling mudah adalah mensetel mesin penyimpanan awalan peladen basisdata anda pada mesin yang diinginkan.

Jika anda sedang menggunakan layanan rumahan dan tidak dapat merubah mesin penyimpanan awalan peladen, anda memiliki sepasang pilihan.

- After the tables are created, execute an `ALTER TABLE` statement to
  convert a table to a new storage engine (such as InnoDB):

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

  Ini dapat membosankan jika anda memiliki banyak tabel.
- Pilihan lain adalah menggunakan pilihan `init_command` untuk MySQLdb sebelum membuat tabel anda:

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

  Ini menyetel mesin penyimpanan awalan diatas hubungan ke basisdata. Setelah tabel-tabel anda telah dibuat, anda harus memindahkan pilihan ini ketika itu menambahkan sebuah permintaan yaitu hanya dibutuhkan selama pembautan tabel pada setiap hubungan basisdata.

### Nama tabel

Ada [known issues](https://bugs.mysql.com/bug.php?id=48875) di bahkan versi terakhir dari MySQL yang dapat menyebabkan kasus dari nama tabel dirubah ketika pernyataan SQL tertentu dijalankan dibawah kondisi tertentu. Itu dianjurkan bahwa anda menggunakan nama tabel huruf kecil, jika memungkinkan, untuk menghindari masalah apapun yang mungkin muncul dari perilaku ini. Django menggunakan nama tabel huruf kecil ketika it membangkitkan-otomatis nama tabel dari mdoel, jadi ini adalah pertimbangan utama jika anda sedang menimpa nama tabel melalui parameter [`db_table`](/id/5.2/ref/models/options/#django.db.models.Options.db_table).

### Savepoint

Kedua ORM Django dan MySQL (ketika menggunakan InnoDB [storage engine](#mysql-storage-engines)) mendukung basisdata [savepoints](/id/5.2/topics/db/transactions/#topics-db-transactions-savepoints).

If you use the MyISAM storage engine please be aware of the fact that you will
receive database-generated errors if you try to use the [savepoint-related
methods of the transactions API](/id/5.2/topics/db/transactions/#topics-db-transactions-savepoints). The reason
for this is that detecting the storage engine of a MySQL database/table is an
expensive operation so it was decided it isn't worth to dynamically convert
these methods in no-op's based in the results of such detection.

### Catatan pada tabel khusus

#### Bidang karakter

Any fields that are stored with `VARCHAR` column types may have their
`max_length` restricted to 255 characters if you are using `unique=True`
for the field. This affects [`CharField`](/id/5.2/ref/models/fields/#django.db.models.CharField),
[`SlugField`](/id/5.2/ref/models/fields/#django.db.models.SlugField). See [the MySQL documentation](https://dev.mysql.com/doc/refman/en/create-index.html#create-index-column-prefixes) for more
details.

#### Batasan `TextField`

MySQL hanya dapat mengindeks karakter N pertama dari kolom `BLOB` atau `TEXT`. Sejak `TextField` tidak memiliki panjang yang ditentukan, anda tidak dapat menanda itu sebagai `unique=True`. MySQLakan melaporkan: "kolom BLOB/TEXT '\<db\_column\>' digunakan dalam spesifikasi kunci tanpa panjang kunci".

#### Pecahan kedua mendukung untuk bidang Time dan DateTime

MySQL can store fractional seconds, provided that the column definition
includes a fractional indication (e.g. `DATETIME(6)`).

Django will not upgrade existing columns to include fractional seconds if the
database server supports it. If you want to enable them on an existing database,
it's up to you to either manually update the column on the target database, by
executing a command like:

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

atau menggunakan tindakan [`RunSQL`](/id/5.2/ref/migration-operations/#django.db.migrations.operations.RunSQL) dalam [data migration](/id/5.2/topics/migrations/#data-migrations).

#### Kolom `TIMESTAMP`

Jika anda menggunakan sebuah basisdata warisan yang mengandung kolom `TIMESTAMP`, anda harus mensetel [`USE_TZ = False`](/id/5.2/ref/settings/#std-setting-USE_TZ) untuk menghindari kerusakan data. [`inspectdb`](/id/5.2/ref/django-admin/#django-admin-inspectdb) memetakan kolom-kolom ini pada [`DateTimeField`](/id/5.2/ref/models/fields/#django.db.models.DateTimeField) dan jika anda mengadakan dukungan zona waktu, kedua MySQL dan Django akan berusaha merubah nilai-nilai dari  UTC ke waktu lokal.

### Penguncian baris dengan `QuerySet.select_for_update()`

MySQL and MariaDB do not support some options to the `SELECT ... FOR UPDATE`
statement. If `select_for_update()` is used with an unsupported option, then
a [`NotSupportedError`](/id/5.2/ref/exceptions/#django.db.NotSupportedError) is raised.

| Option | MariaDB | MySQL |
| --- | --- | --- |
| `SKIP LOCKED` | X (≥10.6) | X |
| `NOWAIT` | X | X |
| `OF` |  | X |
| `NO KEY` |  |  |

When using `select_for_update()` on MySQL, make sure you filter a queryset
against at least a set of fields contained in unique constraints or only
against fields covered by indexes. Otherwise, an exclusive write lock will be
acquired over the full table for the duration of the transaction.

### Typecasting otomatis dapat menggunakan hasil tidak diharapkan

Ketika melakukan sebuah permintaan pada jenis string, tetapi dengan sebuah nilai integer, MySQL akan memaksa jenis-jenis dari semua nilai dalam tabel pada sebuah integer sebelum melakukan perbandingan. Jika tabel-tabel anda mengandung nilai `'abc'`, `'def'` dan permintaan anda untuk `WHERE mycolumn=0`, kedua baris akan cocok. Mirip, `WHERE mycolumn=1` akan cocok nilai `'abc1'`. Karena itu, bidang-bidang jenis string disertakan dalam Django akan selalu melempar nilai ke sebuah string sebelum menggunakan itu dalam sebuah permintaan.

Jika anda menerapkan bdiang model penyesuaian yang mewarisi dari [`Field`](/id/5.2/ref/models/fields/#django.db.models.Field) directly, adalah menimpa [`get_prep_value()`](/id/5.2/ref/models/fields/#django.db.models.Field.get_prep_value), atau menggunakan [`RawSQL`](/id/5.2/ref/models/expressions/#django.db.models.expressions.RawSQL), [`extra()`](/id/5.2/ref/models/querysets/#django.db.models.query.QuerySet.extra), atau [`raw()`](/id/5.2/topics/db/sql/#django.db.models.Manager.raw), anda harus memastikan bahwa anda melakukan typecasting yang sesuai.

## Catatan SQLite

Django supports SQLite 3.31.0 and later.

[SQLite](https://www.sqlite.org/) menyediakan cara lain pengembangan yang bagus untuk aplikasi-aplikasi yang terutama hanya-baca atau membutuhkan jejak kaki pemasangan terkecil. Seperti semua peladen basisdata, meskipun, ada beberapa perbendaan yang khusus pada SQLite yang anda harus waspadai.

### Substring matching and case sensitivity

For all SQLite versions, there is some slightly counterintuitive behavior when
attempting to match some types of strings.  These are triggered when using the
[`iexact`](/id/5.2/ref/models/querysets/#std-fieldlookup-iexact) or [`contains`](/id/5.2/ref/models/querysets/#std-fieldlookup-contains) filters in querysets. The behavior
splits into two cases:

\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`](/id/5.2/ref/models/querysets/#std-fieldlookup-iexact) filter will behave exactly
the same as the [`exact`](/id/5.2/ref/models/querysets/#std-fieldlookup-exact) filter in these cases.

Some possible workarounds for this are [documented at sqlite.org](https://www.sqlite.org/faq.html#q18), but they
aren't utilized by the default SQLite backend in Django, as incorporating them
would be fairly difficult to do robustly. Thus, Django exposes the default
SQLite behavior and you should be aware of this when doing case-insensitive or
substring filtering.

### Decimal handling

SQLite has no real decimal internal type. Decimal values are internally
converted to the `REAL` data type (8-byte IEEE floating point number), as
explained in the [SQLite datatypes documentation](https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes), so they don't support
correctly-rounded decimal floating point arithmetic.

### Kesalahan "Basisdata terkunci"

SQLite berarti menjadi basisdata ringan, dan demikian tidak dapat mendukung bersamaan tingkat tinggi. Kesalahan `OperationalError: bassidata dikunci` menunjukkan bahwa aplikasi anda berpengalaman lebih bersamaan daripada `sqlite` dapat tangani dalam konfigurasi awalan. Kesalahan ini berarti bahwa satu antrian atau proses mempunyai sebuah kunci khusus pada hubungan basisdata dan waktu habis antrian lain menunggu untuk kunci dibebaskan.

Pembungkus SQLite Python mempunyai nilai waktu habis awalan yang menentukan seberapa lama detik urutan diizinkan untuk menunggu penguncian sebelum itu berakhir dan memunculkan kesalahan `OperationalError: database is locked`.

Jika anda mendapatkan kesalahan ini, anda dapat menyelesaikannya dengan:

- Berganti ke backend basisdata lain. Pada titik tertentu SQLite menjadi terlalu "ringan" untuk aplikasi dunia-sebenarnya, dan urutan kesalahan bersamaan ini menunjukkan anda telah mencapat titik itu.
- Menulis kembali kode anda untuk mengurangi bersamaan dan memastikan transaksi basisdata adalah berumur-pendek.
- Meningkatkan nilai waktu habis awalan dengan mengatur pilihan basisdata `timeout`:

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

  This will make SQLite wait a bit longer before throwing "database is locked"
  errors; it won't really do anything to solve them.

#### Transactions behavior

> **New in Django 5.1**

SQLite supports three transaction modes: `DEFERRED`, `IMMEDIATE`, and
`EXCLUSIVE`.

The default is `DEFERRED`. If you need to use a different mode, set it in the
[`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS) part of your database configuration in
[`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES), for example:

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

To make sure your transactions wait until `timeout` before raising "Database
is Locked", change the transaction mode to `IMMEDIATE`.

For the best performance with `IMMEDIATE` and `EXCLUSIVE`, transactions
should be as short as possible. This might be hard to guarantee for all of your
views so the usage of [`ATOMIC_REQUESTS`](/id/5.2/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS) is
discouraged  in this case.

For more information see [Transactions in SQLite](https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions).

### `QuerySet.select_for_update()` tidak didukung

SQLite tidak mendukung sintaksis `SELECT ... FOR UPDATE`. Memanggil itu tidak akan memiliki pengaruh.

### Pengucilan ketika menggunakan `QuerySet.iterator()`

There are special considerations described in [Isolation In SQLite](https://www.sqlite.org/isolation.html) when
modifying a table while iterating over it using [`QuerySet.iterator()`](/id/5.2/ref/models/querysets/#django.db.models.query.QuerySet.iterator). If
a row is added, changed, or deleted within the loop, then that row may or may
not appear, or may appear twice, in subsequent results fetched from the
iterator. Your code must handle this.

### Enabling JSON1 extension on SQLite

To use [`JSONField`](/id/5.2/ref/models/fields/#django.db.models.JSONField) on SQLite, you need to enable the
[JSON1 extension](https://www.sqlite.org/json1.html) on Python's [`sqlite3`](https://docs.python.org/3/library/sqlite3.html#module-sqlite3) library. If the extension is
not enabled on your installation, a system error (`fields.E180`) will be
raised.

To enable the JSON1 extension you can follow the instruction on
[the wiki page](https://code.djangoproject.com/wiki/JSON1Extension).

> **Note**
>
> The JSON1 extension is enabled by default on SQLite 3.38+.

### Setting pragma options

> **New in Django 5.1**

[Pragma options](https://www.sqlite.org/pragma.html) can be set upon connection by using the `init_command` in
the [`OPTIONS`](/id/5.2/ref/settings/#std-setting-OPTIONS) part of your database configuration in
[`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES). The example below shows how to enable extra durability of
synchronous writes and change the `cache_size`:

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

## Catatan Oracle

Django supports [Oracle Database Server](https://www.oracle.com/) versions 19c and higher. Version
2.3.0 or higher of the [oracledb](https://oracle.github.io/python-oracledb/) Python driver is required.

> **Deprecated since Django 5.0**
>
> Ditinggalkan sejak versi 5.0: Support for `cx_Oracle` is deprecated.

Untuk perintah `python manage.py migrate` bekerja, pengguna basisdata Oracle anda harus mempunyai hak istimewa untuk menjalankan perintah berikut:

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

Untuk menjalankan deretan percobaan proyek, pengguna biasanya butuh hak *tambahan* ini:

- 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

Selagi peran `RESOURCE` mempunyai hak istimewa yang diwajibkan `CREATE TABLE`, `CREATE SEQUENCE`, `CREATE PROCEDURE`, dan ```CREATE TRIGGER`, dan seorang pengguna diberikan ``RESOURCE WITH ADMIN OPTION``` dapat memberikan `RESOURCE`, pengguna seperti itu tidak dapat memberikan hak istimewa sendiri (yaitu `CREATE TABLE`), dan demikian `RESOURCE WITH ADMIN OPTION` tidak biasanya cukup untuk menjalankan percobaan.

Some test suites also create views or materialized views; to run these, the
user also needs `CREATE VIEW WITH ADMIN OPTION` and
`CREATE MATERIALIZED VIEW WITH ADMIN OPTION` privileges. In particular, this
is needed for Django's own test suite.

Semua hak iswimewa ini disertakan dalam peran DBA, yang sesuai untuk digunakan pada basisdata pengembang pribadi.

Backend basisdata Oracle menggunakan paket `SYS.DBMS_LOB` dan `SYS.DBMS_RANDOM`, jadi pengguna anda akan membutuhkan menjalankan perizinan padanya. Itu secara biasa dapat diakses ke semua pengguna secara awal, tetapi di kasus itu tidak, anda akan butuh memberikan perizinan seperti itu:

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

### Menyambung ke basisdata

Untuk menghubungkan menggunakan nama layanan dari basisdata Oracle anda, berkas `settings.py` anda harus terlihat seperti ini:

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

Dalam kasus ini, anda harus meninggakan kedua [`HOST`](/id/5.2/ref/settings/#std-setting-HOST) dan [`PORT`](/id/5.2/ref/settings/#std-setting-PORT) kosong. Bagaimanapun, jika anda tidak menggunakan berkas `tnsnames.ora` atau metode penamaan mirip dan ingin berhubungan menggunakan SID ("xe" dalam contoh ini), kemudian isi kedua [`HOST`](/id/5.2/ref/settings/#std-setting-HOST) dan [`PORT`](/id/5.2/ref/settings/#std-setting-PORT) seperti itu:

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

Anda harus salah andara mendukung kedua [`HOST`](/id/5.2/ref/settings/#std-setting-HOST) and [`PORT`](/id/5.2/ref/settings/#std-setting-PORT), atau meninggalkan kedua sebagai string kosong. Django akan menggunakan deskriptor hubungan berbeda tergantung pada pilihan itu.

#### DSN dan Easy Connect penuh

Sebuah Full DSN atau string Easy Connect dapat digunakan dalam [`NAME`](/id/5.2/ref/settings/#std-setting-NAME) jika kedua [`HOST`](/id/5.2/ref/settings/#std-setting-HOST) dan [`PORT`](/id/5.2/ref/settings/#std-setting-PORT) adalah kosong. Bentuk ini diwajibkan ketika menggunakan RAC atau basisdata tertanam tanpa `tnsnames.ora`, sebagai contoh.

Contoh dari Easy Connect string:

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

Contoh dari string DSN penuh:

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

### Connection pool

> **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`](/id/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,
        },
    },
}
```

To pass custom parameters to the driver's [create\_pool()](https://python-oracledb.readthedocs.io/en/latest/user_guide/connection_handling.html#connection-pooling)  function, you can
alternatively set `"pool"` to be a dict:

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

### Pilihan urutan

Jika anda berencana menjalankan Django dalam lingkungan banyak antrian (yaitu Apache menggunakan modul MPM awalan pada sistem operasi modern apapun), kemudian anda **harus** mensetel pilihan `threaded` dari konfigurasi basisdata Oracle anda menjadi `True`:

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

Kegagalam melakukan ini akan menyebabkan tabrakan dan perilaku ganjil lain.

### INSERT ... RETURNING INTO

Secara awalan, backend Oracle menggunakan klausa `RETURNING INTO` untuk efesian mengambil nilai dari `AutoField` ketika memasukkan baris baru. Perilaku ini mungkin menghasilkan sebuah `DatabaseError` dallam pengaturan tidak biasa tertentu, seperti ketika memasukkan kedalam tabel jauh, atau kedalam sebuah tampilan dengan sebuah pemicu `INSTEAD OF`. Klausa `RETURNING INTO` dapat ditiadakan dengan mengatur pilihan `use_returning_into` dari konfigurasi basisdata menjadi `False`:

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

Dalam kasus ini, backend Oracle akan menggunakan permintaan `SELECT` terpisah untuk mengambil nilai-nilai `AutoField`.

### Masalah penamaan

Oracle memaksakan batasan panjang nama dari 30 karakter. Untuk mengakomodasi ini, backend memotong penciri basisdata agar cocok, mengganti empat karakter akhir dari nama terpotong dengan sebuah nilai campuran MD5 berulang. Sebagai tambahan, backend merubah penciri basisdata menjadi semua-huruf-besar.

Untuk mencegah perubahan ini (ini biasanya hanya membutuhkan ketika berhubungan dengan basisdata warisan atau mengakses tabel-tabel yang milik pengguna lain), gunakan sebuah nama terkutip sebagai nilai untuk `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"'
```

Nama terkutip dapat juga digunakan dengan backend basisdata didukung lain Django; kecuali untuk Oracle, bagaimanapun, kutipan tidak mempunyai pengaruh.

Ketika menjalankan `migrate`, sebuah kesalahan `ORA-06552` mungkin ditemui jika kata kunci Oracle tertentu digunakan sebagai nama dari sebuah bidang model atau nilai dari sebuah pilihan `db_column`. Django mengutip semua penciri digunakan dalam permintaan untuk mencegah kebanyakan masalah seperti itu, tetapi kesalahan ini dapat masih muncul ketika sebuah jenis data oracle digunakan sebagai sebuah nama kolom. Khususnya, hati-hati menghindari penggunaan nama-nama `date`, `timestamp`, `number` atau `float` sebagai nama bidang.

### String NULL dan kosong

Django umumnya memilih menggunakan string kosong (`''`) daripada `NULL`, tetapi Oracle memperlakukan keduanya mirip. Untuk menyiasati ini, backend Oracle mengabaikan pilihan `null` tersirat pada bidang yang mempunyai string kosong sebagai nilai kemungkinan dan membangkitkan DDL seolah-olah `null=True`. Ketika mengambil dari basisdata, itu dianggap bahwa sebuah nilai `NULL` dalam satu dari bidang-bidang ini sangat berarti string kosong, dan data secara diam dirubah untuk mencerminkan anggapan ini.

### Batasan `TextField`

The Oracle backend stores each `TextField` as an `NCLOB` column. Oracle
imposes some limitations on the usage of such LOB columns in general:

- Kolom LOB tidak boleh digunakan sebagai primary key.
- Kolom LOB tidak boleh digunakan sebagai indeks.
- Kolom LOB mugnkin tidak digunakan dalam daftar `SELECT DISTINCT`. Ini berarti bahwa mencoba menggunakan metode `QuerySet.distinct` pada sebuah model yang menyertakan kolom `TextField` akan menghasilkan dalam sebuah kesalahan `ORA-00932` ketika berjalan terhadap Oracle. Sebagai pemecahannya, gunakan metode `QuerySet.defer` dalam berhubungan dengan `distinct()` untuk mencegah kolom `TextField` dari menjadi disertakan dalam daftar `SELECT DISTINCT`.

## Subclassing the built-in database backends

Django comes with built-in database backends. You may subclass an existing
database backends to modify its behavior, features, or configuration.

Consider, for example, that you need to change a single database feature.
First, you have to create a new directory with a `base` module in it. For
example:

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

The `base.py` module must contain a class named `DatabaseWrapper` that
subclasses an existing engine from the `django.db.backends` module. Here's an
example of subclassing the PostgreSQL engine to change a feature class
`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
```

Akhirnya, anda harus menentukan ``` DATABASE-ENGINE`di berkas ``settings.py` ``` anda:

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

You can see the current list of database engines by looking in
[django/db/backends](https://github.com/django/django/blob/stable/5.2.x/django/db/backends).

## Menggunakan backend basisdata pihak ketiga

Sebagai tambahan pada basisdata didukung resmi, ada backend disediakan oleh pihak ketiga yang mengizinkan anda menggunakan basisdata lain dengan 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/)

Versi Django dan fitur ORM didukung oleh backend tidak resmi sangat beragam. Permintaan mengenai kemampuan khusus dari backend tidak resmi ini, bersama dengan permintaan didukung apapun, harus diarahkan ke saluran pendukung disediakan oleh proyek pihak ke3.
