Какое значение имеет вопросительный знак в MySQL на "WHERE column =?"?
Я разбираю код и наткнулся на это,
$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 ответа
Подготовленные отчеты используют '?' в MySQL, чтобы разрешить привязку параметров к заявлению. Высоко оценивается как более безопасный от SQL-инъекций при правильном использовании. Это также позволяет быстрее выполнять запросы SQL, так как запрос должен быть скомпилирован только один раз и может быть использован повторно.
Знак вопроса представляет параметр, который впоследствии будет заменен. Использование параметризованных запросов более безопасно, чем встраивание параметров прямо в запрос.
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
представляет цифры.
?
не имеет особого значения в 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
Например, в Rails вопросительный знак заменяется аргументом, заданным переменной языка программирования библиотеки (Ruby), например:
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
'
Это подготовленные заявления, подготовленные заявления предлагают два основных преимущества:
Запрос должен быть проанализирован (или подготовлен) только один раз, но может быть выполнен несколько раз с одинаковыми или разными параметрами. Когда запрос подготовлен, база данных проанализирует, скомпилирует и оптимизирует свой план для выполнения запроса. Для сложных запросов этот процесс может занять достаточно времени, что заметно замедлит работу приложения, если возникнет необходимость повторять один и тот же запрос много раз с разными параметрами. Используя подготовленное утверждение, приложение избегает повторения цикла анализа / компиляции / оптимизации. Это означает, что подготовленные операторы используют меньше ресурсов и, следовательно, работают быстрее.
Параметры для подготовленных заявлений не должны быть указаны; водитель автоматически обрабатывает это. Если приложение использует исключительно подготовленные операторы, разработчик может быть уверен, что SQL-инъекция не произойдет (однако, если другие части запроса создаются с неэкранированным вводом, SQL-инъекция все еще возможна).