Какое значение имеет вопросительный знак в MySQL в «WHERE column =?»? - PullRequest
38 голосов
/ 23 марта 2009

Я разбираю какой-то код и наткнулся на это,

$sql = 'SELECT page.*, author.name AS author, updator.name AS updator '
     . 'FROM '.TABLE_PREFIX.'page AS page '
     . 'LEFT JOIN '.TABLE_PREFIX.'user AS author ON author.id = page.created_by_id '
     . 'LEFT JOIN '.TABLE_PREFIX.'user AS updator ON updator.id = page.updated_by_id '
     . 'WHERE slug = ? AND parent_id = ? AND (status_id='.Page::STATUS_REVIEWED.' OR status_id='.Page::STATUS_PUBLISHED.' OR status_id='.Page::STATUS_HIDDEN.')';

Мне интересно, что за "?" делает в заявлении WHERE. Это какой-то держатель параметра?

Ответы [ 4 ]

36 голосов
/ 23 марта 2009

Подготовленные отчеты используют '?' в MySQL, чтобы разрешить привязку параметров к заявлению. Высоко оценивается как более безопасный от SQL-инъекций при правильном использовании. Это также позволяет быстрее выполнять запросы SQL, поскольку запрос должен быть скомпилирован только один раз и может быть использован повторно.

27 голосов
/ 23 марта 2009

Знак вопроса представляет параметр, который впоследствии будет заменен. Использование параметризованных запросов более безопасно, чем встраивание параметров прямо в запрос.

SQL Server вызывает параметризованные запросы, а Oracle вызывает привязку переменных.

Использование зависит от языка, с которого вы выполняете запрос.

Вот пример того, как он используется из PHP.

при условии, что $mysqli - это соединение с базой данных, а people - это таблица с 4 столбцами.

$stmt = $mysqli->prepare("INSERT INTO People VALUES (?, ?, ?, ?)");

$stmt->bind_param('sssd', $firstName, $lastName, $email, $age);

'sssd' - это флаг, обозначающий остальные параметры, где s представляет строку, а d представляет цифры.

7 голосов

? не имеет особого значения в MySQL WHERE = операторы

Это имеет особое значение только для нескольких внешних интерфейсов, таких как PHP stdlib, и веб-фреймворков, таких как Rails.

? - это просто синтаксическая ошибка в:

CREATE TABLE t (s CHAR(1));
SELECT * FROM t WHERE s = ?;

потому что это не в кавычках, а в:

INSERT INTO t VALUES ('a');
INSERT INTO t VALUES ("?");
SELECT * FROM t WHERE s = '?';

возвращает:

s
?

таким образом, по-видимому, без особого значения.

Пример рельса

Например, в Rails знак вопроса заменяется аргументом, заданным переменной языка программирования библиотеки (Ruby), например ::1010 *

Table.where("column = ?", "value")

и он автоматически заключает в кавычки аргументы, чтобы избежать ошибок и внедрения SQL, генерируя выражение вроде:

SELECT * FROM Table WHERE column = 'value';

Цитирование спасет нас в случае чего-то вроде:

Table.where("column = ?", "; INJECTION")

MySQL 5.0 подготовленные операторы

В MySQL 5.0 добавлена ​​ функция подготовленного оператора , которая имеет семантику, сходную с вопросительным знаком в веб-фреймворках.

Пример из документации:

PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
SET @a = 3;
SET @b = 4;
EXECUTE stmt1 USING @a, @b;

Выход:

hypotenuse
5

Они также экранируют специальные символы, как и ожидалось:

PREPARE stmt1 FROM 'SELECT ? AS s';
SET @a = "'";
EXECUTE stmt1 USING @a;

Выход:

s
'
1 голос
/ 11 февраля 2013

Это подготовленные заявления, подготовленные заявления предлагают два основных преимущества:

Запрос должен быть проанализирован (или подготовлен) только один раз, но может быть выполняется несколько раз с одинаковыми или разными параметрами. когда запрос подготовлен, база данных проанализирует, скомпилирует и оптимизирует его план для выполнения запроса. Для сложных запросов этот процесс может займет достаточно времени, чтобы приложение заметно замедлило если есть необходимость повторять один и тот же запрос много раз с разными параметры. Используя подготовленное утверждение, приложение избегает повторение цикла анализа / компиляции / оптимизации. Это значит что готов операторы используют меньше ресурсов и, следовательно, работают быстрее.

Параметры к подготовленным утверждениям не нужно заключать в кавычки; водитель автоматически обрабатывает это. Если приложение использует исключительно Подготовив заявления, разработчик может быть уверен, что SQL-инъекций нет будет происходить (однако, если другие части запроса строятся с неэкранированным вводом SQL-инъекция все еще возможна).

http://php.net/manual/en/pdo.prepared-statements.php

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...