{"title":"数据库","version":"6.0","locale":"zh-hans","docname":"ref/databases","url":"/zh-hans/6.0/ref/databases/","canonical":"https://djangodocs.dev/zh-hans/6.0/ref/databases/","summary":"Django 官方支持以下数据库： PostgreSQL MariaDB MySQL Oracle SQLite 还有一些第三方提供的 数据库后端 。 Django 试图在所有数据库后端上支持尽可能多的功能。然而，并不是所有的数据库后端都是一样的，我们不得不在设计上决定支持哪些功能，以及我们可以安全地做出哪些假设。…","html":"<h1>数据库<a class=\"heading-anchor\" href=\"#databases\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django 官方支持以下数据库：</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"#postgresql-notes\"><span class=\"std std-ref\">PostgreSQL</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#mariadb-notes\"><span class=\"std std-ref\">MariaDB</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#mysql-notes\"><span class=\"std std-ref\">MySQL</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#oracle-notes\"><span class=\"std std-ref\">Oracle</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#sqlite-notes\"><span class=\"std std-ref\">SQLite</span></a></p></li>\n</ul>\n<p>还有一些第三方提供的 <a class=\"reference internal\" href=\"#third-party-notes\"><span class=\"std std-ref\">数据库后端</span></a>。</p>\n<p>Django 试图在所有数据库后端上支持尽可能多的功能。然而，并不是所有的数据库后端都是一样的，我们不得不在设计上决定支持哪些功能，以及我们可以安全地做出哪些假设。</p>\n<p>该文件描述了一些可能与 Django 使用有关的功能。 它不能替代特定于服务器的文档或参考手册。</p>\n<section id=\"general-notes\">\n<h2>通用注意事项<a class=\"heading-anchor\" href=\"#general-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"persistent-connections\">\n<span id=\"persistent-database-connections\"></span><h3>持久连接<a class=\"heading-anchor\" href=\"#persistent-connections\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>持久连接避免了在每个 HTTP 请求中重新建立与数据库的连接的开销。它们由 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a> 参数控制，该参数定义了连接的最大生命周期。它可以独立设置在每个数据库上。</p>\n<p>默认值是 <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code>，保留了每次请求结束时关闭数据库连接的历史行为。要启用持久连接，可将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a> 设置为正整数秒。对于无限制的持久连接，将其设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>。</p>\n<p>When using ASGI, persistent connections should be disabled. Instead, use your\ndatabase backend's built-in connection pooling if available, or investigate a\nthird-party connection pooling option if required.</p>\n<section id=\"connection-management\">\n<h4>连接管理<a class=\"heading-anchor\" href=\"#connection-management\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>当 Django 第一次进行数据库查询时，就会打开一个与数据库的连接。它保持这个连接的开放性，并在以后的请求中重复使用。一旦连接超过了 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a> 所定义的最大时长，或者当它不再可用时，Django 就会关闭这个连接。</p>\n<p>详细来说，Django 每当需要连接数据库而又没有连接的时候，就会自动打开一个连接到数据库——或者是因为这是第一个连接，或者是因为之前的连接被关闭。</p>\n<p>在每次请求开始时，如果连接已达到最大时长，Django 就会关闭连接。如果你的数据库在一段时间后终止了空闲的连接，你应该将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a> 设置为一个较低的值，这样 Django 就不会尝试使用一个已经被数据库服务器终止的连接。（这个问题可能只影响到流量很低的网站。）</p>\n<p>在每个请求结束时，如果连接已达到其最大寿命或处于不可恢复的错误状态，Django 将关闭连接。如果在处理请求时发生了任何数据库错误，Django 会检查连接是否仍然可用，如果不可用，将关闭连接。因此，数据库错误最多会影响每个应用程序工作线程的一个请求；如果连接变得无法使用，下一个请求将获得一个新的连接。</p>\n<p>将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CONN_HEALTH_CHECKS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_HEALTH_CHECKS</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 可以用于提高连接复用的健壮性，并防止在连接已被数据库服务器关闭且现在已准备好接受和提供新连接时发生错误，例如在数据库服务器重新启动后。健康检查只在每个请求中执行一次，只有在处理请求期间访问数据库时才会执行。</p>\n</section>\n<section id=\"caveats\">\n<h4>附加说明<a class=\"heading-anchor\" href=\"#caveats\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>由于每个线程都维护自己的连接，所以你的数据库必须支持至少与你的工作线程一样多的同时连接。</p>\n<p>有时，数据库不会被大多数视图访问，例如因为它是外部系统的数据库，或者由于缓存的原因。在这种情况下，你应该将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a> 设置为一个低值，甚至 <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code>，因为维护一个不太可能被重复使用的连接是没有意义的。这将有助于保持这个数据库的同时连接数较少。</p>\n<p>开发服务器每处理一个请求都会创建一个新的线程，消除了持久连接的影响。在开发过程中不要启用它们。</p>\n<p>当 Django 建立与数据库的连接时，它会根据所使用的后端设置相应的参数。如果你启用了持久化连接，就不再每次请求都重复这种设置。如果你修改了连接的隔离级别或时区等参数，你应该在每次请求结束时恢复 Django 的默认值，在每次请求开始时强制设置一个合适的值，或者禁用持久连接。</p>\n<p>如果在 Django 的请求-响应周期之外的长运行进程中创建了连接，该连接将保持打开状态，直到显式关闭或超时发生。你可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.close_old_connections()</span></code> 来关闭所有旧的或不可用的连接。</p>\n</section>\n</section>\n<section id=\"encoding\">\n<h3>编码<a class=\"heading-anchor\" href=\"#encoding\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 假设所有的数据库都使用 UTF-8 编码。使用其他编码可能会导致意外的行为，比如数据库中的数据在 Django 中是有效的，却出现“value too long”的错误。关于如何正确设置数据库，请参考下面的数据库具体说明。</p>\n</section>\n</section>\n<section id=\"postgresql-notes\">\n<span id=\"id1\"></span><h2>PostgreSQL 注意事项<a class=\"heading-anchor\" href=\"#postgresql-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django supports PostgreSQL 14 and higher. <a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/\">psycopg</a> 3.1.12+ or <a class=\"reference external\" href=\"https://www.psycopg.org/\">psycopg2</a>\n2.9.9+ is required, though the latest <a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/\">psycopg</a> 3.1.12+ is recommended.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>对 <code class=\"docutils literal notranslate\"><span class=\"pre\">psycopg2</span></code> 的支持可能会在将来的某个时候被弃用并移除。</p>\n</aside>\n<section id=\"postgresql-connection-settings\">\n<span id=\"id2\"></span><h3>PostgreSQL 连接配置<a class=\"heading-anchor\" href=\"#postgresql-connection-settings\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>详见 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a>。</p>\n<p>要使用 <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/libpq-pgpass.html\">连接服务文件</a> 中的服务名称和 <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/libpq-pgservice.html\">密码文件</a> 中的密码进行连接，你必须在数据库配置中的 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">:settings:`OPTIONS`</span></a> 部分指定它们。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.postgresql&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;service&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;my_service&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;passfile&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;.my_pgpass&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></figure>\n<figure class=\"code-block code-block-captioned\" data-language=\"text\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">.pg_service.conf</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>[my_service]\nhost=localhost\nuser=USER\ndbname=NAME\nport=5432\n</code></pre></figure>\n<figure class=\"code-block code-block-captioned\" data-language=\"text\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">.my_pgpass</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>localhost:5432:NAME:USER:PASSWORD\n</code></pre></figure>\n<p>PostgreSQL 后端将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> 的内容作为关键字参数传递给连接构造函数，从而允许更高级地控制驱动程序的行为。所有可用的 <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS\">parameters</a> 在 PostgreSQL 文档中都有详细描述。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>出于测试目的不支持使用服务名称。这个 <a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/33685\">可能会在以后实现</a>。</p>\n</aside>\n</section>\n<section id=\"optimizing-postgresql-s-configuration\">\n<h3>优化 PostgreSQL 的配置<a class=\"heading-anchor\" href=\"#optimizing-postgresql-s-configuration\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 的数据库连接需要以下参数：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">client_encoding</span></code>：<code class=\"docutils literal notranslate\"><span class=\"pre\">'UTF8'</span></code>，</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">default_transaction_isolation</span></code>：<code class=\"docutils literal notranslate\"><span class=\"pre\">'read</span> <span class=\"pre\">committed'</span></code> 默认情况下，或在连接选项中设置的值（见下文）。</p></li>\n<li><dl class=\"simple\">\n<dt><code class=\"docutils literal notranslate\"><span class=\"pre\">timezone</span></code>：</dt><dd><ul>\n<li><p>当 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-USE_TZ\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">USE_TZ</span></code></a> 为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 时，默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">'UTC</span></code>，或 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-TIME_ZONE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TIME_ZONE</span></code></a> 为连接设置的值。</p></li>\n<li><p>当 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-USE_TZ\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">USE_TZ</span></code></a> 为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> 时，全局 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-TIME_ZONE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TIME_ZONE</span></code></a> 设置的值。</p></li>\n</ul>\n</dd>\n</dl>\n</li>\n</ul>\n<p>如果这些参数已经有了正确的值，Django 就不会为每个新的连接设置这些参数，这样可以稍微提高性能。你可以直接在 <code class=\"file docutils literal notranslate\"><span class=\"pre\">postgresql.conf</span></code> 中设置它们，或者更方便地在每个数据库用户中用 <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/sql-alterrole.html\">ALTER ROLE</a> 设置。</p>\n<p>如果没有这个优化，Django 也能正常工作，但每个新的连接都会做一些额外的查询来设置这些参数。</p>\n</section>\n<section id=\"isolation-level\">\n<span id=\"database-isolation-level\"></span><h3>隔离等级<a class=\"heading-anchor\" href=\"#isolation-level\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>和 PostgreSQL 本身一样，Django 默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">READ</span> <span class=\"pre\">COMMITTED</span></code> <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/transaction-iso.html\">隔离级别</a> 。如果你需要更高的隔离级别，比如 <code class=\"docutils literal notranslate\"><span class=\"pre\">REPEATABLE</span> <span class=\"pre\">READ</span></code> 或者 <code class=\"docutils literal notranslate\"><span class=\"pre\">SERIALIZABLE</span></code>，可以在数据库配置的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 中的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> 部分进行设置：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.backends.postgresql.psycopg_any</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">IsolationLevel</span>\n\n<span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;isolation_level&quot;</span><span class=\"p\">:</span> <span class=\"n\">IsolationLevel</span><span class=\"o\">.</span><span class=\"n\">SERIALIZABLE</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>在更高的隔离级别下，你的应用程序应该准备好处理序列化失败时引发的异常。这个选项是为进阶用途设计的。</p>\n</aside>\n</section>\n<section id=\"role\">\n<span id=\"database-role\"></span><h3>角色<a class=\"heading-anchor\" href=\"#role\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>If you need to use a different role for database connections than the role used\nto establish the connection, set it in the <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> part of your\ndatabase configuration in <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.postgresql&quot;</span><span class=\"p\">,</span>\n        <span class=\"c1\"># ...</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;assume_role&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;my_application_role&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n</section>\n<section id=\"connection-pool\">\n<span id=\"postgresql-pool\"></span><h3>连接池<a class=\"heading-anchor\" href=\"#connection-pool\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>要将连接池与 <a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/\">psycopg</a> 一起使用，你可以在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 的数据库配置的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> 部分将 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;pool&quot;</span></code> 设置为传递给 <a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/docs/api/pool.html#psycopg_pool.ConnectionPool\" title=\"(in psycopg)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ConnectionPool</span></code></a> 的字典，或设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">ConnectionPool</span></code> 的默认值：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.postgresql&quot;</span><span class=\"p\">,</span>\n        <span class=\"c1\"># ...</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;pool&quot;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>此选项需要安装 <code class=\"docutils literal notranslate\"><span class=\"pre\">psycopg[pool]</span></code> 或 <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/psycopg-pool/\">psycopg-pool</a>，并且在使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">psycopg2</span></code> 时会被忽略。</p>\n</section>\n<section id=\"server-side-parameters-binding\">\n<span id=\"database-server-side-parameters-binding\"></span><h3>服务器端参数绑定<a class=\"heading-anchor\" href=\"#server-side-parameters-binding\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>使用 <a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/\">psycopg</a> 3.1.8+，Django 默认使用 <a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/docs/advanced/cursors.html#client-side-binding-cursors\" title=\"(in psycopg)\"><span class=\"xref std std-ref\">客户端端绑定游标</span></a>。如果想要使用 <a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/docs/basic/from_pg2.html#server-side-binding\" title=\"(in psycopg)\"><span class=\"xref std std-ref\">服务器端绑定</span></a>，请在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 中的数据库配置的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> 部分进行设置：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.postgresql&quot;</span><span class=\"p\">,</span>\n        <span class=\"c1\"># ...</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;server_side_binding&quot;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>这个选项在 <code class=\"docutils literal notranslate\"><span class=\"pre\">psycopg2</span></code> 中被忽略。</p>\n</section>\n<section id=\"indexes-for-varchar-and-text-columns\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">varchar</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">text</span></code> 列的索引。<a class=\"heading-anchor\" href=\"#indexes-for-varchar-and-text-columns\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>When specifying <code class=\"docutils literal notranslate\"><span class=\"pre\">db_index=True</span></code> on your model fields, Django typically\noutputs a single <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">INDEX</span></code> statement. However, if the database type\nfor the field is either <code class=\"docutils literal notranslate\"><span class=\"pre\">varchar</span></code> or <code class=\"docutils literal notranslate\"><span class=\"pre\">text</span></code> (e.g., used by <code class=\"docutils literal notranslate\"><span class=\"pre\">CharField</span></code>,\n<code class=\"docutils literal notranslate\"><span class=\"pre\">FileField</span></code>, and <code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code>), then Django will create\nan additional index that uses an appropriate <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/indexes-opclass.html\">PostgreSQL operator class</a>\nfor the column. The extra index is necessary to correctly perform\nlookups that use the <code class=\"docutils literal notranslate\"><span class=\"pre\">LIKE</span></code> operator in their SQL, as is done with the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">contains</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">startswith</span></code> lookup types.</p>\n</section>\n<section id=\"migration-operation-for-adding-extensions\">\n<h3>添加扩展的迁移操作<a class=\"heading-anchor\" href=\"#migration-operation-for-adding-extensions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果你需要使用迁移来添加 PostgreSQL 扩展（如 <code class=\"docutils literal notranslate\"><span class=\"pre\">hstore</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">postgis</span></code> 等），请使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/contrib/postgres/operations/#django.contrib.postgres.operations.CreateExtension\" title=\"django.contrib.postgres.operations.CreateExtension\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CreateExtension</span></code></a> 操作。</p>\n</section>\n<section id=\"server-side-cursors\">\n<span id=\"postgresql-server-side-cursors\"></span><h3>服务器端游标<a class=\"heading-anchor\" href=\"#server-side-cursors\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>在使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/querysets/#django.db.models.query.QuerySet.iterator\" title=\"django.db.models.query.QuerySet.iterator\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">QuerySet.iterator()</span></code></a> 时，Django 打开了一个 <a class=\"reference external\" href=\"https://www.psycopg.org/psycopg3/docs/advanced/cursors.html#server-side-cursors\" title=\"(in psycopg)\"><span class=\"xref std std-ref\">服务器端游标</span></a>。默认情况下，PostgreSQL 假定游标查询结果的前 10% 将被获取。查询计划器在规划查询时花费更少的时间，开始更快地返回结果，但如果获取的结果超过 10%，性能可能会下降。PostgreSQL 对游标查询的行数假设是由 <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-CURSOR-TUPLE-FRACTION\">cursor_tuple_fraction</a> 选项控制的。</p>\n<section id=\"transaction-pooling-and-server-side-cursors\">\n<span id=\"transaction-pooling-server-side-cursors\"></span><h4>事务池和服务器端游标<a class=\"heading-anchor\" href=\"#transaction-pooling-and-server-side-cursors\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>在事务池模式下使用连接池（如 <a class=\"reference external\" href=\"https://www.pgbouncer.org/\">PgBouncer</a> ）需要禁用该连接的服务器端游标。</p>\n<p>服务器端游标是本地连接，当 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASE-AUTOCOMMIT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTOCOMMIT</span></code></a> 为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 时，服务器端游标在事务结束时保持开放。后续事务可能会尝试从服务器端游标中获取更多的结果。在事务池模式下，不能保证后续事务会使用同一个连接。如果使用了不同的连接，当事务引用服务器端游标时就会出现错误，因为服务器端游标只有在创建它们的连接中才能访问。</p>\n<p>一种解决方案是在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 中通过将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASE-DISABLE_SERVER_SIDE_CURSORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DISABLE_SERVER_SIDE_CURSORS</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 来禁用连接的服务器端游标。</p>\n<p>为了从事务池模式下的服务器端游标中获益，你可以设置 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/db/multi-db/\"><span class=\"doc\">与数据库的另一个连接</span></a>，以便执行使用服务器端游标的查询。这个连接需要直接连接到数据库或者连接到会话池模式下的连接池。</p>\n<p>另一种选择是将每个使用服务器端游标的 <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> 包裹在一个 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/db/transactions/#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> 块中，因为它在事务的持续时间内禁用 <code class=\"docutils literal notranslate\"><span class=\"pre\">autocommit</span></code>。这样一来，服务器端游标将只在事务持续时间内有效。</p>\n</section>\n</section>\n<section id=\"manually-specifying-values-of-auto-incrementing-primary-keys\">\n<span id=\"manually-specified-autoincrement-pk\"></span><h3>手动指定自增主键的值。<a class=\"heading-anchor\" href=\"#manually-specifying-values-of-auto-incrementing-primary-keys\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 使用 PostgreSQL 的 identity 列来存储自增的主键。一个 identity 列会通过一个 <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/sql-createsequence.html\">sequence</a> 来填充值，该 sequence 跟踪下一个可用的值。手动为自增字段分配一个值不会更新字段的 sequence，这可能会导致后续冲突。例如：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">User</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"o\">=</span><span class=\"s2\">&quot;alice&quot;</span><span class=\"p\">,</span> <span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;User: alice&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># The sequence hasn&#39;t been updated; its next value is 1.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"o\">=</span><span class=\"s2\">&quot;bob&quot;</span><span class=\"p\">)</span>\n<span class=\"go\">IntegrityError: duplicate key value violates unique constraint</span>\n<span class=\"go\">&quot;auth_user_pkey&quot; DETAIL:  Key (id)=(1) already exists.</span>\n</code></pre></div>\n<p>如果你需要指定这样的值，请在之后重置序列以避免重复使用已经在表中的值。<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django-admin-sqlsequencereset\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">sqlsequencereset</span></code></a> 管理命令会生成 SQL 语句来做到这一点。</p>\n</section>\n<section id=\"test-database-templates\">\n<h3>测试数据库模板<a class=\"heading-anchor\" href=\"#test-database-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>你可以使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-TEST_TEMPLATE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TEST['TEMPLATE']</span></code></a> 配置来指定一个 <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/sql-createdatabase.html\">template</a> （例如 <code class=\"docutils literal notranslate\"><span class=\"pre\">'template0'</span></code>）来创建测试数据库。</p>\n</section>\n<section id=\"speeding-up-test-execution-with-non-durable-settings\">\n<h3>使用非持久设置加快测试执行速度。<a class=\"heading-anchor\" href=\"#speeding-up-test-execution-with-non-durable-settings\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>你可以通过 <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/non-durability.html\">将 PostgreSQL 配置为非持久</a> 来加快测试执行时间。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>这是很危险的：它将使你的数据库在服务器崩溃或断电的情况下更容易发生数据丢失或损坏。只有在开发机器上使用，在那里你可以轻松的恢复集群中所有数据库的全部内容。</p>\n</aside>\n</section>\n</section>\n<section id=\"mariadb-notes\">\n<span id=\"id4\"></span><h2>MariaDB 注意事项<a class=\"heading-anchor\" href=\"#mariadb-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django supports MariaDB 10.6 and higher.</p>\n<p>要使用 MariaDB，请使用 MySQL 后端，两者共享。详情请看 <a class=\"reference internal\" href=\"#mysql-notes\"><span class=\"std std-ref\">MySQL 注意事项</span></a>。</p>\n</section>\n<section id=\"mysql-notes\">\n<span id=\"id5\"></span><h2>MySQL 注意事项<a class=\"heading-anchor\" href=\"#mysql-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"version-support\">\n<h3>版本支持<a class=\"heading-anchor\" href=\"#version-support\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 支持 MySQL 8.0.11 及更高版本。</p>\n<p>Django 的 <code class=\"docutils literal notranslate\"><span class=\"pre\">inspectdb</span></code> 功能使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">information_schema</span></code> 数据库，其中包含所有数据库架构的详细数据。</p>\n<p>Django 希望数据库支持 Unicode（UTF-8 编码），并将执行事务和引用完整性的任务交给它。需要注意的是，MySQL 在使用 MyISAM 存储引擎时，后两项其实并没有强制执行，参见下一节。</p>\n</section>\n<section id=\"storage-engines\">\n<span id=\"mysql-storage-engines\"></span><h3>存储引擎<a class=\"heading-anchor\" href=\"#storage-engines\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>MySQL 有几个 <a class=\"reference internal\" href=\"#storage-engines\">存储引擎</a> 。你可以在服务器配置中更改默认的存储引擎。</p>\n<p>MySQL 的默认存储引擎是 <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/innodb-storage-engine.html\">InnoDB</a> 。这个引擎是完全事务性的，并且支持外键引用。这是推荐的选择。然而，InnoDB 自动增量计数器在 MySQL 重启时丢失，因为它不记得 <code class=\"docutils literal notranslate\"><span class=\"pre\">AUTO_INCREMENT</span></code> 值，而是将其重新创建为 &quot;max(id)+1&quot;。这可能会导致无意中重用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/fields/#django.db.models.AutoField\" title=\"django.db.models.AutoField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AutoField</span></code></a> 值。</p>\n<p><a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/myisam-storage-engine.html\">MyISAM</a> 的主要缺点是不支持事务，也不执行外键约束。</p>\n</section>\n<section id=\"mysql-db-api-drivers\">\n<span id=\"id7\"></span><h3>MySQL 数据库 API 驱动程序<a class=\"heading-anchor\" href=\"#mysql-db-api-drivers\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>MySQL 有几个驱动程序实现了 <span class=\"target\" id=\"index-2\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0249/\"><strong>PEP 249</strong></a> 中描述的 Python 数据库 API。</p>\n<ul class=\"simple\">\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/mysqlclient/\">mysqlclient</a> 是一个本地的数据库驱动程序。它是 <strong>推荐的选择</strong>。</p></li>\n<li><p><a class=\"reference external\" href=\"https://dev.mysql.com/downloads/connector/python/\">MySQL Connector/Python</a> 是一个来自 Oracle 的纯 Python 驱动，不需要 MySQL 客户端库或标准库之外的任何 Python 模块。</p></li>\n</ul>\n<p>除了数据库 API 驱动之外，Django 还需要一个适配器来从其 ORM 中访问数据库驱动。Django 为 mysqlclient 提供了一个适配器，而 MySQL Connector/Python 则包含了 <a class=\"reference external\" href=\"https://dev.mysql.com/doc/connector-python/en/connector-python-django-backend.html\">自己的</a> 。</p>\n<section id=\"mysqlclient\">\n<h4>mysqlclient<a class=\"heading-anchor\" href=\"#mysqlclient\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Django requires <a class=\"reference internal\" href=\"#mysqlclient\">mysqlclient</a> 2.2.1 or later.</p>\n</section>\n<section id=\"id8\">\n<h4>MySQL Connector/Python<a class=\"heading-anchor\" href=\"#id8\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>MySQL Connector/Python 可从 <a class=\"reference external\" href=\"https://dev.mysql.com/downloads/connector/python/\">下载页面</a> 。Django 适配器在 1.1.X 及以后的版本中可用。它可能不支持最新版本的 Django。</p>\n</section>\n</section>\n<section id=\"time-zone-definitions\">\n<span id=\"mysql-time-zone-definitions\"></span><h3>时区定义<a class=\"heading-anchor\" href=\"#time-zone-definitions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果你打算使用 Django 的 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/i18n/timezones/\"><span class=\"doc\">时区支持</span></a>，使用 <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/mysql-tzinfo-to-sql.html\">mysql_tzinfo_to_sql</a> 将时区表加载到 MySQL 数据库中。这只需要为你的 MySQL 服务器做一次，而不是每个数据库。</p>\n</section>\n<section id=\"creating-your-database\">\n<h3>创建你的数据库<a class=\"heading-anchor\" href=\"#creating-your-database\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>你可以使用命令行工具并执行以下 SQL 语句来 <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/create-database.html\">创建数据库</a>：</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">DATABASE</span><span class=\"w\"> </span><span class=\"o\">&lt;</span><span class=\"n\">dbname</span><span class=\"o\">&gt;</span><span class=\"w\"> </span><span class=\"nb\">CHARACTER</span><span class=\"w\"> </span><span class=\"k\">SET</span><span class=\"w\"> </span><span class=\"n\">utf8mb4</span><span class=\"p\">;</span>\n</code></pre></div>\n<p>这确保了所有的表和列默认使用 UTF-8。</p>\n<section id=\"collation-settings\">\n<span id=\"mysql-collation\"></span><h4>字符序配置<a class=\"heading-anchor\" href=\"#collation-settings\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>一列的字符序配置控制了数据排序的顺序，以及哪些字符串被比较为相等。你可以指定 <code class=\"docutils literal notranslate\"><span class=\"pre\">db_collation</span></code> 参数来为 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/fields/#django.db.models.CharField.db_collation\" title=\"django.db.models.CharField.db_collation\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">CharField</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/fields/#django.db.models.TextField.db_collation\" title=\"django.db.models.TextField.db_collation\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">TextField</span></code></a> 设置列的字符序名称。</p>\n<p>字符序也可以在整个数据库层面和每张表上设置。这在 MySQL 文档中有详细的记录。在这种情况下，你必须通过直接操作数据库配置或表来设置字符序。Django 并没有提供一个 API 来改变它们。</p>\n<p>By default, with a UTF-8 database, MySQL will use the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">utf8mb4_0900_ai_ci</span></code> collation. This results in all string equality\ncomparisons being done in a <em>case-insensitive</em> manner. That is, <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;Fred&quot;</span></code> and\n<code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;freD&quot;</span></code> are considered equal at the database level. If you have a unique\nconstraint on a field, it would be illegal to try to insert both <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;aa&quot;</span></code> and\n<code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;AA&quot;</span></code> into the same column, since they compare as equal (and, hence,\nnon-unique) with the default collation. If you want case-sensitive comparisons\non a particular column or table, change the column or table to use the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">utf8mb4_0900_as_cs</span></code> collation.</p>\n<p>Please note that according to <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/charset-unicode-sets.html\">MySQL Unicode Character Sets</a>, comparisons for\nthe <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8mb4_general_ci</span></code> collation are faster, but slightly less correct,\nthan comparisons for <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8mb4_unicode_ci</span></code>. If this is acceptable for your\napplication, you should use <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8mb4_general_ci</span></code> because it is faster. If\nthis is not acceptable (for example, if you require German dictionary order),\nuse <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8mb4_unicode_ci</span></code> because it is more accurate.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>模型表格集以区分大小写的方式验证唯一字段。因此，当使用不区分大小写的字符序方式时，一个具有唯一字段值的表单集，如果只因大小写不同，将通过验证，但在调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> 时，将引发 <code class=\"docutils literal notranslate\"><span class=\"pre\">IntegrityError</span></code>。</p>\n</aside>\n</section>\n</section>\n<section id=\"connecting-to-the-database\">\n<h3>连接数据库<a class=\"heading-anchor\" href=\"#connecting-to-the-database\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>参考 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/\"><span class=\"doc\">配置文档</span></a>。</p>\n<p>连接配置应按此顺序使用</p>\n<ol class=\"arabic simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a>。</p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">NAME</span></code></a>、<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-USER\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">USER</span></code></a>、<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-PASSWORD\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD</span></code></a>、<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a>、<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-PORT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PORT</span></code></a></p></li>\n<li><p>MySQL 选项文件。</p></li>\n</ol>\n<p>换句话说，如果你在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> 中设置数据库的名称，这将优先于 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">NAME</span></code></a>，它将覆盖 <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/option-files.html\">MySQL 选项文件</a> 中的任何内容。</p>\n<p>下面是一个使用 MySQL 选项文件的配置示例：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"c1\"># settings.py</span>\n<span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.mysql&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;read_default_file&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;/path/to/my.cnf&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<div class=\"code-block\" data-language=\"ini\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Ini</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Ini code\"><code><span class=\"c1\"># my.cnf</span>\n<span class=\"k\">[client]</span>\n<span class=\"na\">database</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">NAME</span>\n<span class=\"na\">user</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">USER</span>\n<span class=\"na\">password</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">PASSWORD</span>\n<span class=\"na\">default-character-set</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">utf8mb4</span>\n</code></pre></div>\n<p>其他几个 <a class=\"reference external\" href=\"https://mysqlclient.readthedocs.io/user_guide.html#functions-and-attributes\">MySQLdb 连接选项</a> 可能会有用，比如 <code class=\"docutils literal notranslate\"><span class=\"pre\">ssl</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">init_command</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">sql_mode</span></code>。</p>\n<section id=\"setting-sql-mode\">\n<span id=\"mysql-sql-mode\"></span><h4>设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">sql_mode</span></code><a class=\"heading-anchor\" href=\"#setting-sql-mode\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">sql_mode</span></code> 选项的默认值包含 <code class=\"docutils literal notranslate\"><span class=\"pre\">STRICT_TRANS_TABLES</span></code>。该选项在插入时将警告升级为错误，因此 Django 强烈建议在 MySQL 中激活 <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/sql-mode.html#sql-mode-strict\">strict mode</a>，以防止数据丢失（可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">STRICT_TRANS_TABLES</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">STRICT_ALL_TABLES</span></code>）。</p>\n<p>如果你需要自定义 SQL 模式，你可以像其他 MySQL 选项一样设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">sql_mode</span></code> 变量：可以在配置文件中设置，也可以在你的数据库配置的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> 部分的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 中使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">'init_command':</span> <span class=\"pre\">&quot;SET</span> <span class=\"pre\">sql_mode='STRICT_TRANS_TABLES'&quot;</span></code> 配置。</p>\n</section>\n<section id=\"mysql-isolation-level\">\n<span id=\"id9\"></span><h4>隔离等级<a class=\"heading-anchor\" href=\"#mysql-isolation-level\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>当运行并发负载时，来自不同会话的数据库事务（例如，处理不同请求的独立线程）可能会相互交互。这些交互受到每个会话的 <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/innodb-transaction-isolation-levels.html\">事务隔离级别</a> 的影响。你可以在数据库配置的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 中的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> 部分设置连接的隔离级别，并在其中设置一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">'isolation_level'</span></code> 条目。这个条目的有效值是四个标准隔离级别：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'read</span> <span class=\"pre\">uncommitted'</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'read</span> <span class=\"pre\">committed'</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'repeatable</span> <span class=\"pre\">read'</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'serializable'</span></code></p></li>\n</ul>\n<p>或 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> 来使用服务器配置的隔离级别。然而，Django 的最佳工作方式和默认值是 read committed，而不是 MySQL 的默认 repeatable read。在使用 repeatable read 时，可能会出现数据丢失的情况。特别是，你可能会看到这样的情况：<code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_or_create()</span></code> 会引发一个 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/exceptions/#django.db.IntegrityError\" title=\"django.db.IntegrityError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">IntegrityError</span></code></a>，但在随后的 <code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code> 调用中不会出现该对象。</p>\n</section>\n</section>\n<section id=\"creating-your-tables\">\n<h3>创建你的表<a class=\"heading-anchor\" href=\"#creating-your-tables\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>当 Django 生成架构时，它并没有指定存储引擎，所以无论你的数据库服务器配置了什么默认的存储引擎，都会创建表。最简单的解决方案是将数据库服务器的默认存储引擎设置为所需的引擎。</p>\n<p>如果你使用的是托管服务，无法更改服务器的默认存储引擎，你有几个选择。</p>\n<ul>\n<li><p>在创建表之后，执行一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">ALTER</span> <span class=\"pre\">TABLE</span></code> 语句来将表转换为新的存储引擎（例如 InnoDB）：</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"o\">&lt;</span><span class=\"n\">tablename</span><span class=\"o\">&gt;</span><span class=\"w\"> </span><span class=\"n\">ENGINE</span><span class=\"o\">=</span><span class=\"n\">INNODB</span><span class=\"p\">;</span>\n</code></pre></div>\n<p>如果你有很多表，这可能会很繁琐。</p>\n</li>\n<li><p>另一个选择是在创建表之前使用 MySQLdb 的 <code class=\"docutils literal notranslate\"><span class=\"pre\">init_command</span></code> 选项：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;init_command&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;SET default_storage_engine=INNODB&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>这将设置连接到数据库时的默认存储引擎。在你的表创建后，你应该删除这个选项，因为它为每个数据库连接添加了一个只在表创建期间需要的查询。</p>\n</li>\n</ul>\n</section>\n<section id=\"table-names\">\n<h3>表名称<a class=\"heading-anchor\" href=\"#table-names\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>即使在最新版本的 MySQL 中，也有一些 <a class=\"reference external\" href=\"https://bugs.mysql.com/bug.php?id=48875\">已知问题</a> ，当在某些条件下执行某些 SQL 语句时，可能会导致表名的大小写被改变。如果可能的话，建议你使用小写的表名，以避免这种行为可能产生的任何问题。Django 在从模型中自动生成表名时使用小写表名，所以这主要是考虑到如果你是通过 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/options/#django.db.models.Options.db_table\" title=\"django.db.models.Options.db_table\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">db_table</span></code></a> 参数来覆盖表名。</p>\n</section>\n<section id=\"savepoints\">\n<h3>保存点<a class=\"heading-anchor\" href=\"#savepoints\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django ORM 和 MySQL（使用 InnoDB <a class=\"reference internal\" href=\"#mysql-storage-engines\"><span class=\"std std-ref\">存储引擎</span></a> 时）都支持数据库 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/db/transactions/#topics-db-transactions-savepoints\"><span class=\"std std-ref\">保存点</span></a>。</p>\n<p>如果你使用 MyISAM 存储引擎，请注意，如果你试图使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/db/transactions/#topics-db-transactions-savepoints\"><span class=\"std std-ref\">事务 API 的保存点相关方法</span></a>，你将收到数据库生成的错误。原因是检测 MySQL 数据库／表的存储引擎是一个昂贵的操作，所以决定不值得在没有操作的情况下动态转换这些方法，基于这种检测的结果。</p>\n</section>\n<section id=\"notes-on-specific-fields\">\n<h3>特定字段的注意事项<a class=\"heading-anchor\" href=\"#notes-on-specific-fields\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<section id=\"character-fields\">\n<span id=\"mysql-character-fields\"></span><h4>字符字段<a class=\"heading-anchor\" href=\"#character-fields\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>如果你对字段使用了 <code class=\"docutils literal notranslate\"><span class=\"pre\">unique=True</span></code>，那么任何以 <code class=\"docutils literal notranslate\"><span class=\"pre\">VARCHAR</span></code> 列类型存储的字段可能会被 <code class=\"docutils literal notranslate\"><span class=\"pre\">max_length</span></code> 限制为255个字符。这将影响 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/fields/#django.db.models.CharField\" title=\"django.db.models.CharField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CharField</span></code></a>、<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/fields/#django.db.models.SlugField\" title=\"django.db.models.SlugField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SlugField</span></code></a>。更多细节请看 <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/create-index.html#create-index-column-prefixes\">MySQL 文档</a> 。</p>\n</section>\n<section id=\"textfield-limitations\">\n<h4><code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code> 限制<a class=\"heading-anchor\" href=\"#textfield-limitations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>MySQL 只能对 <code class=\"docutils literal notranslate\"><span class=\"pre\">BLOB</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">TEXT</span></code> 列的前 N 个字符进行索引。由于 <code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code> 没有定义的长度，所以不能将其标记为 <code class=\"docutils literal notranslate\"><span class=\"pre\">unique=True</span></code>。MySQL 会报告：&quot;BLOB/TEXT column '&lt;db_column&gt;' used in key specification without a key length&quot;。</p>\n</section>\n<section id=\"fractional-seconds-support-for-time-and-datetime-fields\">\n<span id=\"mysql-fractional-seconds\"></span><h4>支持时间和 DateTime 字段的小数秒。<a class=\"heading-anchor\" href=\"#fractional-seconds-support-for-time-and-datetime-fields\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>MySQL 可以存储小数秒，只要列的定义包括一个小数指示（例如 <code class=\"docutils literal notranslate\"><span class=\"pre\">DATETIME(6)</span></code>）。</p>\n<p>Django 不会在数据库服务器支持的情况下升级现有列以包含小数秒。如果要在现有数据库上启用它们，你需要手动在目标数据库上更新列，通过执行类似以下命令：</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"o\">`</span><span class=\"n\">your_table</span><span class=\"o\">`</span><span class=\"w\"> </span><span class=\"k\">MODIFY</span><span class=\"w\"> </span><span class=\"o\">`</span><span class=\"n\">your_datetime_column</span><span class=\"o\">`</span><span class=\"w\"> </span><span class=\"n\">DATETIME</span><span class=\"p\">(</span><span class=\"mi\">6</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>或在 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/migrations/#data-migrations\"><span class=\"std std-ref\">数据迁移</span></a> 中使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/migration-operations/#django.db.migrations.operations.RunSQL\" title=\"django.db.migrations.operations.RunSQL\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RunSQL</span></code></a> 操作。</p>\n</section>\n<section id=\"timestamp-columns\">\n<h4><code class=\"docutils literal notranslate\"><span class=\"pre\">TIMESTAMP</span></code> 列<a class=\"heading-anchor\" href=\"#timestamp-columns\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>如果你使用的是包含 <code class=\"docutils literal notranslate\"><span class=\"pre\">TIMESTAMP</span></code> 列的遗留数据库，你必须设置 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-USE_TZ\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">USE_TZ</span> <span class=\"pre\">=</span> <span class=\"pre\">False</span></code></a> 以避免数据损坏。 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django-admin-inspectdb\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">inspectdb</span></code></a> 将这些列映射到 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a>，如果你启用了时区支持，MySQL 和 Django 都会尝试将值从 UTC 转换为当地时间。</p>\n</section>\n</section>\n<section id=\"row-locking-with-queryset-select-for-update\">\n<h3>用 <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.select_for_update()</span></code> 锁定行<a class=\"heading-anchor\" href=\"#row-locking-with-queryset-select-for-update\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>MySQL 和 MariaDB 不支持 <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span> <span class=\"pre\">...</span> <span class=\"pre\">FOR</span> <span class=\"pre\">UPDATE</span></code> 语句的某些选项。如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">select_for_update()</span></code> 与一个不支持的选项一起使用，那么就会引发一个 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/exceptions/#django.db.NotSupportedError\" title=\"django.db.NotSupportedError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">NotSupportedError</span></code></a>。</p>\n<div class=\"table-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"Table\"><table class=\"docutils align-default\">\n<thead>\n<tr class=\"row-odd\"><th class=\"head\"><p>选项</p></th>\n<th class=\"head\"><p>MariaDB</p></th>\n<th class=\"head\"><p>MySQL</p></th>\n</tr>\n</thead>\n<tbody>\n<tr class=\"row-even\"><td><p><code class=\"docutils literal notranslate\"><span class=\"pre\">SKIP</span> <span class=\"pre\">LOCKED</span></code></p></td>\n<td><p>X</p></td>\n<td><p>X</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><code class=\"docutils literal notranslate\"><span class=\"pre\">NOWAIT</span></code></p></td>\n<td><p>X</p></td>\n<td><p>X</p></td>\n</tr>\n<tr class=\"row-even\"><td><p><code class=\"docutils literal notranslate\"><span class=\"pre\">OF</span></code></p></td>\n<td></td>\n<td><p>X</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><code class=\"docutils literal notranslate\"><span class=\"pre\">NO</span> <span class=\"pre\">KEY</span></code></p></td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>当在 MySQL 上使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">select_for_update()</span></code> 时，确保你至少针对唯一约束中包含的一组字段或仅针对索引覆盖的字段过滤查询集。否则，在事务过程中，将对整个表获得一个独占的写锁。</p>\n</section>\n<section id=\"automatic-typecasting-can-cause-unexpected-results\">\n<h3>自动排版会造成意想不到的结果<a class=\"heading-anchor\" href=\"#automatic-typecasting-can-cause-unexpected-results\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>当对字符串类型执行查询，但有一个整数值时，MySQL 会在执行比较之前将表中所有值的类型强制为整数。如果你的表中包含值 <code class=\"docutils literal notranslate\"><span class=\"pre\">'abc'</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">'def'</span></code>，而你查询 <code class=\"docutils literal notranslate\"><span class=\"pre\">WHERE</span> <span class=\"pre\">mycolumn=0</span></code>，两行都会匹配。同理，<code class=\"docutils literal notranslate\"><span class=\"pre\">WHERE</span> <span class=\"pre\">mycolumn=1</span></code> 将匹配值 <code class=\"docutils literal notranslate\"><span class=\"pre\">'abc1'</span></code>。因此，Django 中包含的字符串类型字段在查询中使用之前，总是会先将值转换为字符串。</p>\n<p>如果你实现的自定义模型字段直接继承自 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a>，覆盖 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/fields/#django.db.models.Field.get_prep_value\" title=\"django.db.models.Field.get_prep_value\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_prep_value()</span></code></a> 或者使用 <code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RawSQL</span></code>、<code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">extra()</span></code> 或者 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/db/sql/#django.db.models.Manager.raw\" title=\"django.db.models.Manager.raw\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">raw()</span></code></a>，你应该确保你执行了适当的类型化。</p>\n</section>\n</section>\n<section id=\"sqlite-notes\">\n<span id=\"id10\"></span><h2>SQLite 注意事项<a class=\"heading-anchor\" href=\"#sqlite-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django 支持 SQLite 3.31.0 及更高版本。</p>\n<p><a class=\"reference external\" href=\"https://www.sqlite.org/\">SQLite</a> 为以只读为主或需要较小安装空间的应用程序提供了一个很好的开发选择。不过，与所有数据库服务器一样，SQLite 也有一些特定的差异，你应该注意。</p>\n<section id=\"substring-matching-and-case-sensitivity\">\n<span id=\"sqlite-string-matching\"></span><h3>子串匹配和大小写敏感性<a class=\"heading-anchor\" href=\"#substring-matching-and-case-sensitivity\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>For all SQLite versions, there is some slightly counterintuitive behavior when\nattempting to match some types of strings. These are triggered when using the\n<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/querysets/#std-fieldlookup-iexact\"><code class=\"xref std std-lookup docutils literal notranslate\"><span class=\"pre\">iexact</span></code></a> or <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/querysets/#std-fieldlookup-contains\"><code class=\"xref std std-lookup docutils literal notranslate\"><span class=\"pre\">contains</span></code></a> filters in querysets. The behavior\nsplits into two cases:</p>\n<p>1. For substring matching, all matches are done case-insensitively. That is a\nfilter such as <code class=\"docutils literal notranslate\"><span class=\"pre\">filter(name__contains=&quot;aa&quot;)</span></code> will match a name of <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;Aabb&quot;</span></code>.</p>\n<p>2. For strings containing characters outside the ASCII range, all exact string\nmatches are performed case-sensitively, even when the case-insensitive options\nare passed into the query. So the <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/querysets/#std-fieldlookup-iexact\"><code class=\"xref std std-lookup docutils literal notranslate\"><span class=\"pre\">iexact</span></code></a> filter will behave exactly\nthe same as the <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/querysets/#std-fieldlookup-exact\"><code class=\"xref std std-lookup docutils literal notranslate\"><span class=\"pre\">exact</span></code></a> filter in these cases.</p>\n<p>一些可能的变通方法在 <a class=\"reference external\" href=\"https://www.sqlite.org/faq.html#q18\">sqlite.org 有记载</a> ，但是 Django 的默认 SQLite 后端并没有利用这些方法，因为将它们整合起来是相当困难的。因此，Django 暴露了默认的 SQLite 行为，当你进行大小写不敏感或子串过滤时，你应该注意这一点。</p>\n</section>\n<section id=\"decimal-handling\">\n<span id=\"sqlite-decimal-handling\"></span><h3>小数处理<a class=\"heading-anchor\" href=\"#decimal-handling\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>SQLite 没有真正的小数内部类型。小数值在内部转换为 <code class=\"docutils literal notranslate\"><span class=\"pre\">REAL</span></code> 数据类型（8 字节的 IEEE 浮点数），正如 <a class=\"reference external\" href=\"https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes\">SQLite 数据类型文档</a> 中所解释的那样，所以它们不支持正确舍入的小数浮点运算。</p>\n</section>\n<section id=\"database-is-locked-errors\">\n<h3>“Database is locked”错误<a class=\"heading-anchor\" href=\"#database-is-locked-errors\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>SQLite 是一个轻量级数据库，因此不能支持高并发。<code class=\"docutils literal notranslate\"><span class=\"pre\">OperationalError:</span> <span class=\"pre\">database</span> <span class=\"pre\">is</span> <span class=\"pre\">locked</span></code> 错误表明你的应用程序遇到的并发量超过了 <code class=\"docutils literal notranslate\"><span class=\"pre\">sqlite</span></code> 在默认配置下所能处理的范围。这个错误意味着一个线程或进程在数据库连接上有一个独占锁，另一个线程超时等待锁被释放。</p>\n<p>Python 的 SQLite 包装器有一个默认的超时值，这个超时值决定了第二个线程在超时并引发 <code class=\"docutils literal notranslate\"><span class=\"pre\">OperationalError:</span> <span class=\"pre\">database</span> <span class=\"pre\">is</span> <span class=\"pre\">locked</span></code> 错误之前允许在锁上等待多长时间。</p>\n<p>如果你遇到这种错误，你可以通过以下方式解决：</p>\n<ul>\n<li><p>切换到另一个数据库后端。到了一定程度，SQLite 对于现实世界的应用来说就会变得过于“精简”，这类并发错误表明你已经达到了这个程度。</p></li>\n<li><p>重写你的代码以减少并发性，并确保数据库事务是短暂的。</p></li>\n<li><p>通过设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">timeout</span></code> 数据库选项增加默认超时值：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"s2\">&quot;timeout&quot;</span><span class=\"p\">:</span> <span class=\"mi\">20</span><span class=\"p\">,</span>\n    <span class=\"c1\"># ...</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>这将使 SQLite 在抛出 “database is locked” 的错误之前等待更长的时间；它不会真正起到任何解决这些问题的作用。</p>\n</li>\n</ul>\n<section id=\"transactions-behavior\">\n<span id=\"sqlite-transaction-behavior\"></span><h4>事务行为<a class=\"heading-anchor\" href=\"#transactions-behavior\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>SQLite 支持三种事务模式：<code class=\"docutils literal notranslate\"><span class=\"pre\">DEFERRED</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">IMMEDIATE</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">EXCLUSIVE</span></code>。</p>\n<p>默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">DEFERRED</span></code>。如果你需要使用不同的模式，请在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 的数据库配置的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> 部分设置它，例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"s2\">&quot;transaction_mode&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;IMMEDIATE&quot;</span><span class=\"p\">,</span>\n    <span class=\"c1\"># ...</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>为了确保你的事务在引发“数据库被锁定”之前等待 <code class=\"docutils literal notranslate\"><span class=\"pre\">timeout</span></code>，请将事务模式更改为 <code class=\"docutils literal notranslate\"><span class=\"pre\">IMMEDIATE</span></code>。</p>\n<p>为了在 <code class=\"docutils literal notranslate\"><span class=\"pre\">IMMEDIATE</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">EXCLUSIVE</span></code> 模式下获得最佳性能，事务应尽可能短。这可能很难保证所有视图都满足，因此在这种情况下不鼓励使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ATOMIC_REQUESTS</span></code></a>。</p>\n<p>有关更多信息，请参阅 <a class=\"reference external\" href=\"https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions\">SQLite 中的事务</a>。</p>\n</section>\n</section>\n<section id=\"queryset-select-for-update-not-supported\">\n<h3>不支持 <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.select_for_update()</span></code><a class=\"heading-anchor\" href=\"#queryset-select-for-update-not-supported\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>SQLite 不支持 <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span> <span class=\"pre\">...</span> <span class=\"pre\">FOR</span> <span class=\"pre\">UPDATE</span></code> 语法。调用它不会有任何效果。</p>\n</section>\n<section id=\"isolation-when-using-queryset-iterator\">\n<span id=\"sqlite-isolation\"></span><h3>使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.iterator()</span></code> 时的隔离<a class=\"heading-anchor\" href=\"#isolation-when-using-queryset-iterator\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>当使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/querysets/#django.db.models.query.QuerySet.iterator\" title=\"django.db.models.query.QuerySet.iterator\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">QuerySet.iterator()</span></code></a> 在迭代表时修改表，有一些特殊的注意事项在 <a class=\"reference external\" href=\"https://www.sqlite.org/isolation.html\">SQLite 的隔离</a> 中描述。如果一条记录在循环中被添加、更改或删除，那么这条记录可能会出现，也可能不会出现，或者可能会在后续从迭代器中获取的结果中出现两次。你的代码必须处理这个问题。</p>\n</section>\n<section id=\"enabling-json1-extension-on-sqlite\">\n<span id=\"sqlite-json1\"></span><h3>在 SQLite 上启用 JSON1 扩展<a class=\"heading-anchor\" href=\"#enabling-json1-extension-on-sqlite\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>To use <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/models/fields/#django.db.models.JSONField\" title=\"django.db.models.JSONField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">JSONField</span></code></a> on SQLite, you need to enable the\n<a class=\"reference external\" href=\"https://www.sqlite.org/json1.html\">JSON1 extension</a> on Python's <a class=\"reference external\" href=\"https://docs.python.org/3/library/sqlite3.html#module-sqlite3\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">sqlite3</span></code></a> library. If the extension is\nnot enabled on your installation, a system error (<code class=\"docutils literal notranslate\"><span class=\"pre\">fields.E180</span></code>) will be\nraised.</p>\n<p>要启用 JSON1 扩展，你可以按照 <a class=\"reference external\" href=\"https://code.djangoproject.com/wiki/JSON1Extension\">wiki 页面</a> 上的说明进行操作。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>JSON1 扩展在 SQLite 3.38+ 上默认启用。</p>\n</aside>\n</section>\n<section id=\"setting-pragma-options\">\n<span id=\"sqlite-init-command\"></span><h3>设置 pragma 选项<a class=\"heading-anchor\" href=\"#setting-pragma-options\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>可以通过在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 的数据库配置的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> 部分中使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">init_command</span></code> 来在连接时设置 <a class=\"reference external\" href=\"https://www.sqlite.org/pragma.html\">Pragma 选项</a>。以下示例展示了如何启用同步写入的额外持久性并更改 <code class=\"docutils literal notranslate\"><span class=\"pre\">cache_size</span></code>：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.sqlite3&quot;</span><span class=\"p\">,</span>\n        <span class=\"c1\"># ...</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;init_command&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;PRAGMA synchronous=3; PRAGMA cache_size=2000;&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"oracle-notes\">\n<span id=\"id12\"></span><h2>Oracle 注意事项<a class=\"heading-anchor\" href=\"#oracle-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django supports <a class=\"reference external\" href=\"https://www.oracle.com/\">Oracle Database Server</a> versions 19c and higher. Version\n2.3.0 or higher of the <a class=\"reference external\" href=\"https://oracle.github.io/python-oracledb/\">oracledb</a> Python driver is required.</p>\n<p>为了使 <code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">manage.py</span> <span class=\"pre\">migrate</span></code> 命令有效，你的 Oracle 数据库用户必须拥有运行以下命令的权限：</p>\n<ul class=\"simple\">\n<li><p>CREATE TABLE</p></li>\n<li><p>CREATE SEQUENCE</p></li>\n<li><p>CREATE PROCEDURE</p></li>\n<li><p>CREATE TRIGGER</p></li>\n</ul>\n<p>要运行一个项目的测试套件，用户通常需要这些 <em>额外</em> 的权限：</p>\n<ul class=\"simple\">\n<li><p>CREATE USER</p></li>\n<li><p>ALTER USER</p></li>\n<li><p>DROP USER</p></li>\n<li><p>CREATE TABLESPACE</p></li>\n<li><p>DROP TABLESPACE</p></li>\n<li><p>CREATE SESSION WITH ADMIN OPTION</p></li>\n<li><p>CREATE TABLE WITH ADMIN OPTION</p></li>\n<li><p>CREATE SEQUENCE WITH ADMIN OPTION</p></li>\n<li><p>CREATE PROCEDURE WITH ADMIN OPTION</p></li>\n<li><p>CREATE TRIGGER WITH ADMIN OPTION</p></li>\n</ul>\n<p>虽然 <code class=\"docutils literal notranslate\"><span class=\"pre\">RESOURCE</span></code> 角色具有所需的 <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">TABLE</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">SEQUENCE</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">PROCEDURE</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">TRIGGER</span></code> 特权，被授予 <code class=\"docutils literal notranslate\"><span class=\"pre\">RESOURCE</span> <span class=\"pre\">WITH</span> <span class=\"pre\">ADMIN</span> <span class=\"pre\">OPTION</span></code> 的用户可以授予 <code class=\"docutils literal notranslate\"><span class=\"pre\">RESOURCE</span></code>，但这样的用户不能授予单个特权（如 <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">TABLE</span></code>），因此 <code class=\"docutils literal notranslate\"><span class=\"pre\">RESOURCE</span> <span class=\"pre\">WITH</span> <span class=\"pre\">ADMIN</span> <span class=\"pre\">OPTION</span></code> 通常不足以运行测试。</p>\n<p>有些测试套件还可以创建视图或实体化视图；要运行这些视图，用户还需要 <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">VIEW</span> <span class=\"pre\">WITH</span> <span class=\"pre\">ADMIN</span> <span class=\"pre\">OPTION</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">MATERIALIZED</span> <span class=\"pre\">VIEW</span> <span class=\"pre\">WITH</span> <span class=\"pre\">ADMIN</span> <span class=\"pre\">OPTION</span></code> 权限。尤其是 Django 自己的测试套件，更是需要这样的权限。</p>\n<p>这些权限都包含在 DBA 角色中，适合在个人开发者的数据库上使用。</p>\n<p>Oracle 数据库后台使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">SYS.DBMS_LOB</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">SYS.DBMS_RANDOM</span></code> 包，所以你的用户需要对它有执行权限。一般情况下，所有用户都可以访问它，但如果不是，你需要授予这样的权限。</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">GRANT</span><span class=\"w\"> </span><span class=\"k\">EXECUTE</span><span class=\"w\"> </span><span class=\"k\">ON</span><span class=\"w\"> </span><span class=\"n\">SYS</span><span class=\"p\">.</span><span class=\"n\">DBMS_LOB</span><span class=\"w\"> </span><span class=\"k\">TO</span><span class=\"w\"> </span><span class=\"k\">user</span><span class=\"p\">;</span>\n<span class=\"k\">GRANT</span><span class=\"w\"> </span><span class=\"k\">EXECUTE</span><span class=\"w\"> </span><span class=\"k\">ON</span><span class=\"w\"> </span><span class=\"n\">SYS</span><span class=\"p\">.</span><span class=\"n\">DBMS_RANDOM</span><span class=\"w\"> </span><span class=\"k\">TO</span><span class=\"w\"> </span><span class=\"k\">user</span><span class=\"p\">;</span>\n</code></pre></div>\n<section id=\"id13\">\n<h3>连接数据库<a class=\"heading-anchor\" href=\"#id13\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>要使用 Oracle 数据库的服务名进行连接，你的 <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code> 文件应该像这样：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.oracle&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;NAME&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;xe&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;USER&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;a_user&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;PASSWORD&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;a_password&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;HOST&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;PORT&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>在这种情况下，你应该把 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-PORT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PORT</span></code></a> 都留空。但是，如果你不使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">tnsnames.ora</span></code> 文件或类似的命名方法，而想使用 SID（本例中的“xe”）进行连接，则应像这样填写 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-PORT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PORT</span></code></a>。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.oracle&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;NAME&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;xe&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;USER&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;a_user&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;PASSWORD&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;a_password&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;HOST&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;dbprod01ned.mycompany.com&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;PORT&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;1540&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>你应该同时提供 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-PORT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PORT</span></code></a>，或者把这两个字符串都留为空。Django 会根据这个选择使用不同的连接描述符。</p>\n<section id=\"full-dsn-and-easy-connect\">\n<h4>完整的 DSN 和 Easy Connect<a class=\"heading-anchor\" href=\"#full-dsn-and-easy-connect\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>如果 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-PORT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PORT</span></code></a> 都是空的，可以在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">NAME</span></code></a> 中使用完整的 DSN 或 Easy Connect 字符串。例如，在使用 RAC 或没有 <code class=\"docutils literal notranslate\"><span class=\"pre\">tnsnames.ora</span></code> 的可插拔数据库时，需要使用这种格式。</p>\n<p>一个 Easy Connect 字符串的例子：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"s2\">&quot;NAME&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;localhost:1521/orclpdb1&quot;</span>\n</code></pre></div>\n<p>一个完整 DSN 字符串的例子：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"s2\">&quot;NAME&quot;</span><span class=\"p\">:</span> <span class=\"p\">(</span>\n    <span class=\"s2\">&quot;(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))&quot;</span>\n    <span class=\"s2\">&quot;(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))&quot;</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"oracle-pool\">\n<span id=\"id14\"></span><h3>连接池<a class=\"heading-anchor\" href=\"#oracle-pool\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<aside class=\"version-note version-added\" data-version=\"5.2\">\n<p class=\"version-note-title\">New in Django 5.2</p></aside>\n<p>To use a connection pool with <a class=\"reference external\" href=\"https://oracle.github.io/python-oracledb/\">oracledb</a>, set <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;pool&quot;</span></code> to <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> in the\n<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> part of your database configuration. This uses the driver's\n<a class=\"reference external\" href=\"https://python-oracledb.readthedocs.io/en/latest/user_guide/connection_handling.html#connection-pooling\">create_pool()</a> default values:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.oracle&quot;</span><span class=\"p\">,</span>\n        <span class=\"c1\"># ...</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;pool&quot;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>To pass custom parameters to the driver's <a class=\"reference external\" href=\"https://python-oracledb.readthedocs.io/en/latest/user_guide/connection_handling.html#connection-pooling\">create_pool()</a>  function, you can\nalternatively set <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;pool&quot;</span></code> to be a dict:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.db.backends.oracle&quot;</span><span class=\"p\">,</span>\n        <span class=\"c1\"># ...</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;pool&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n                <span class=\"s2\">&quot;min&quot;</span><span class=\"p\">:</span> <span class=\"mi\">1</span><span class=\"p\">,</span>\n                <span class=\"s2\">&quot;max&quot;</span><span class=\"p\">:</span> <span class=\"mi\">10</span><span class=\"p\">,</span>\n                <span class=\"c1\"># ...</span>\n            <span class=\"p\">}</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n</section>\n<section id=\"insert-returning-into\">\n<h3>INSERT ... RETURNING INTO<a class=\"heading-anchor\" href=\"#insert-returning-into\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>By default, the Oracle backend uses a <code class=\"docutils literal notranslate\"><span class=\"pre\">RETURNING</span> <span class=\"pre\">INTO</span></code> clause to efficiently\nretrieve the value of an <code class=\"docutils literal notranslate\"><span class=\"pre\">AutoField</span></code> when inserting new rows. This behavior\nmay result in a <code class=\"docutils literal notranslate\"><span class=\"pre\">DatabaseError</span></code> in certain unusual setups, such as when\ninserting into a remote table, or into a view with an <code class=\"docutils literal notranslate\"><span class=\"pre\">INSTEAD</span> <span class=\"pre\">OF</span></code> trigger.\nThe <code class=\"docutils literal notranslate\"><span class=\"pre\">RETURNING</span> <span class=\"pre\">INTO</span></code> clause can be disabled by setting the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">use_returning_into</span></code> option of the database configuration to <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;use_returning_into&quot;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>在这种情况下，Oracle 后端将使用一个单独的 <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span></code> 查询来检索 <code class=\"docutils literal notranslate\"><span class=\"pre\">AutoField</span></code> 值。</p>\n</section>\n<section id=\"naming-issues\">\n<h3>命名问题<a class=\"heading-anchor\" href=\"#naming-issues\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Oracle 规定名称长度限制为 30 个字符。为了适应这一限制，后端对数据库标识符进行截断以适应，用一个可重复的 MD5 哈希值替换截断后的名称的最后四个字符。此外，后端将数据库标识符变成全大写。</p>\n<p>为了防止这些转换（通常只有在处理遗留数据库或访问属于其他用户的表时才需要这样做），使用加引号的名称作为 <code class=\"docutils literal notranslate\"><span class=\"pre\">db_table</span></code>：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">LegacyModel</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        <span class=\"n\">db_table</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;&quot;name_left_in_lowercase&quot;&#39;</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">ForeignModel</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        <span class=\"n\">db_table</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;&quot;OTHER_USER&quot;.&quot;NAME_ONLY_SEEMS_OVER_30&quot;&#39;</span>\n</code></pre></div>\n<p>引用的名字也可以用在 Django 的其他支持的数据库后端；但是，除了 Oracle，引用没有任何效果。</p>\n<p>When running <code class=\"docutils literal notranslate\"><span class=\"pre\">migrate</span></code>, an <code class=\"docutils literal notranslate\"><span class=\"pre\">ORA-06552</span></code> error may be encountered if\ncertain Oracle keywords are used as the name of a model field or the\nvalue of a <code class=\"docutils literal notranslate\"><span class=\"pre\">db_column</span></code> option. Django quotes all identifiers used\nin queries to prevent most such problems, but this error can still\noccur when an Oracle datatype is used as a column name. In\nparticular, take care to avoid using the names <code class=\"docutils literal notranslate\"><span class=\"pre\">date</span></code>,\n<code class=\"docutils literal notranslate\"><span class=\"pre\">timestamp</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">number</span></code> or <code class=\"docutils literal notranslate\"><span class=\"pre\">float</span></code> as a field name.</p>\n</section>\n<section id=\"null-and-empty-strings\">\n<span id=\"oracle-null-empty-strings\"></span><h3>NULL 和空字符串<a class=\"heading-anchor\" href=\"#null-and-empty-strings\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 通常更喜欢使用空字符串（<code class=\"docutils literal notranslate\"><span class=\"pre\">''</span></code>）而不是 <code class=\"docutils literal notranslate\"><span class=\"pre\">NULL</span></code>，但 Oracle 对两者的处理是一样的。为了解决这个问题，Oracle 后端会忽略字段上显式的 <code class=\"docutils literal notranslate\"><span class=\"pre\">null</span></code> 选项，并将 <code class=\"docutils literal notranslate\"><span class=\"pre\">null=True</span></code> 生成 DDL。当从数据库中获取数据时，假定这些字段中的 <code class=\"docutils literal notranslate\"><span class=\"pre\">null</span></code> 值确实意味着空字符串，数据被默默地转换以反映这一假设。</p>\n</section>\n<section id=\"id15\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code> 限制<a class=\"heading-anchor\" href=\"#id15\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The Oracle backend stores each <code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code> as an <code class=\"docutils literal notranslate\"><span class=\"pre\">NCLOB</span></code> column. Oracle\nimposes some limitations on the usage of such LOB columns in general:</p>\n<ul class=\"simple\">\n<li><p>LOB 列不可作为主键使用。</p></li>\n<li><p>LOB 列不可用于索引中。</p></li>\n<li><p>LOB 列不能用于 <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span> <span class=\"pre\">DISTINCT</span></code> 列表中。这意味着，当与 Oracle 运行时，试图在包含 <code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code> 列的模型上使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.distinct</span></code> 方法将导致 <code class=\"docutils literal notranslate\"><span class=\"pre\">ORA-00932</span></code> 错误。作为一个变通办法，使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.defer</span></code> 方法与 <code class=\"docutils literal notranslate\"><span class=\"pre\">distinct()</span></code> 结合使用，以防止 <code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code> 列被包含在 <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span> <span class=\"pre\">DISTINCT</span></code> 列表中。</p></li>\n</ul>\n</section>\n</section>\n<section id=\"subclassing-the-built-in-database-backends\">\n<span id=\"subclassing-database-backends\"></span><h2>子类化内置数据库后端<a class=\"heading-anchor\" href=\"#subclassing-the-built-in-database-backends\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django comes with built-in database backends. You may subclass an existing\ndatabase backend to modify its behavior, features, or configuration.</p>\n<p>考虑一个情况，你需要改变一个数据库特性。首先，你需要创建一个包含一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">base</span></code> 模块的新目录，例如：</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>mysite/\n    ...\n    mydbengine/\n        __init__.py\n        base.py\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">base.py</span></code> 模块必须包含一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">DatabaseWrapper</span></code> 的类，它从 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.backends</span></code> 模块中子类化了一个现有的引擎。下面是一个子类化 PostgreSQL 引擎的例子，用来改变一个特征类 <code class=\"docutils literal notranslate\"><span class=\"pre\">allows_group_by_selected_pks_on_model</span></code>。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">mysite/mydbengine/base.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.backends.postgresql</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">base</span><span class=\"p\">,</span> <span class=\"n\">features</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">DatabaseFeatures</span><span class=\"p\">(</span><span class=\"n\">features</span><span class=\"o\">.</span><span class=\"n\">DatabaseFeatures</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">allows_group_by_selected_pks_on_model</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"kc\">True</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">DatabaseWrapper</span><span class=\"p\">(</span><span class=\"n\">base</span><span class=\"o\">.</span><span class=\"n\">DatabaseWrapper</span><span class=\"p\">):</span>\n    <span class=\"n\">features_class</span> <span class=\"o\">=</span> <span class=\"n\">DatabaseFeatures</span>\n</code></pre></figure>\n<p>最后，你必须在你的 <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code> 文件中指定一个 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-DATABASE-ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASE-ENGINE</span></code></a>：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;ENGINE&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;mydbengine&quot;</span><span class=\"p\">,</span>\n        <span class=\"c1\"># ...</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>你可以在 <a class=\"extlink-source reference external\" href=\"https://github.com/django/django/blob/stable/6.0.x/django/db/backends\">django/db/backends</a> 中查看当前的数据库引擎列表。</p>\n</section>\n<section id=\"using-a-3rd-party-database-backend\">\n<span id=\"third-party-notes\"></span><h2>使用第三方数据库后端<a class=\"heading-anchor\" href=\"#using-a-3rd-party-database-backend\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>除了官方支持的数据库外，还有第三方提供的后端，允许你在 Django 中使用其他数据库。</p>\n<ul class=\"simple\">\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/django-cockroachdb/\">CockroachDB</a></p></li>\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/django-firebird/\">Firebird</a></p></li>\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/django-google-spanner/\">Google Cloud Spanner</a></p></li>\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/mssql-django/\">Microsoft SQL Server</a></p></li>\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/django-mongodb-backend/\">MongoDB</a></p></li>\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/django-snowflake/\">Snowflake</a></p></li>\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/django-tidb/\">TiDB</a></p></li>\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/django-yugabytedb/\">YugabyteDB</a></p></li>\n</ul>\n<p>这些非官方后端所支持的 Django 版本和 ORM 功能有很大的不同。关于这些非官方后端的具体功能的查询，以及任何支持的查询，都应该通过每个第三方项目提供的支持渠道进行。</p>\n</section>","rootId":"databases","toc":[{"title":"通用注意事项","anchor":"general-notes","children":[{"title":"持久连接","anchor":"persistent-connections","children":[{"title":"连接管理","anchor":"connection-management","children":[]},{"title":"附加说明","anchor":"caveats","children":[]}]},{"title":"编码","anchor":"encoding","children":[]}]},{"title":"PostgreSQL 注意事项","anchor":"postgresql-notes","children":[{"title":"PostgreSQL 连接配置","anchor":"postgresql-connection-settings","children":[]},{"title":"优化 PostgreSQL 的配置","anchor":"optimizing-postgresql-s-configuration","children":[]},{"title":"隔离等级","anchor":"isolation-level","children":[]},{"title":"角色","anchor":"role","children":[]},{"title":"连接池","anchor":"connection-pool","children":[]},{"title":"服务器端参数绑定","anchor":"server-side-parameters-binding","children":[]},{"title":"varchar 和 text 列的索引。","anchor":"indexes-for-varchar-and-text-columns","children":[]},{"title":"添加扩展的迁移操作","anchor":"migration-operation-for-adding-extensions","children":[]},{"title":"服务器端游标","anchor":"server-side-cursors","children":[{"title":"事务池和服务器端游标","anchor":"transaction-pooling-and-server-side-cursors","children":[]}]},{"title":"手动指定自增主键的值。","anchor":"manually-specifying-values-of-auto-incrementing-primary-keys","children":[]},{"title":"测试数据库模板","anchor":"test-database-templates","children":[]},{"title":"使用非持久设置加快测试执行速度。","anchor":"speeding-up-test-execution-with-non-durable-settings","children":[]}]},{"title":"MariaDB 注意事项","anchor":"mariadb-notes","children":[]},{"title":"MySQL 注意事项","anchor":"mysql-notes","children":[{"title":"版本支持","anchor":"version-support","children":[]},{"title":"存储引擎","anchor":"storage-engines","children":[]},{"title":"MySQL 数据库 API 驱动程序","anchor":"mysql-db-api-drivers","children":[{"title":"mysqlclient","anchor":"mysqlclient","children":[]},{"title":"MySQL Connector/Python","anchor":"id8","children":[]}]},{"title":"时区定义","anchor":"time-zone-definitions","children":[]},{"title":"创建你的数据库","anchor":"creating-your-database","children":[{"title":"字符序配置","anchor":"collation-settings","children":[]}]},{"title":"连接数据库","anchor":"connecting-to-the-database","children":[{"title":"设置 sql_mode","anchor":"setting-sql-mode","children":[]},{"title":"隔离等级","anchor":"mysql-isolation-level","children":[]}]},{"title":"创建你的表","anchor":"creating-your-tables","children":[]},{"title":"表名称","anchor":"table-names","children":[]},{"title":"保存点","anchor":"savepoints","children":[]},{"title":"特定字段的注意事项","anchor":"notes-on-specific-fields","children":[{"title":"字符字段","anchor":"character-fields","children":[]},{"title":"TextField 限制","anchor":"textfield-limitations","children":[]},{"title":"支持时间和 DateTime 字段的小数秒。","anchor":"fractional-seconds-support-for-time-and-datetime-fields","children":[]},{"title":"TIMESTAMP 列","anchor":"timestamp-columns","children":[]}]},{"title":"用 QuerySet.select_for_update() 锁定行","anchor":"row-locking-with-queryset-select-for-update","children":[]},{"title":"自动排版会造成意想不到的结果","anchor":"automatic-typecasting-can-cause-unexpected-results","children":[]}]},{"title":"SQLite 注意事项","anchor":"sqlite-notes","children":[{"title":"子串匹配和大小写敏感性","anchor":"substring-matching-and-case-sensitivity","children":[]},{"title":"小数处理","anchor":"decimal-handling","children":[]},{"title":"“Database is locked”错误","anchor":"database-is-locked-errors","children":[{"title":"事务行为","anchor":"transactions-behavior","children":[]}]},{"title":"不支持 QuerySet.select_for_update()","anchor":"queryset-select-for-update-not-supported","children":[]},{"title":"使用 QuerySet.iterator() 时的隔离","anchor":"isolation-when-using-queryset-iterator","children":[]},{"title":"在 SQLite 上启用 JSON1 扩展","anchor":"enabling-json1-extension-on-sqlite","children":[]},{"title":"设置 pragma 选项","anchor":"setting-pragma-options","children":[]}]},{"title":"Oracle 注意事项","anchor":"oracle-notes","children":[{"title":"连接数据库","anchor":"id13","children":[{"title":"完整的 DSN 和 Easy Connect","anchor":"full-dsn-and-easy-connect","children":[]}]},{"title":"连接池","anchor":"oracle-pool","children":[]},{"title":"INSERT ... RETURNING INTO","anchor":"insert-returning-into","children":[]},{"title":"命名问题","anchor":"naming-issues","children":[]},{"title":"NULL 和空字符串","anchor":"null-and-empty-strings","children":[]},{"title":"TextField 限制","anchor":"id15","children":[]}]},{"title":"子类化内置数据库后端","anchor":"subclassing-the-built-in-database-backends","children":[]},{"title":"使用第三方数据库后端","anchor":"using-a-3rd-party-database-backend","children":[]}],"breadcrumbs":[{"docname":"ref/index","title":"API 参考","url":"/zh-hans/6.0/ref/"}],"prev":{"docname":"ref/csrf","title":"跨站请求伪造保护","url":"/zh-hans/6.0/ref/csrf/"},"next":{"docname":"ref/django-admin","title":"django-admin 和 manage.py","url":"/zh-hans/6.0/ref/django-admin/"},"formats":{"html":"/zh-hans/6.0/ref/databases/","markdown":"/zh-hans/6.0/ref/databases.md","json":"/zh-hans/6.0/ref/databases.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/ref/databases.txt","official":"https://docs.djangoproject.com/zh-hans/6.0/ref/databases/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}