{"title":"Lancement de requêtes SQL brutes","version":"6.1","locale":"fr","docname":"topics/db/sql","url":"/fr/6.1/topics/db/sql/","canonical":"https://djangodocs.dev/fr/6.1/topics/db/sql/","summary":"Django propose trois manières d’exécuter des requêtes SQL brutes : vous pouvez intégrer des fragments de SQL bruts dans les requêtes ORM en utilisant RawSQL (voir…","html":"<h1>Lancement de requêtes SQL brutes<a class=\"heading-anchor\" href=\"#performing-raw-sql-queries\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django propose trois manières d’exécuter des requêtes SQL brutes : vous pouvez intégrer des fragments de SQL bruts dans les requêtes ORM en utilisant <a class=\"reference internal\" href=\"/fr/6.1/ref/models/expressions/#django.db.models.expressions.RawSQL\" title=\"django.db.models.expressions.RawSQL\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RawSQL</span></code></a> (voir <a class=\"reference internal\" href=\"#raw-sql-fragments\"><span class=\"std std-ref\">Fragments SQL bruts</span></a>), utiliser <a class=\"reference internal\" href=\"#django.db.models.Manager.raw\" title=\"django.db.models.Manager.raw\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Manager.raw()</span></code></a> pour <a class=\"reference internal\" href=\"#performing-raw-queries\">exécuter des requêtes brutes et renvoyer des instances de modèles</a>, ou outrepasser complètement la couche des modèles et <a class=\"reference internal\" href=\"#executing-custom-sql-directly\">exécuter directement du code SQL personnalisé</a>.</p>\n<aside class=\"admonition-explore-the-orm-before-using-raw-sql admonition\">\n<p class=\"admonition-title\">Explorez les possibilités de l’ORM avant d’avoir recours à du code SQL brut !</p>\n<p>L’ORM de Django fournit de nombreux outils pour formuler des requêtes sans recourir à du code SQL brut. Par exemple :</p>\n<ul class=\"simple\">\n<li><p>L’API <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/\"><span class=\"doc\">QuerySet</span></a> est bien documentée.</p></li>\n<li><p>Il est possible d’<a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.annotate\" title=\"django.db.models.query.QuerySet.annotate\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">annoter</span></code></a> et d’<a class=\"reference internal\" href=\"/fr/6.1/topics/db/aggregation/\"><span class=\"doc\">agréger</span></a> en utilisant de nombreuses <a class=\"reference internal\" href=\"/fr/6.1/ref/models/database-functions/\"><span class=\"doc\">fonctions de base de données</span></a> intégrées. Au-delà de ça, il est possible de créer des <a class=\"reference internal\" href=\"/fr/6.1/ref/models/expressions/\"><span class=\"doc\">expressions de requête personnalisées</span></a>.</p></li>\n</ul>\n<p>Avant de recourir à du code SQL brut, explorez <a class=\"reference internal\" href=\"/fr/6.1/topics/db/\"><span class=\"doc\">l’ORM</span></a>. Posez vos questions sur l’un des <a class=\"reference internal\" href=\"/fr/6.1/faq/help/\"><span class=\"doc\">canaux d’aide</span></a> pour savoir si l’ORM peut satisfaire votre cas de figure.</p>\n</aside>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Vous devez être très prudent lors de l’écriture d’instructions SQL brutes. Lors de chaque utilisation, vous devez échapper correctement tout paramètre pouvant être contrôlé par les utilisateurs en employant <code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> afin de vous protéger contre les attaques par injection SQL. Lisez attentivement les paragraphes sur la <a class=\"reference internal\" href=\"/fr/6.1/topics/security/#sql-injection-protection\"><span class=\"std std-ref\">protection contre les injections SQL</span></a>.</p>\n</aside>\n<section id=\"raw-sql-fragments\">\n<span id=\"id3\"></span><h2>Fragments SQL bruts<a class=\"heading-anchor\" href=\"#raw-sql-fragments\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Dans certains cas, il peut être nécessaire d’intégrer des fragments de code SQL brut directement dans les requêtes ORM, par exemple dans des appels à <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.annotate\" title=\"django.db.models.query.QuerySet.annotate\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">annotate()</span></code></a> ou <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.filter\" title=\"django.db.models.query.QuerySet.filter\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">filter()</span></code></a>. Utilisez des <a class=\"reference internal\" href=\"/fr/6.1/ref/models/expressions/#func-expressions\"><span class=\"std std-ref\">expressions Func()</span></a> pour appeler des fonctions de base de données indépendamment du type de base de données, ou <a class=\"reference internal\" href=\"/fr/6.1/ref/models/expressions/#django.db.models.expressions.RawSQL\" title=\"django.db.models.expressions.RawSQL\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RawSQL</span></code></a> pour des fragments directs de SQL paramétrisé.</p>\n</section>\n<section id=\"performing-raw-queries\">\n<span id=\"executing-raw-queries\"></span><h2>Lancement de requêtes brutes<a class=\"heading-anchor\" href=\"#performing-raw-queries\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>La méthode de gestionnaire <code class=\"docutils literal notranslate\"><span class=\"pre\">raw()</span></code> peut être utilisée pour exécuter des requêtes SQL brutes qui renvoient des instances de modèles :</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Manager.raw\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Manager.</span></span><span class=\"sig-name descname\"><span class=\"pre\">raw</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">raw_query</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">()</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">translations</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Manager.raw\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Cette méthode accepte une requête SQL brute, l’exécute et renvoie une instance <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.models.query.RawQuerySet</span></code>. Il est possible alors d’effectuer une boucle sur cette instance <code class=\"docutils literal notranslate\"><span class=\"pre\">RawQuerySet</span></code> comme pour un objet <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet\" title=\"django.db.models.query.QuerySet\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code></a> normal afin d’accéder aux instances d’objets.</p>\n<p>Un exemple vaut mieux que mille mots. Supposons que vous ayez créé le modèle suivant :</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\">Person</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=\"n\">first_name</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n    <span class=\"n\">last_name</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n    <span class=\"n\">birth_date</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">DateField</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Vous pouvez alors exécuter du code SQL personnalisé comme ceci :</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=\"k\">for</span> <span class=\"n\">p</span> <span class=\"ow\">in</span> <span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT * FROM myapp_person&quot;</span><span class=\"p\">):</span>\n<span class=\"gp\">... </span>    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">p</span><span class=\"p\">)</span>\n<span class=\"gp\">...</span>\n<span class=\"go\">John Smith</span>\n<span class=\"go\">Jane Jones</span>\n</code></pre></div>\n<p>Cet exemple n’est pas des plus passionnants, car il correspond exactement à l’expression <code class=\"docutils literal notranslate\"><span class=\"pre\">Person.objects.all()</span></code>. Toutefois, <code class=\"docutils literal notranslate\"><span class=\"pre\">raw()</span></code> comporte quelques autres options qui en font un outil très puissant.</p>\n<aside class=\"admonition-model-table-names admonition\">\n<p class=\"admonition-title\">Noms de table des modèles</p>\n<p>D’où vient le nom de la table `` Person`` dans cet exemple?</p>\n<p>Par défaut, Django compose un nom de table de base de données en combinant l”« étiquette d’application » du modèle (le nom utilisé dans <code class=\"docutils literal notranslate\"><span class=\"pre\">manage.py</span> <span class=\"pre\">startapp</span></code>) avec le nom de classe du modèle, séparés par un soulignement. Dans l’exemple, nous sommes partis du principe que le modèle <code class=\"docutils literal notranslate\"><span class=\"pre\">Person</span></code> se trouvait dans une application nommée <code class=\"docutils literal notranslate\"><span class=\"pre\">myapp</span></code>, et donc que le nom de la table était <code class=\"docutils literal notranslate\"><span class=\"pre\">myapp_person</span></code>.</p>\n<p>Pour plus de détails, consultez la documentation de l’option <a class=\"reference internal\" href=\"/fr/6.1/ref/models/options/#django.db.models.Options.db_table\" title=\"django.db.models.Options.db_table\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">db_table</span></code></a> qui vous permet également de définir manuellement le nom de table de la base de données.</p>\n</aside>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Aucune vérification n’est effectuée pour les instructions SQL transmises à <code class=\"docutils literal notranslate\"><span class=\"pre\">.raw()</span></code>. Django s’attend à ce que la requête renvoie un ensemble de lignes de la base de données, mais ne fait rien pour le vérifier a priori. Si la requête ne retourne pas de ligne, une erreur (potentiellement cryptique) sera générée.</p>\n</aside>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Si vous effectuez des requêtes vers MySQL, notez que le forçage de type silencieux de MySQL peut produire des résultats inattendus lors du mélange de types. Si une requête porte sur une colonne de type chaîne mais contient une valeur nombre entier, MySQL transforme le type de toutes les valeurs de la table en nombre entier avant d’effectuer la comparaison. Par exemple, si la table contient les valeurs <code class=\"docutils literal notranslate\"><span class=\"pre\">'abc'</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">'def'</span></code> et que la requête contient <code class=\"docutils literal notranslate\"><span class=\"pre\">WHERE</span> <span class=\"pre\">macolonne=0</span></code>, les deux lignes seront sélectionnées. Pour empêcher cela, effectuez les transformations de type avant d’utiliser une valeur dans une requête.</p>\n</aside>\n<section id=\"mapping-query-fields-to-model-fields\">\n<h3>Correspondance entre champs de requête et champs de modèle<a class=\"heading-anchor\" href=\"#mapping-query-fields-to-model-fields\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">raw()</span></code> fait automatiquement correspondre les champs de la requête avec les champs du modèle.</p>\n<p>L’ordre des champs dans la requête n’est pas important. En d’autres termes, les deux requêtes suivantes donneront le même résultat :</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=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT id, first_name, last_name, birth_date FROM myapp_person&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT last_name, birth_date, first_name, id FROM myapp_person&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>La correspondance se fait sur le nom. Cela signifie que vous pouvez utiliser les clauses SQL <code class=\"docutils literal notranslate\"><span class=\"pre\">AS</span></code> pour faire correspondre les champs de la requête aux champs du modèle. Ainsi, si vous disposez d’une autre table contenant les données de <code class=\"docutils literal notranslate\"><span class=\"pre\">Person</span></code>, vous pouvez facilement faire correspondre ces données avec des instances de <code class=\"docutils literal notranslate\"><span class=\"pre\">Person</span></code>:</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=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"s2\">&quot;&quot;&quot;</span>\n<span class=\"gp\">... </span><span class=\"s2\">    SELECT first AS first_name,</span>\n<span class=\"gp\">... </span><span class=\"s2\">           last AS last_name,</span>\n<span class=\"gp\">... </span><span class=\"s2\">           bd AS birth_date,</span>\n<span class=\"gp\">... </span><span class=\"s2\">           pk AS id,</span>\n<span class=\"gp\">... </span><span class=\"s2\">    FROM some_other_table</span>\n<span class=\"gp\">... </span><span class=\"s2\">    &quot;&quot;&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">...</span>\n</code></pre></div>\n<p>Tant que les noms correspondent, les instances de modèle seront créées correctement.</p>\n<p>Il est aussi possible de faire correspondre les champs de requête aux champs de modèle en utilisant le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">translations</span></code> de <code class=\"docutils literal notranslate\"><span class=\"pre\">raw()</span></code>. Il s’agit d’un dictionnaire faisant correspondre les noms des champs de la requête aux noms des champs du modèle. Par exemple, la requête ci-dessus aurait aussi pu être écrite de cette manière :</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=\"n\">name_map</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s2\">&quot;first&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;first_name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;last&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;last_name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;bd&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;birth_date&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;id&quot;</span><span class=\"p\">}</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT * FROM some_other_table&quot;</span><span class=\"p\">,</span> <span class=\"n\">translations</span><span class=\"o\">=</span><span class=\"n\">name_map</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"index-lookups\">\n<h3>Filtrage par index<a class=\"heading-anchor\" href=\"#index-lookups\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">raw()</span></code> autorise l’utilisation d’index ; dans le cas où vous souhaitez obtenir uniquement le premier résultat, vous pouvez écrire :</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=\"n\">first_person</span> <span class=\"o\">=</span> <span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT * FROM myapp_person&quot;</span><span class=\"p\">)[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>Cependant, l’indexation et la segmentation ne sont pas effectuées au niveau de la base de données. Si la base de données contient une grande quantité d’objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Person</span></code>, il est plus efficace de limiter la requête au niveau SQL :</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=\"n\">first_person</span> <span class=\"o\">=</span> <span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT * FROM myapp_person LIMIT 1&quot;</span><span class=\"p\">)[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n</code></pre></div>\n</section>\n<section id=\"deferring-model-fields\">\n<h3>Report des champs de modèle<a class=\"heading-anchor\" href=\"#deferring-model-fields\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il est aussi possible d’ignorer certains champs :</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=\"n\">people</span> <span class=\"o\">=</span> <span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT id, first_name FROM myapp_person&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Les objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Person</span></code> renvoyés par cette requête constitueront des instances de modèle différées (voir <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.defer\" title=\"django.db.models.query.QuerySet.defer\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">defer()</span></code></a>). Cela signifie que les champs omis dans la requête seront chargés à la demande. Par exemple :</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=\"k\">for</span> <span class=\"n\">p</span> <span class=\"ow\">in</span> <span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT id, first_name FROM myapp_person&quot;</span><span class=\"p\">):</span>\n<span class=\"gp\">... </span>    <span class=\"nb\">print</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>        <span class=\"n\">p</span><span class=\"o\">.</span><span class=\"n\">first_name</span><span class=\"p\">,</span>  <span class=\"c1\"># This will be retrieved by the original query</span>\n<span class=\"gp\">... </span>        <span class=\"n\">p</span><span class=\"o\">.</span><span class=\"n\">last_name</span><span class=\"p\">,</span>  <span class=\"c1\"># This will be retrieved on demand</span>\n<span class=\"gp\">... </span>    <span class=\"p\">)</span>\n<span class=\"gp\">...</span>\n<span class=\"go\">John Smith</span>\n<span class=\"go\">Jane Jones</span>\n</code></pre></div>\n<p>En apparence, il semble que la requête ait récupéré à la fois le prénom et le nom. Cependant, cet exemple effectue en réalité 3 requêtes. Seuls les prénoms (first_name) ont été obtenus par la requête <code class=\"docutils literal notranslate\"><span class=\"pre\">raw()</span></code>, les noms (last_name) ont été obtenus chacun à la demande au moment où ils ont été affichés.</p>\n<p>Un seul champ ne peut pas être omis, c’est le champ clé primaire. Django utilise la clé primaire pour identifier les instances de modèle, elle doit donc être obligatoirement incluse dans la requête brute. Une exception <a class=\"reference internal\" href=\"/fr/6.1/ref/exceptions/#django.core.exceptions.FieldDoesNotExist\" title=\"django.core.exceptions.FieldDoesNotExist\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FieldDoesNotExist</span></code></a> est générée si vous oubliez d’inclure la clé primaire.</p>\n</section>\n<section id=\"passing-parameters-into-raw\">\n<h3>Transmission de paramètres dans <code class=\"docutils literal notranslate\"><span class=\"pre\">raw()</span></code><a class=\"heading-anchor\" href=\"#passing-parameters-into-raw\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>S’il est nécessaire d’effectuer des requêtes paramétrées, il est possible d’utiliser le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> de <code class=\"docutils literal notranslate\"><span class=\"pre\">raw()</span></code>:</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=\"n\">lname</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;Doe&quot;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT * FROM myapp_person WHERE last_name = </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"n\">lname</span><span class=\"p\">])</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> est une liste ou un dictionnaire de paramètres. Dans la chaîne de requête, il faut alors inclure des substituants <code class=\"docutils literal notranslate\"><span class=\"pre\">%s</span></code> pour une liste ou des substituants``%(clé)s`` pour un dictionnaire (où <code class=\"docutils literal notranslate\"><span class=\"pre\">clé</span></code> est remplacé par une clé de dictionnaire), quel que soit le moteur de base de données. Ces substituants seront remplacés par le contenu du paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code>.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Les paramètres de type dictionnaire ne sont pas pris en charge par le moteur SQLite ; avec ce moteur, vous devez transmettre les paramètres sous forme de liste.</p>\n</aside>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p><strong>N’utilisez pas de formatage de chaîne dans les requêtes brutes, ni de substituants entre guillemets dans vos chaînes SQL !</strong></p>\n<p>Il est tentant d’écrire la requête ci-dessus comme ceci :</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=\"n\">query</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;SELECT * FROM myapp_person WHERE last_name = </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span> <span class=\"o\">%</span> <span class=\"n\">lname</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">raw</span><span class=\"p\">(</span><span class=\"n\">query</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Vous pourriez aussi imaginer devoir écrire votre requête comme ceci (avec des guillemets autour de <code class=\"docutils literal notranslate\"><span class=\"pre\">%s</span></code>) :</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=\"n\">query</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;SELECT * FROM myapp_person WHERE last_name = &#39;</span><span class=\"si\">%s</span><span class=\"s2\">&#39;&quot;</span>\n</code></pre></div>\n<p><strong>Ne faites aucune de ces erreurs.</strong></p>\n<p>Comme discuté dans <a class=\"reference internal\" href=\"/fr/6.1/topics/security/#sql-injection-protection\"><span class=\"std std-ref\">Protection contre l’injection SQL</span></a>, l’utilisation du paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> et le fait de laisser les substituants sans guillemets vous protègent contre les <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/SQL_injection\">attaques d’injection SQL</a>, une faille courante où un attaquant injecte du code SQL arbitraire dans votre base de données. Si vous utilisez l’interpolation de chaîne ou que vous placez les substituants entre guillemets, vous êtes exposé aux injections SQL.</p>\n</aside>\n</section>\n</section>\n<section id=\"executing-custom-sql-directly\">\n<span id=\"executing-custom-sql\"></span><h2>Exécution directe de code SQL<a class=\"heading-anchor\" href=\"#executing-custom-sql-directly\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Dans certains cas, même <a class=\"reference internal\" href=\"#django.db.models.Manager.raw\" title=\"django.db.models.Manager.raw\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Manager.raw()</span></code></a> ne suffit pas : il se peut que des requêtes doivent être effectuées sans correspondre proprement à des modèles ou que vous vouliez exécuter directement des requêtes <code class=\"docutils literal notranslate\"><span class=\"pre\">UPDATE</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">INSERT</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">DELETE</span></code>.</p>\n<p>Dans ces situations, vous pouvez toujours accéder directement à la base de données, outrepassant complètement la couche des modèles.</p>\n<p>L’objet <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.connection</span></code> représente la connexion à la base de données par défaut. Pour utiliser la connexion à la base de données, appelez <code class=\"docutils literal notranslate\"><span class=\"pre\">connection.cursor()</span></code> pour obtenir un objet curseur. Puis, appelez <code class=\"docutils literal notranslate\"><span class=\"pre\">cursor.execute(sql,</span> <span class=\"pre\">[params])</span></code> pour exécuter le code SQL et <code class=\"docutils literal notranslate\"><span class=\"pre\">cursor.fetchone()</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">cursor.fetchall()</span></code> pour obtenir les lignes de résultat.</p>\n<p>Par exemple :</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</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">connection</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_custom_sql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"k\">with</span> <span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">cursor</span><span class=\"p\">()</span> <span class=\"k\">as</span> <span class=\"n\">cursor</span><span class=\"p\">:</span>\n        <span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">execute</span><span class=\"p\">(</span><span class=\"s2\">&quot;UPDATE bar SET foo = 1 WHERE baz = </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">baz</span><span class=\"p\">])</span>\n        <span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">execute</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT foo FROM bar WHERE baz = </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">baz</span><span class=\"p\">])</span>\n        <span class=\"n\">row</span> <span class=\"o\">=</span> <span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">fetchone</span><span class=\"p\">()</span>\n\n    <span class=\"k\">return</span> <span class=\"n\">row</span>\n</code></pre></div>\n<p>Pour se protéger des injections SQL, vous devez vous abstenir de placer des guillemets autour des substituants <code class=\"docutils literal notranslate\"><span class=\"pre\">%s</span></code> dans la chaîne SQL.</p>\n<p>Notez que si vous voulez inclure des signes « pour cent » littéraux dans la requête, vous devez les doubler dans le cas où vous transmettez des paramètres :</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\">cursor</span><span class=\"o\">.</span><span class=\"n\">execute</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT foo FROM bar WHERE baz = &#39;30%&#39;&quot;</span><span class=\"p\">)</span>\n<span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">execute</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT foo FROM bar WHERE baz = &#39;30</span><span class=\"si\">%%</span><span class=\"s2\">&#39; AND id = </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">id</span><span class=\"p\">])</span>\n</code></pre></div>\n<p>Si vous utilisez <a class=\"reference internal\" href=\"/fr/6.1/topics/db/multi-db/\"><span class=\"doc\">plus d’une base de données</span></a>, vous pouvez utiliser <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.connections</span></code> pour obtenir la connexion (et le curseur) pour une base de données spécifique. <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.connections</span></code> est un objet de type dictionnaire permettant de récupérer une connexion spécifique en employant son alias :</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</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">connections</span>\n\n<span class=\"k\">with</span> <span class=\"n\">connections</span><span class=\"p\">[</span><span class=\"s2\">&quot;my_db_alias&quot;</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">cursor</span><span class=\"p\">()</span> <span class=\"k\">as</span> <span class=\"n\">cursor</span><span class=\"p\">:</span>\n    <span class=\"c1\"># Your code here</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>Par défaut, l’API de base de données de Python renvoie les résultats sans les noms de champs, ce qui signifie que vous vous retrouvez avec une liste de valeurs plutôt qu’un dictionnaire. Pour un faible coût en performances et en mémoire, vous pouvez obtenir les résultats sous forme de dictionnaire en écrivant quelque chose comme :</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\">def</span><span class=\"w\"> </span><span class=\"nf\">dictfetchall</span><span class=\"p\">(</span><span class=\"n\">cursor</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    Return all rows from a cursor as a dict.</span>\n<span class=\"sd\">    Assume the column names are unique.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"n\">columns</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"n\">col</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"k\">for</span> <span class=\"n\">col</span> <span class=\"ow\">in</span> <span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">description</span><span class=\"p\">]</span>\n    <span class=\"k\">return</span> <span class=\"p\">[</span><span class=\"nb\">dict</span><span class=\"p\">(</span><span class=\"nb\">zip</span><span class=\"p\">(</span><span class=\"n\">columns</span><span class=\"p\">,</span> <span class=\"n\">row</span><span class=\"p\">))</span> <span class=\"k\">for</span> <span class=\"n\">row</span> <span class=\"ow\">in</span> <span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">fetchall</span><span class=\"p\">()]</span>\n</code></pre></div>\n<p>Une autre option est d’utiliser une structure <a class=\"reference external\" href=\"https://docs.python.org/3/library/collections.html#collections.namedtuple\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">collections.namedtuple()</span></code></a> de la bibliothèque Python standard. Un <code class=\"docutils literal notranslate\"><span class=\"pre\">namedtuple</span></code> est un objet de type tuple dont les champs sont accessibles sous forme d’attribut ; l’accès par indice est aussi possible et l’objet est itérable. Les résultats sont immuables et accessibles par nom de champ ou par indice, ce qui pourrait être pratique :</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\">collections</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">namedtuple</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">namedtuplefetchall</span><span class=\"p\">(</span><span class=\"n\">cursor</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    Return all rows from a cursor as a namedtuple.</span>\n<span class=\"sd\">    Assume the column names are unique.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"n\">desc</span> <span class=\"o\">=</span> <span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">description</span>\n    <span class=\"n\">nt_result</span> <span class=\"o\">=</span> <span class=\"n\">namedtuple</span><span class=\"p\">(</span><span class=\"s2\">&quot;Result&quot;</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"n\">col</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"k\">for</span> <span class=\"n\">col</span> <span class=\"ow\">in</span> <span class=\"n\">desc</span><span class=\"p\">])</span>\n    <span class=\"k\">return</span> <span class=\"p\">[</span><span class=\"n\">nt_result</span><span class=\"p\">(</span><span class=\"o\">*</span><span class=\"n\">row</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">row</span> <span class=\"ow\">in</span> <span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">fetchall</span><span class=\"p\">()]</span>\n</code></pre></div>\n<p>Les exemples <code class=\"docutils literal notranslate\"><span class=\"pre\">dictfetchall()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">namedtuplefetchall()</span></code> supposent que les noms de colonnes sont uniques, car un curseur ne peut pas distinguer les colonnes de tables différentes.</p>\n<p>Voici un exemple de la différence entre les trois :</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=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">execute</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT id, parent_id FROM test LIMIT 2&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">fetchall</span><span class=\"p\">()</span>\n<span class=\"go\">((54360982, None), (54360880, None))</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">execute</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT id, parent_id FROM test LIMIT 2&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">dictfetchall</span><span class=\"p\">(</span><span class=\"n\">cursor</span><span class=\"p\">)</span>\n<span class=\"go\">[{&#39;parent_id&#39;: None, &#39;id&#39;: 54360982}, {&#39;parent_id&#39;: None, &#39;id&#39;: 54360880}]</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">execute</span><span class=\"p\">(</span><span class=\"s2\">&quot;SELECT id, parent_id FROM test LIMIT 2&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">results</span> <span class=\"o\">=</span> <span class=\"n\">namedtuplefetchall</span><span class=\"p\">(</span><span class=\"n\">cursor</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">results</span>\n<span class=\"go\">[Result(id=54360982, parent_id=None), Result(id=54360880, parent_id=None)]</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">results</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">id</span>\n<span class=\"go\">54360982</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">results</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">][</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n<span class=\"go\">54360982</span>\n</code></pre></div>\n<section id=\"connections-and-cursors\">\n<h3>Connexions et curseurs<a class=\"heading-anchor\" href=\"#connections-and-cursors\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">connection</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">cursor</span></code> implémentent essentiellement l’API de base de données standard de Python décrite dans la <span class=\"target\" id=\"index-2\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0249/\"><strong>PEP 249</strong></a>, à l’exception de ce qui concerne la <a class=\"reference internal\" href=\"/fr/6.1/topics/db/transactions/\"><span class=\"doc\">gestion des transactions</span></a>.</p>\n<p>Si cette API DB de Python ne vous est pas familière, notez que l’instruction SQL dans <code class=\"docutils literal notranslate\"><span class=\"pre\">cursor.execute()</span></code> utilise des substituants, <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;%s&quot;</span></code>, plutôt que d’ajouter directement les paramètres dans la chaîne SQL. Si vous utilisez cette technique, la bibliothèque sous-jacente de base de données s’occupe automatiquement d’échapper vos paramètres au besoin.</p>\n<p>Notez également que Django compte sur des substituants <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;%s&quot;</span></code>, <em>pas</em> de substituants <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;?&quot;</span></code> qui sont utilisés par la bibliothèque SQLite de Python, pour des raisons de cohérence et de bon sens.</p>\n<p>L’utilisation d’un curseur en tant que gestionnaire de contexte :</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\">with</span> <span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">cursor</span><span class=\"p\">()</span> <span class=\"k\">as</span> <span class=\"n\">c</span><span class=\"p\">:</span>\n    <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">execute</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>est équivalent à :</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\">c</span> <span class=\"o\">=</span> <span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">cursor</span><span class=\"p\">()</span>\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">execute</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n<span class=\"k\">finally</span><span class=\"p\">:</span>\n    <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">close</span><span class=\"p\">()</span>\n</code></pre></div>\n<section id=\"calling-stored-procedures\">\n<h4>Appeler des procédures stockées<a class=\"heading-anchor\" href=\"#calling-stored-procedures\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.CursorWrapper.callproc\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">CursorWrapper.</span></span><span class=\"sig-name descname\"><span class=\"pre\">callproc</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">procname</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">kparams</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.CursorWrapper.callproc\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Appelle une procédure stockée de base de données ayant le nom indiqué. Une liste (<code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code>) ou un dictionnaire (<code class=\"docutils literal notranslate\"><span class=\"pre\">kparams</span></code>) de paramètres d’entrée peuvent être fournis. La plupart des bases de données n’acceptent pas <code class=\"docutils literal notranslate\"><span class=\"pre\">kparams</span></code>. Parmi celles qui sont prises en charge nativement par Django, seule Oracle accepte <code class=\"docutils literal notranslate\"><span class=\"pre\">kparams</span></code>.</p>\n<p>Par exemple, avec cette procédure stockée dans une base de données Oracle :</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\">PROCEDURE</span><span class=\"w\"> </span><span class=\"ss\">&quot;TEST_PROCEDURE&quot;</span><span class=\"p\">(</span><span class=\"n\">v_i</span><span class=\"w\"> </span><span class=\"nb\">INTEGER</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">v_text</span><span class=\"w\"> </span><span class=\"n\">NVARCHAR2</span><span class=\"p\">(</span><span class=\"mi\">10</span><span class=\"p\">))</span><span class=\"w\"> </span><span class=\"k\">AS</span>\n<span class=\"w\">    </span><span class=\"n\">p_i</span><span class=\"w\"> </span><span class=\"nb\">INTEGER</span><span class=\"p\">;</span>\n<span class=\"w\">    </span><span class=\"n\">p_text</span><span class=\"w\"> </span><span class=\"n\">NVARCHAR2</span><span class=\"p\">(</span><span class=\"mi\">10</span><span class=\"p\">);</span>\n<span class=\"k\">BEGIN</span>\n<span class=\"w\">    </span><span class=\"n\">p_i</span><span class=\"w\"> </span><span class=\"p\">:</span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"n\">v_i</span><span class=\"p\">;</span>\n<span class=\"w\">    </span><span class=\"n\">p_text</span><span class=\"w\"> </span><span class=\"p\">:</span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"n\">v_text</span><span class=\"p\">;</span>\n<span class=\"w\">    </span><span class=\"p\">...</span>\n<span class=\"k\">END</span><span class=\"p\">;</span>\n</code></pre></div>\n<p>Ceci l’appellera</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\">with</span> <span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">cursor</span><span class=\"p\">()</span> <span class=\"k\">as</span> <span class=\"n\">cursor</span><span class=\"p\">:</span>\n    <span class=\"n\">cursor</span><span class=\"o\">.</span><span class=\"n\">callproc</span><span class=\"p\">(</span><span class=\"s2\">&quot;test_procedure&quot;</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"s2\">&quot;test&quot;</span><span class=\"p\">])</span>\n</code></pre></div>\n</dd></dl>\n\n</section>\n</section>\n</section>","rootId":"performing-raw-sql-queries","toc":[{"title":"Fragments SQL bruts","anchor":"raw-sql-fragments","children":[]},{"title":"Lancement de requêtes brutes","anchor":"performing-raw-queries","children":[{"title":"Correspondance entre champs de requête et champs de modèle","anchor":"mapping-query-fields-to-model-fields","children":[]},{"title":"Filtrage par index","anchor":"index-lookups","children":[]},{"title":"Report des champs de modèle","anchor":"deferring-model-fields","children":[]},{"title":"Transmission de paramètres dans raw()","anchor":"passing-parameters-into-raw","children":[]}]},{"title":"Exécution directe de code SQL","anchor":"executing-custom-sql-directly","children":[{"title":"Connexions et curseurs","anchor":"connections-and-cursors","children":[{"title":"Appeler des procédures stockées","anchor":"calling-stored-procedures","children":[]}]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Utilisation de Django","url":"/fr/6.1/topics/"},{"docname":"topics/db/index","title":"Modèles et bases de données","url":"/fr/6.1/topics/db/"}],"prev":{"docname":"topics/db/managers","title":"Gestionnaires","url":"/fr/6.1/topics/db/managers/"},"next":{"docname":"topics/db/transactions","title":"Transactions de base de données","url":"/fr/6.1/topics/db/transactions/"},"formats":{"html":"/fr/6.1/topics/db/sql/","markdown":"/fr/6.1/topics/db/sql.md","json":"/fr/6.1/topics/db/sql.json"},"source":"https://github.com/django/django/blob/stable/6.1.x/docs/topics/db/sql.txt","official":"https://docs.djangoproject.com/fr/6.1/topics/db/sql/","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","1.11","1.10","1.9"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}