Коли використовувати одиничні лапки, подвійні лапки та зворотні посилання в MySQL


633

Я намагаюся навчитися найкращим способом писати запити. Я також розумію важливість бути послідовною. До сих пір я випадково використовував одиничні цитати, подвійні лапки та зворотні посилання без будь-якої реальної думки.

Приклад:

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

Крім того , в наведеному вище прикладі, вважають , що table, col1, val1і т.д. , можуть бути змінними.

Який стандарт для цього? Що ти робиш?

Я читав відповіді на подібні запитання тут близько 20 хвилин, але, здається, немає остаточної відповіді на це питання.


16
Зауважте, що це дуже специфічне питання для MySQL. Загалом SQL (тобто ISO / ANSI SQL) має різний набір лапок: подвійні лапки призначені для розмежованих ідентифікаторів, наприклад "tablename", а одиничні цитати - для літералів, наприклад 'this is a some text'. Зворотні кліти ніколи не використовуються в стандартному SQL. (Якщо вам потрібно включити подвійну лапочку в ідентифікатор, введіть її двічі "odd""tablename". Аналогічно, подвійні одинарні лапки, як-от 'Conan O''Brien'.)
jarlh

Відповіді:


609

Зворотні посилання слід використовувати для ідентифікаторів таблиць і стовпців, але вони необхідні лише тоді, коли ідентифікатор є зарезервованим ключовим словом MySQL або коли ідентифікатор містить символи пробілів або символи, що перевищують обмежений набір (див. Нижче) Часто рекомендується уникати використання зарезервованих ключових слів як можливі ідентифікатори стовпців або таблиць, коли це можливо, уникаючи проблеми котирування.

Одиничні лапки повинні використовуватися для рядкових значень, як у VALUES()списку. Подвійні лапки підтримуються MySQL і для рядкових значень, але одинарні лапки більш широко прийняті іншими RDBMS, тому є доброю звичкою використовувати одинарні лапки замість подвійних.

MySQL також розраховує, що DATEі DATETIMEбуквальні значення будуть одноцитованими як рядки '2001-01-01 00:00:00'. Для отримання більш детальної інформації зверніться до документації з літератури дати та часу , зокрема альтернативи використанню дефіса -як роздільника сегмента у рядках дати.

Отже, використовуючи ваш приклад, я би подвійно цитував рядок PHP і використовував одиничні лапки на значення 'val1', 'val2'. NULLє ключовим словом MySQL і спеціальним (не) значенням, тому його не цитують.

Жоден із цих ідентифікаторів таблиці чи стовпців не є зарезервованими словами або не використовує символи, що вимагають цитування, але я все-таки цитував їх із задніми посиланнями (докладніше про це пізніше ...).

Функції, вроджені для RDBMS (наприклад, NOW()в MySQL), не повинні цитуватися, хоча їхні аргументи підпорядковуються тим самим рядкам або ідентифікаційним правилам цитування, які вже були згадані.

Backtick (`)
таблиця та стовпець ─────────────────────────────────────────────────────── ───────┐
                      ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
$ query = " ВСТАВИТИ в таблицю` (` id`, `col1`,` col2`, `дата`,` оновлено`)
                       ЦІННОСТІ (NULL, 'val1', 'val2', '2001-01-01', NOW ()) ";
                               ↑↑↑↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑↑↑↑↑ 
Без котирування ключове слово ─────┴┴┴┘ │ │ │ │ │ │ │││││
Одно цитовані (') рядки ────────────────────────┘ │ │ │││││
Одноцитовані (') ДАТА ────────────────────────────────────────┘ ││││ │
Без котирування функція ──────────────────────────────────────────┴┴┴┴┘    

Змінна інтерполяція

Шаблони цитування змінних не змінюються, хоча якщо ви маєте намір інтерполювати змінні безпосередньо в рядок, вони повинні бути подвійними цитатами в PHP. Просто переконайтеся, що ви правильно уникнули змінних для використання в SQL. ( Рекомендується натомість використовувати API, що підтримує підготовлені оператори, як захист від введення SQL ).

// Те саме з деякими змінними замінами
// Тут ім'я змінної таблиці $ table цитується за допомогою зворотного вибору та змінних
// у списку ЦІННОСТІ наведені одноцитування 
$ query = "ВСТАВИТИСЬ В` $ table` (`id`,` col1`, `col2`,` date`) VALUES (NULL, '$ val1' , '$ val2' , '$ date' ) ";

Підготовлені заяви

Працюючи з підготовленими заявами, проконсультуйтеся з документацією, щоб визначити, чи потрібно цитувати заставники заяви. Найпопулярніші API, доступні в PHP, PDO та MySQLi, очікують не котируваних заповнювачів, як і більшість підготовлених API заяв іншими мовами:

// 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 (?, ?, ?, ?)";

Символи, що вимагають цитування зворотного посилання в ідентифікаторах:

Згідно з документацією на MySQL , вам не потрібно цитувати (backtick) ідентифікаторів, використовуючи такий набір символів:

ASCII: [0-9,a-z,A-Z$_](основні латинські літери, цифри 0-9, долар, підкреслення)

Ви можете використовувати символи поза цим набором як ідентифікатори таблиці або стовпців, включаючи, наприклад, пробіл, але тоді ви повинні цитувати їх (backtick).


43
", але одинарні лапки більш широко приймаються іншими RDBMS " - використання одиничних лапок для рядкових літералів визначається (і вимагається) стандартом SQL
a_horse_with_no_name

@a_horse_with_no_name майже ніхто не використовує ANSI MySQL ('|' для рядка concat - справді?)
Good Person

3
це неправда: "MySQL також очікує, що значення DATE та DATETIME буквально будуть цитуватися в одному
коду

3
@evilReiko Документи MySQL, схоже, не чітко адресують псевдоніми, котируючи їх. Він прийме одиночний, подвійний або зворотний відбір для псевдонімів, але на це можуть вплинути різні режими ANSI SQL. Я не впевнений, що вимагає специфікація SQL для цитат псевдонімів - Особисті переваги: ​​для послідовності я цитую їх так само, як ідентифікатори стовпців - тобто я або беруть їх назад, якщо потрібно, або залишаю їх без котировки, якщо ні. Я не використовую одиночні чи подвійні лапки на псевдонімах.
Майкл Берковський

2
@GuneyOzsan Так, дуже вразливий. Ніколи не використовуйте змінну для імені таблиці, якщо вона не була затверджена відповідно до списку прийнятних імен таблиць - створіть масив допустимих імен та перевірте, чи змінна відповідає чимось у списку, щоб зробити її безпечною у використанні. В іншому випадку ви не можете безпечно уникнути змінної імені таблиці для використання.
Майкл Берковський

121

У MySQL є два типи цитат:

  1. ' для додавання рядкових літералів
  2. ` для введення ідентифікаторів, таких як назви таблиць та стовпців

І тут "є якийсь особливий випадок. Він може використовуватися для однієї з вищезазначених цілей одночасно, залежно від сервера MySQL sql_mode:

  1. За замовчуванням" символ може бути використаний , щоб докласти рядкові літерали так само , як'
  2. У ANSI_QUOTESрежимі "характер може використовуватися для того, щоб укладати ідентифікатори так само, як`

Наступний запит дасть різні результати (або помилки) залежно від режиму SQL:

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

ANSI_QUOTES вимкнено

Запит вибере рядковий рядок, "column"де стовпець fooдорівнює рядку"bar"

ANSI_QUOTES увімкнено

Запит вибере стовпець, у columnякому стовпець fooдорівнює стовпцюbar

Коли використовувати що

  • Я пропоную вам уникати використання, "щоб ваш код став незалежним від режимів SQL
  • Завжди цитуйте ідентифікатори, оскільки це є хорошою практикою (досить багато питань, про які це обговорюють)

32

(Є гарні відповіді вище щодо характеру SQL вашого запитання, але це також може бути актуальним, якщо ви новачок у PHP.)

Можливо, важливо згадати, що PHP по-різному обробляє одиночні та подвійні цитовані рядки ...

Рядки з одним котируванням є "буквальними" і в значній мірі є рядками WYSIWYG. Рядки з подвійним котируванням інтерпретуються PHP для можливої ​​підстановки змінної (backticks у PHP не є точно рядками; вони виконують команду в оболонці і повертають результат).

Приклади:

$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

23

Зворотні посилання, як правило, використовуються для позначення identifierта, а також для захисту від випадкового використання зарезервованих ключових слів .

Наприклад:

Use `database`;

Тут підсистема допоможе серверу зрозуміти, що databaseнасправді це ім’я бази даних, а не ідентифікатор бази даних.

Те ж саме можна зробити для назв таблиць та назв полів. Це дуже гарна звичка, якщо ви обернете свій ідентифікатор бази даних за допомогою зворотних посилань.

Перевірте цю відповідь, щоб дізнатися більше про зворотні посилання.


Тепер про подвійні цитати та одинарні котирування (Майкл вже згадував про це).

Але, щоб визначити значення, ви повинні використовувати або одиничні, або подвійні лапки. Давайте подивимось інший приклад.

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

Тут я навмисно забув обернути title1цитатами. Тепер сервер прийме title1як стовпець ім'я (тобто ідентифікатор). Отже, щоб вказати, що це значення, ви повинні використовувати або подвійні, або одиничні лапки.

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

Тепер у поєднанні з PHP подвійні лапки та одиничні цитати значно полегшують час написання запиту. Давайте подивимось модифіковану версію запиту у вашому запитанні.

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

Тепер, використовуючи подвійні лапки в PHP, ви будете робити змінні $val1та $val2використовувати їх значення, створюючи таким чином ідеально правильний запит. Подібно до

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

зробить

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

15

В MySQL, ці символи використовуються для поділу запиту `, ", 'і ().

  1. "або 'використовуються для огороджувальних струноподобних значень "26-01-2014 00:00:00"або '26-01-2014 00:00:00'. Ці символи тільки для рядків, які не агрегатні функції , такі як now, sumабо max.

  2. ` використовується для додавання назв таблиці або стовпців, наприклад select `column_name` from `table_name` where id='2'

  3. (і )просто додайте частини запиту, наприклад select `column_name` from `table_name` where (id='2' and gender='male') or name='rakesh'.


13

Літеральні рядки в MySQL та PHP однакові.

Рядок - це послідовність байтів або символів, укладених у межах однієї цитати ("" ") або подвійної лапки (" "").

Отже, якщо ваша рядок містить одинарні лапки, то ви можете використовувати подвійні лапки для цитування рядка, або якщо вони містять подвійні лапки, то ви можете використовувати одинарні лапки для цитування рядка. Але якщо ваша рядок містить як одиничні, так і подвійні лапки, вам потрібно уникати тієї, яка використовувалась для цитування рядка.

Здебільшого ми використовуємо одиничні лапки для значення рядка SQL, тому нам потрібно використовувати подвійні лапки для рядка PHP.

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

І ви можете використати змінну в подвійному цитуванні рядка PHP:

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

Але якщо $val1або $val2містять одинарні лапки, це зробить ваш SQL помилковим. Тому вам потрібно уникнути цього, перш ніж він буде використаний у sql; це те mysql_real_escape_string, для чого. (Хоча підготовлена ​​заява краще.)


12

У поєднанні PHP та MySQL подвійні лапки та одиничні цитати значно полегшують час написання запитів.

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

Тепер, припустимо, ви використовуєте змінну прямого повідомлення у запиті MySQL, використовуйте її наступним чином:

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

Це найкраща практика використання змінних PHP в MySQL.


Тому подвійні лапки є гнучкими, але їх не можна використовувати як ідентифікатори.
rhavendc

Будь ласка, ніколи безпосередньо не використовуйте у своєму запиті нездійснені користувальницькі дані!
jankal

@jankal Це просто приклад. Я вказав, що якщо ви використовуєте прямий ввід користувача, тоді n тоді ...........
vipul sorathiya

@vipulsorathiya Будь ласка, вкажіть у своїй відповіді, що слід перемістити змінні POST. Тепер ви вказуєте на їх використання безпосередньо у вашому запиті. Погано для початківців, які намагаються це зробити ...
RFLdev

12

Тут було багато корисних відповідей, які, як правило, завершилися двома пунктами.

  1. BACKTICKS (`) використовуються навколо імен ідентифікаторів.
  2. ОДНІ КОШТИ (') використовуються навколо значень.

І як сказав @MichaelBerkowski

Зворотні посилання слід використовувати для ідентифікаторів таблиць і стовпців, але вони необхідні лише тоді, коли ідентифікатор є MySQLзарезервованим ключовим словом або коли ідентифікатор містить символи або символи пробілу за межами обмеженого набору (див. Нижче) Часто рекомендується уникати використання зарезервованих ключових слів як Ідентифікатори стовпців або таблиць, коли це можливо, уникаючи проблеми цитування.

Однак є випадок, коли ідентифікатор не може бути зарезервованим ключовим словом або містити пробіли або символи за межами обмеженого набору, але обов'язково потребує зворотних посилань навколо них.

ПРИКЛАД

123E10є дійсним ідентифікаційним іменем, але також допустимим INTEGERлітералом

[Не вникаючи в деталі, як ви отримаєте таке ім'я ідентифікатора], припустимо, я хочу створити тимчасову таблицю з назвою 123456e6.

На задніх планах немає ПОМИЛКИ.

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

ПОМИЛКА, коли не використовуються зворотні посилання.

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

Однак 123451a6це ідеально чітка назва ідентифікатора (без зворотних кліщів).

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

Це повністю тому, що 1234156e6це також експоненціальне число.


10

Якщо таблиці таблиць і значення є змінними, то є два способи:

З подвійними цитатами ""повний запит:

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

Або

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

З одинарними цитатами '':

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

Використовуйте галочки, ``коли назва стовпця / значення схоже на ключове слово, зарезервоване в MySQL.

Примітка. Якщо ви позначаєте ім'я стовпця з назвою таблиці, тоді використовуйте зворотні клітинки таким чином:

`table_name`. `column_name` <- Примітка: виключити . із зворотних кліщів.


8

Одиничні лапки повинні використовуватися для рядкових значень, таких як у списку VALUES ().

Зворотні посилання, як правило, використовуються для позначення ідентифікатора, а також захищаються від випадкового використання зарезервованих ключових слів.

У поєднанні PHP та MySQL подвійні лапки та одиничні цитати значно спрощують час написання запиту.


4

Окрім усіх (добре пояснених) відповідей, не було згаданих нижче, і я часто відвідую це запитання та відповіді.

Коротко; MySQL вважає, що ви хочете займатися математикою у власній таблиці / стовпчику, і інтерпретує дефіси, такі як "електронна пошта", як e мінус mail .


Відмова: Тому я подумав, що додаю це як "відповідь" типу відповіді для тих, хто абсолютно новий у роботі з базами даних і хто може не розуміти технічні умови, описані вже.


1

Сервери SQL і MySQL, PostgreySQL, Oracle не розуміють подвійних лапок ("). Таким чином, ваш запит не повинен мати подвійних лапок (") і використовувати лише одиничні лапки (').

Back-trip (`) необов’язково використовувати в SQL і використовується для імені таблиці, імені db та імен стовпців.

Якщо ви намагаєтесь написати запит у своєму бек-енді, щоб зателефонувати на MySQL, ви можете скористатися подвійною цитатою (") або одинарними лапками ("), щоб призначити запит змінній на зразок:

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

Якщо ther - це whereтвердження у вашому запиті та / або намагається insertотримати значення та / або updateзначення, яке є рядковим, використовуйте єдину цитату (') для таких значень, як:

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.

Якщо ви хочете оминути цю плутанину при використанні подвійних лапок (") та одинарних лапок ('), рекомендуємо дотримуватися одинарних лапок ('), це буде включати зворотну косу рису (), наприклад:

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

Проблема з подвійними (") або одинарними (") лапками виникає, коли нам потрібно було призначити деяку динаміку значення та виконати деяке об'єднання рядків, наприклад:

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 + '\'';

Якщо потрібно додаткове очищення, виконайте цитати в JavaScript

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.