Quand utiliser des guillemets simples, des guillemets doubles et des backticks dans MySQL

633

J'essaie d'apprendre la meilleure façon d'écrire des requêtes. Je comprends également l'importance d'être cohérent. Jusqu'à présent, j'ai utilisé au hasard des guillemets simples, des guillemets doubles et des guillemets sans aucune véritable pensée.

Exemple:

$query = 'INSERT INTO table (id, col1, col2) VALUES (NULL, val1, val2)';

En outre, dans l'exemple ci - dessus, considérer que table, col1, val1, etc. , peuvent être des variables.

Quelle est la norme pour cela? Que faire?

Je lis les réponses à des questions similaires ici depuis environ 20 minutes, mais il semble qu'il n'y ait pas de réponse définitive à cette question.

Nate
la source
16
Notez que c'est une question très spécifique à MySQL. SQL en général (c'est-à-dire ISO / ANSI SQL) a un ensemble différent de guillemets: les guillemets doubles sont pour les identificateurs délimités, par exemple "tablename", et les guillemets simples sont pour les littéraux, par exemple 'this is a some text'. Les back-ticks ne sont jamais utilisés en SQL standard. (Si vous devez inclure un guillemet double dans un identifiant, tapez-le deux fois comme "odd""tablename". De même, double guillemets simples dans des littéraux, comme 'Conan O''Brien'.)
jarlh

Réponses:

611

Les backticks doivent être utilisés pour les identificateurs de table et de colonne, mais ne sont nécessaires que lorsque l'identifiant est un mot clé réservé MySQL , ou lorsque l'identifiant contient des espaces ou des caractères au-delà d'un ensemble limité (voir ci-dessous). Il est souvent recommandé d'éviter d'utiliser des mots clés réservés comme identificateurs de colonne ou de table lorsque cela est possible, en évitant le problème de citation.

Des guillemets simples doivent être utilisés pour les valeurs de chaîne comme dans la VALUES()liste. Les guillemets doubles sont également pris en charge par MySQL pour les valeurs de chaîne, mais les guillemets simples sont plus largement acceptés par les autres SGBDR, c'est donc une bonne habitude d'utiliser des guillemets simples au lieu de doubles.

MySQL s'attend également à ce DATEque DATETIMEles valeurs littérales soient entre guillemets simples comme des chaînes '2001-01-01 00:00:00'. Consultez la documentation des littéraux de date et d'heure pour plus de détails, en particulier des alternatives à l'utilisation du trait -d' union comme délimiteur de segment dans les chaînes de date.

Donc, en utilisant votre exemple, je citerais deux fois la chaîne PHP et utiliserais des guillemets simples sur les valeurs 'val1', 'val2'. NULLest un mot-clé MySQL, et une valeur (non) spéciale, et n'est donc pas cité.

Aucun de ces identifiants de table ou de colonne n'est un mot réservé ou n'utilise des caractères nécessitant une citation, mais je les ai quand même cités avec des astuces (plus de détails plus loin ...).

Les fonctions natives du SGBDR (par exemple, NOW()dans MySQL) ne doivent pas être citées, bien que leurs arguments soient soumis aux mêmes règles de citation de chaîne ou d'identifiant déjà mentionnées.

Backtick (`)
table et colonne ───────┬─────┬──┬──┬──┬────┬──┬────┬──┬────┬──┬ ───────┐
                      ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
$ query = " INSERT INTO` table` (`id`,` col1`, `col2`,` date`, `updated`)
                       VALEURS (NULL, 'val1', 'val2', '2001-01-01', NOW ()) ";
                               ↑↑↑↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑↑↑↑↑ 
Mot-clé non cité ─────┴┴┴┘ │ │ │ │ │ │ │││││
Chaînes entre guillemets simples (') ───────────┴────┴──┴────┘ │ │ │││││
Devis simple (') DATE ───────────────────────────┴──────────┘ ││││ │
Fonction non citée ─────────────────────────────────────────┴┴┴┴┘    

Interpolation variable

Les modèles de guillemets pour les variables ne changent pas, bien que si vous avez l'intention d'interpoler les variables directement dans une chaîne, ils doivent être entre guillemets doubles en PHP. Assurez-vous simplement que vous avez correctement échappé les variables à utiliser dans SQL. ( Il est recommandé d'utiliser à la place une API prenant en charge les instructions préparées, comme protection contre l'injection SQL ).

// Même chose avec certains remplacements de variables
// Ici, un nom de table de variable $ table est entre guillemets, et les variables
// dans la liste VALUES sont entre guillemets simples 
$ query = "INSERT INTO` $ table` (`id`,` col1`, `col2`,` date`) VALUES (NULL, '$ val1' , '$ val2' , '$ date' ) ";

Déclarations préparées

Lorsque vous travaillez avec des instructions préparées, consultez la documentation pour déterminer si les espaces réservés de l'instruction doivent être cités. Les API les plus populaires disponibles en PHP, PDO et MySQLi, attendent des espaces réservés non cités, comme le font la plupart des API d'instructions préparées dans d'autres langues:

// PDO example with named parameters, unquoted
$query = "INSERT INTO `table` (`id`, `col1`, `col2`, `date`) VALUES (:id, :col1, :col2, :date)";

// MySQLi example with ? parameters, unquoted
$query = "INSERT INTO `table` (`id`, `col1`, `col2`, `date`) VALUES (?, ?, ?, ?)";

Caractères nécessitant un backtick entre guillemets:

Selon la documentation MySQL , vous n'avez pas besoin de citer (backtick) les identifiants en utilisant le jeu de caractères suivant:

ASCII: [0-9,a-z,A-Z$_](lettres latines de base, chiffres 0-9, dollar, trait de soulignement)

Vous pouvez utiliser des caractères au-delà de cet ensemble comme identifiants de table ou de colonne, y compris les espaces blancs par exemple, mais vous devez ensuite les citer (les insérer).

Michael Berkowski
la source
43
" mais les guillemets simples sont plus largement acceptés par les autres SGBDR " - l'utilisation de guillemets simples pour les littéraux de chaîne est définie (et requise) par le standard SQL
a_horse_with_no_name
@a_horse_with_no_name presque personne n'utilise ANSI MySQL ('|' pour la chaîne de caractères - vraiment?)
Bonne personne
3
ce n'est pas vrai: "MySQL s'attend également à ce que les valeurs littérales DATE et DATETIME soient entre guillemets simples comme '2001-01-01 00:00:00'"
Kick_the_BUCKET
3
Les documents @evilReiko MySQL ne semblent pas aborder clairement les alias. Il accepte les alias simples, doubles ou en backtick mais qui peuvent être affectés par différents modes SQL ANSI. Je ne suis pas sûr de ce que la spécification SQL requiert pour les guillemets d'alias - Préférence personnelle: pour des raisons de cohérence, je les cite de la même manière que les identificateurs de colonne - c'est-à-dire que je les ajoute au besoin si nécessaire, ou les laisse sans guillemets sinon. Je n'utilise pas de guillemets simples ou doubles sur les alias.
Michael Berkowski
2
@GuneyOzsan Oui, très vulnérable. N'utilisez jamais une variable pour un nom de table à moins qu'elle n'ait été validée par rapport à une liste de noms de table acceptables - créez un tableau de noms autorisés et vérifiez que la variable correspond à quelque chose dans la liste pour la rendre sûre à utiliser. Sinon, vous ne pouvez pas échapper en toute sécurité une variable de nom de table à utiliser.
Michael Berkowski
121

Il existe deux types de devis dans MySQL:

  1. ' pour enfermer des littéraux de chaîne
  2. ` pour enfermer des identificateurs tels que les noms de table et de colonne

Et puis il y a "ce qui est un cas particulier. Il pourrait être utilisé à l' une des fins mentionnées ci-dessus à la fois en fonction du serveur MySQL sql_mode:

  1. Par défaut, le "caractère peut être utilisé pour entourer des littéraux de chaîne comme'
  2. En ANSI_QUOTESmode, le "caractère peut être utilisé pour entourer des identifiants comme`

La requête suivante produira des résultats (ou erreurs) différents selon le mode SQL:

SELECT "column" FROM table WHERE foo = "bar"

ANSI_QUOTES désactivé

La requête sélectionnera le littéral de chaîne "column"où la colonne fooest égale à la chaîne"bar"

ANSI_QUOTES activé

La requête sélectionnera la colonne columnoù la colonne fooest égale à la colonnebar

Quand utiliser quoi

  • Je vous suggère d'éviter d'utiliser "afin que votre code devienne indépendant des modes SQL
  • Citez toujours les identifiants car c'est une bonne pratique (pas mal de questions sur SO en discutent)
Salman A
la source
32

(Il existe de bonnes réponses ci-dessus concernant la nature SQL de votre question, mais cela peut également être pertinent si vous êtes nouveau sur PHP.)

Il est peut-être important de mentionner que PHP gère différemment les chaînes entre guillemets simples et doubles ...

Les chaînes entre guillemets simples sont des «littéraux» et sont à peu près des chaînes WYSIWYG. Les chaînes entre guillemets doubles sont interprétées par PHP pour une éventuelle substitution de variable (les backticks en PHP ne sont pas exactement des chaînes; ils exécutent une commande dans le shell et retournent le résultat).

Exemples:

$foo = "bar";
echo 'there is a $foo'; // There is a $foo
echo "there is a $foo"; // There is a bar
echo `ls -l`; // ... a directory list
Chris Trahey
la source
23

Les backticks sont généralement utilisés pour indiquer un identifieret ainsi être à l' abri de l'utilisation accidentelle des mots-clés réservés .

Par exemple:

Use `database`;

Ici, les backticks aideront le serveur à comprendre que databasec'est en fait le nom de la base de données, pas l'identifiant de la base de données.

La même chose peut être faite pour les noms de table et les noms de champ. C'est une très bonne habitude si vous enveloppez votre identifiant de base de données avec des astuces.

Cochez cette réponse pour en savoir plus sur les backticks.


Maintenant sur les guillemets doubles et les guillemets simples (Michael l'a déjà mentionné).

Mais, pour définir une valeur, vous devez utiliser des guillemets simples ou doubles. Voyons un autre exemple.

INSERT INTO `tablename` (`id, `title`) VALUES ( NULL, title1);

Ici, j'ai délibérément oublié d'envelopper les title1citations. Maintenant, le serveur prendra le title1comme un nom de colonne (c'est-à-dire un identifiant). Donc, pour indiquer qu'il s'agit d'une valeur, vous devez utiliser des guillemets doubles ou simples.

INSERT INTO `tablename` (`id, `title`) VALUES ( NULL, 'title1');

Désormais, en combinaison avec PHP, les guillemets doubles et les guillemets simples facilitent le temps d'écriture de vos requêtes. Voyons une version modifiée de la requête dans votre question.

$query = "INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, '$val1', '$val2')";

Maintenant, en utilisant des guillemets doubles dans le PHP, vous allez créer les variables $val1, et $val2utiliser leurs valeurs créant ainsi une requête parfaitement valide. Comme

$val1 = "my value 1";
$val2 = "my value 2";
$query = "INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, '$val1', '$val2')";

fera

INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, 'my value 1', 'my value 2')
Starx
la source
15

Dans MySQL, ces symboles sont utilisés pour délimiter une requête `, ", 'et ().

  1. "ou 'sont utilisés pour inclure des valeurs de type chaîne "26-01-2014 00:00:00"ou '26-01-2014 00:00:00'. Ces symboles ne sont que pour les chaînes, les fonctions non agrégées aiment now, sumou max.

  2. ` est utilisé pour inclure des noms de table ou de colonne, par exemple select `column_name` from `table_name` where id='2'

  3. (et )simplement joindre des parties d'une requête, par exemple select `column_name` from `table_name` where (id='2' and gender='male') or name='rakesh'.

Kumar Rakesh
la source
13

Les littéraux de chaîne dans MySQL et PHP sont les mêmes.

Une chaîne est une séquence d'octets ou de caractères, entre guillemets simples ("'") ou guillemets doubles ("" ").

Donc, si votre chaîne contient des guillemets simples, vous pouvez utiliser des guillemets doubles pour citer la chaîne, ou si elle contient des guillemets doubles, vous pouvez utiliser des guillemets simples pour citer la chaîne. Mais si votre chaîne contient à la fois des guillemets simples et des guillemets doubles, vous devez échapper à celui qui utilisé pour citer la chaîne.

Généralement, nous utilisons des guillemets simples pour une valeur de chaîne SQL, nous devons donc utiliser des guillemets doubles pour une chaîne PHP.

$query = "INSERT INTO table (id, col1, col2) VALUES (NULL, 'val1', 'val2')";

Et vous pouvez utiliser une variable dans la chaîne entre guillemets de PHP:

$query = "INSERT INTO table (id, col1, col2) VALUES (NULL, '$val1', '$val2')";

Mais si $val1ou $val2contient des guillemets simples, cela rendra votre SQL erroné. Vous devez donc y échapper avant de l'utiliser dans sql; c'est pour ça mysql_real_escape_string. (Bien qu'une déclaration préparée soit meilleure.)

xdazz
la source
12

En combinaison de PHP et MySQL, les guillemets doubles et les guillemets simples rendent votre temps d'écriture de requête tellement plus facile.

$query = "INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, '$val1', '$val2')";

Supposons maintenant que vous utilisez une variable de publication directe dans la requête MySQL, puis utilisez-la de cette façon:

$query = "INSERT INTO `table` (`id`, `name`, `email`) VALUES (' ".$_POST['id']." ', ' ".$_POST['name']." ', ' ".$_POST['email']." ')";

C'est la meilleure pratique pour utiliser des variables PHP dans MySQL.

vipul sorathiya
la source
Par conséquent, les guillemets doubles sont flexibles mais ne peuvent pas être utilisés comme identificateurs.
rhavendc
Veuillez ne jamais utiliser directement la saisie utilisateur non échappée dans votre requête!
jankal
@jankal C'est juste un exemple. J'ai spécifié que si vous utilisez une entrée utilisateur directe, alors n alors ...........
vipul sorathiya
@vipulsorathiya Veuillez spécifier dans votre réponse que les variables POST doivent être échappées. Vous pointez maintenant sur leur utilisation directe dans votre requête. Mauvais pour les débutants qui essaient cela ...
RFLdev
12

Il y a eu ici de nombreuses réponses utiles, qui ont généralement abouti à deux points.

  1. Les BACKTICKS (`) sont utilisés autour des noms d'identifiant.
  2. LES CITATIONS SIMPLES (') sont utilisées autour des valeurs.

ET comme l'a dit @MichaelBerkowski

Les backticks doivent être utilisés pour les identifiants de table et de colonne, mais ne sont nécessaires que lorsque l'identifiant est un MySQLmot clé réservé, ou lorsque l'identifiant contient des espaces ou des caractères au-delà d'un ensemble limité (voir ci-dessous). Il est souvent recommandé d'éviter d'utiliser des mots clés réservés comme identificateurs de colonne ou de table lorsque cela est possible, en évitant le problème de citation.

Il y a cependant un cas où un identifiant ne peut être ni un mot - clé réservé, ni contenir des espaces ou des caractères au-delà d'un ensemble limité, mais nécessite nécessairement des retours en arrière autour d'eux.

EXEMPLE

123E10est un nom d'identifiant valide mais également un INTEGERlittéral valide .

[Sans entrer dans les détails pour obtenir un tel nom d'identifiant], supposons que je veuille créer une table temporaire nommée 123456e6.

Aucune erreur sur les backticks.

DB [XXX]> create temporary table `123456e6` (`id` char (8));
Query OK, 0 rows affected (0.03 sec)

ERREUR lorsque vous n'utilisez pas de backticks.

DB [XXX]> create temporary table 123451e6 (`id` char (8));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '123451e6 (`id` char (8))' at line 1

Cependant, 123451a6c'est un nom d'identifiant parfaitement fin (sans tiques arrière).

DB [XXX]> create temporary table 123451a6 (`id` char (8));
Query OK, 0 rows affected (0.03 sec)

C'est complètement parce que 1234156e6c'est aussi un nombre exponentiel.

MJ007
la source
10

Si les colonnes et les valeurs de table sont des variables, il y a deux façons:

Avec des guillemets doubles, ""la requête complète:

$query = "INSERT INTO $table_name (id, $col1, $col2)
                 VALUES (NULL, '$val1', '$val2')";

Ou

 $query = "INSERT INTO ".$table_name." (id, ".$col1.", ".$col2.")
               VALUES (NULL, '".$val1."', '".$val2."')";

Avec des guillemets simples '':

$query = 'INSERT INTO '.$table_name.' (id, '.$col1.', '.$col2.')
             VALUES (NULL, '.$val1.', '.$val2.')';

Utilisez les ticks arrière ``lorsqu'un nom de colonne / valeur est similaire à un mot clé réservé MySQL.

Remarque: Si vous dénotez un nom de colonne avec un nom de table, utilisez des graduations comme ceci:

`table_name`. `column_name` <- Remarque: exclure . des tiques arrière.

diEcho
la source
8

Des guillemets simples doivent être utilisés pour les valeurs de chaîne comme dans la liste VALUES ().

Les backticks sont généralement utilisés pour indiquer un identifiant et ainsi être à l'abri de l'utilisation accidentelle des mots-clés réservés.

En combinaison de PHP et MySQL, les guillemets doubles et les guillemets simples facilitent le temps d'écriture de vos requêtes.

john igneel
la source
4

En plus de toutes les réponses (bien expliquées), il n'y a pas eu les suivantes et je visite ce Q&R assez souvent.

En un mot; MySQL pense que vous voulez faire des calculs sur sa propre table / colonne et interprète les tirets comme "e-mail" comme e moins mail .


Avertissement: J'ai donc pensé ajouter ceci comme un type de réponse "FYI" pour ceux qui sont complètement nouveaux dans le travail avec les bases de données et qui peuvent ne pas comprendre les termes techniques déjà décrits.

Funk Forty Niner
la source
1

Les serveurs SQL et MySQL, PostgreySQL, Oracle ne comprennent pas les guillemets doubles ("). Ainsi, votre requête doit être exempte de guillemets doubles (") et ne doit utiliser que des guillemets simples (').

Back-trip (`) est facultatif à utiliser dans SQL et est utilisé pour le nom de table, le nom de base de données et les noms de colonne.

Si vous essayez d'écrire une requête dans votre back-end pour appeler MySQL, vous pouvez utiliser des guillemets doubles (") ou des guillemets simples (') pour affecter une requête à une variable comme:

let query = "select id, name from accounts";
//Or
let query = 'select id, name from accounts';

S'il y a une whereinstruction dans votre requête et / ou essayez insertune valeur et / ou une updatevaleur qui est une chaîne, utilisez des guillemets simples (') pour ces valeurs comme:

let querySelect = "select id, name from accounts where name = 'John'";
let queryUpdate = "update accounts set name = 'John' where id = 8";
let queryInsert = "insert into accounts(name) values('John')";

//Please not that double quotes are only to be used in assigning string to our variable not in the query
//All these below will generate error

let querySelect = 'select id, name from accounts where name = "John"';
let queryUpdate = 'update accounts set name = "John" where id = 8';
let queryInsert = 'insert into accounts(name) values("John")';

//As MySQL or any SQL doesn't understand double quotes("), these all will generate error.

Si vous voulez éviter cette confusion lorsque vous utilisez des guillemets doubles (") et des guillemets simples ('), nous vous recommandons de vous en tenir aux guillemets simples ('), ce qui inclura une barre oblique inverse () comme:

let query = 'select is, name from accounts where name = \'John\'';

Un problème avec les guillemets doubles (") ou simples (') survient lorsque nous avons dû attribuer une valeur dynamique et effectuer une concaténation de chaîne comme:

let query = "select id, name from accounts where name = " + fName + " " + lName;
//This will generate error as it must be like name = 'John Smith' for SQL
//However our statement made it like name = John Smith

//In order to resolve such errors use
let query = "select id, name from accounts where name = '" + fName + " " + lName + "'";

//Or using backslash(\)
let query = 'select id, name from accounts where name = \'' + fName + ' ' + lName + '\'';

Si vous avez besoin d'un dégagement supplémentaire, suivez les devis en JavaScript

NAVIN
la source