Добро пожаловать на форум PHP программистов!
За последние 24 часа нас посетили 18288 программистов и 1684 робота. Сейчас ищут 686 программистов ...
Приступая к работе

Подготовленные запросы и хранимые процедуры

Вернуться к: PDO

Большинство баз данных поддерживают концепцию подготовленных запросов. Что это такое? Это можно описать, как некий вид скомпилированного шаблона SQL запроса, который будет запускаться приложением и настраиваться с помощью входных параметров. У подготовленных запросов есть два главных преимущества:

  • Запрос необходимо однажды подготовить и затем его можно запускать столько раз, сколько нужно, причем как с теми же, так и с отличающимися параметрами. Когда запрос подготовлен, СУБД анализирует его, компилирует и оптимизирует план его выполнения. В случае сложных запросов этот процесс может занимать ощутимое время и заметно замедлить работу приложения, если потребуется много раз выполнять запрос с разными параметрами. При использовании подготовленного запроса СУБД анализирует/компилирует/оптимизирует запрос любой сложности только один раз, а приложение запускает на выполнение уже подготовленный шаблон. Таким образом подготовленные запросы потребляют меньше ресурсов и работают быстрее.
  • Параметры подготовленного запроса не требуется экранировать кавычками; драйвер это делает автоматически. Если в приложении используются исключительно подготовленные запросы, разработчик может быть уверен, что никаких SQL инъекций случиться не может (однако, если другие части текста запроса записаны с неэкранированными символами, SQL инъекции все же возможны; здесь речь идет именно о параметрах).

Подготовленные запросы также полезны тем, что PDO может эмулировать их, если драйвер базы данных не имеет подобного функционала. Это значит, что приложение может пользоваться одной и той же методикой доступа к данным независимо от возможностей СУБД.

Пример #1 Повторяющиеся вставки в базу с использованием подготовленных запросов

В этом примере 2 раза выполняется INSERT запрос с разными значениями name и value, которые подставляются вместо соответствующих псевдопеременных:

<?php
$stmt 
$dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name'$name);
$stmt->bindParam(':value'$value);

// вставим одну строку
$name 'one';
$value 1;
$stmt->execute();

// теперь другую строку с другими значениями
$name 'two';
$value 2;
$stmt->execute();
?>

Пример #2 Повторяющиеся вставки в базу с использованием подготовленных запросов

В этом примере 2 раза выполняется INSERT запрос с разными значениями name и valueкоторые подставляются вместо псевдопеременных ?.

<?php
$stmt 
$dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1$name);
$stmt->bindParam(2$value);

// вставим одну строку
$name 'one';
$value 1;
$stmt->execute();

// теперь другую строку с другими значениями
$name 'two';
$value 2;
$stmt->execute();
?>

Пример #3 Выборка данных с использованием подготовленных запросов

В этом примере производится выборка из базы по ключу, который вводит пользователь через форму. Пользовательский ввод автоматически заключается в кавычки, поэтому нет риска SQL инъекции.

<?php
$stmt 
$dbh->prepare("SELECT * FROM REGISTRY where name = ?");
if (
$stmt->execute(array($_GET['name']))) {
  while (
$row $stmt->fetch()) {
    
print_r($row);
  }
}
?>

Если СУБД поддерживает выходные параметры, приложение может пользоваться ими также как и входными. Выходные параметры обычно используют для получения данных из хранимых процедур. Пользоваться выходными параметрами несколько сложнее, так как разработчику необходимо знать максимальный размер извлекаемых значений еще на этапе задания этих параметров. Если извлекаемое значение окажется больше, чем предполагалось, будет вызвана ошибка.

Пример #4 Вызов хранимой процедуры с выходными параметрами

<?php
$stmt 
$dbh->prepare("CALL sp_returns_string(?)");
$stmt->bindParam(1$return_valuePDO::PARAM_STR4000); 

// вызов хранимой процедуры
$stmt->execute();

print 
"процедура вернула $return_value\n";
?>

Можно задать параметр одновременно входным и выходным; синтаксис при этом тот же, что и для выходных параметров. В следующем примере строка 'привет' передается в хранимую процедуру, а затем эта строка будет заменена возвращаемым значением.

Пример #5 Вызов хранимой процедуры с входным/выходным параметром

<?php
$stmt 
$dbh->prepare("CALL sp_takes_string_returns_string(?)");
$value 'привет';
$stmt->bindParam(1$valuePDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT4000); 

// вызов хранимой процедуры
$stmt->execute();

print 
"процедура вернула $value\n";
?>

Пример #6 Неправильное использование псевдопеременной

<?php
$stmt 
$dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'");
$stmt->execute(array($_GET['name']));

// псевдопеременная может использоваться только в виде отдельного значения
$stmt $dbh->prepare("SELECT * FROM REGISTRY where name LIKE ?");
$stmt->execute(array("%$_GET[name]%"));
?>



Вернуться к: PDO

© 2024 «PHP.RU — Сообщество PHP-Программистов»
Главная | Форум | Реклама на сайте | Контакты VIP Сувениры
Разработка компании ODware