Какое значение имеет вопросительный знак в 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-инъекция все еще возможна).

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

Другие вопросы по тегам