Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
при СП оракловая база будет использовать один план запроса
Я мог бы многое рассказать про связываемые переменные в Oracle…
$sql = 'select * from price_'.mysql_escape_string($_GET['year']).' order by name';
;drop table user;... явно сделает то, что хотел хакер. И простой mysql_real_escape_string никак не спасет, нужна более серьезная проверка.$sql = 'select * from price';
$cond = Array();
for($i=0;$i<2;$i++)
{
if($_GET['order_'.$i]=='name')
$cond []= 'name';
if($_GET['order_'.$i]=='price')
$cond []= 'price';
if($_GET['order_'.$i]=='count')
$cond []= 'count';
}
if(count($cond)>0)
$sql .= ' order by '.implode(',',$cond);
for($i=0;$i<2;$i++)
{
$cond []= $_GET['order_'.$i;
}
public function getFormContent($language, $dict_id, $from, $to, $filter){
$this->connect();
self::$connection_oracle->setRequestParam('p_lang', $language);
self::$connection_oracle->setRequestParam('p_dict_id', $dict_id);
self::$connection_oracle->setRequestParam('p_from', $from);
self::$connection_oracle->setRequestParam('p_to', $to);
$queryParams = '';
foreach($filter as $key=>$value){
self::$connection_oracle->setRequestParam($key, $value);
$queryParams=$queryParams.',:'.$key;
}
$query = "SELECT * FROM TABLE(". self::PKG_DICT_VIEW .".get_dict_data(:p_lang, :p_dict_id, :p_from, :p_to".$queryParams."))";
return self::$connection_oracle->requestArrayHash($query);
}
«Достоинства»
(1) и (2) В типичном веб-приложении данные достоинства могут проявиться очень редко. Один и тот же запрос выполненный несколько раз в пределах одного и того же соединения — это, чаще всего, показатель кривого кода.
С точки зрения кэша плана запросов — одинаковые.
С какой это стати нет гарантии?
А в чем препятствия-то?
Для запроса «с явными значениями» парсер не сможет отделить значение от ключевых слов, что ли?
при попытке вывести результирующий SQL мы видим все тот же запрос с плейсхолдерами, и выполнить его для отладки в консоли без плясок с бубном несколько затруднительно.
такие конструкции, как IN(...). WHERE IN(:stroka_s_sapyatymi) почему-то не работает.
идентификаторы
В силу технологических особенностей большинства веб-приложений (скрипт запускается для обслуживания реквеста и умирает) все преимущества сводятся на нет,
а вот очевидная задержка — из-за того что для выполнения каждого запроса скрипт обращается к БД по два раза — объективно присутствует.
Можно пример «профайлера», который берет на себя функции парсинга SQL и подстановки данных на место плейсхолдера?
Что такое идентификатор — в принципе, неважно (хотя и вполне понятно из приведенного рядом примера). Нам важен сам факт того, что подготовленные выражения для идентификаторов в принципе невозможны.
По поводу клиента, который требует отдельного обращения к БД — это не ко мне, а к автору топика. Это он ратует за их использование.
SQL Server Profiler никак не поможет мне в моей разработке, когда я составляю динамический запрос средствами серверного ЯП, и передаю для него данные средствами серверного ЯП.
Автор же статьи рассказывает нам о механизме работы родных подготовленных выражений, при которых подстановка данных производится на сервере. при использовании данной технологии обращений к серверу будет два.
Что бы он ни путал, но статья его — о первых.
Иначе ему придется признать использование mysql_real_escape_string() в php, которую он сам же и предал анафеме :)
Насчет профайлера — да, на стороне сервера это можно сделать. Именно в моей формулировке, «парсинг SQL и подстановка данных на место плейсхолдеров».
Очень интересно узнать, как можно обойтись без mysql_real_escape_string() или её аналогов, если мы парсим плейсхолдеры на клиенте.
Судя по всему, вы забыли, о чем шла речь :)
Напомню — о выводе запроса, в пригодном для использовании в консоли виде ;)
exec sp_executesql N'SELECT TOP (2)
[Extent1].[IdAgency] AS [IdAgency],
[Extent1].[IdOrg] AS [IdOrg]
FROM [Refer].[Agency_q] AS [Extent1]
WHERE [Extent1].[IdOrg] = @p__linq__0',N'@p__linq__0 uniqueidentifier',@p__linq__0='6FE130E8-BF13-494B-BABC-D9E85AAA9B56'Как правильно отмечено у автора, МС-у в этом случае приходится "«шерстить» мегабайтную строку, чтобы найти места, где все-таки поставить обратный слэш", или чем там МС искейпит строки.
SELECT * FROM Agency WHERE IdAgency = 8exec sp_executesql N'SELECT * FROM Agency WHERE AgencyName LIKE :name AND IdAgency = :Id',N':name nvarchar(8),:Id int',:name=N'%Москва%',:Id=8Ну, утверждать, что нет никакого искейпинга, можно только если в данных будут подлежащие искейпингу символы.
Поэтому приходится подправлять информацию.
Судя по всему, МС все-таки не выпендривается, а общается с сервером по бинарному протоколу как все, а ваш «запрос, ушедший на сервер. Дословный.» — всего лишь представление, сформированное профайлером для удобства.
Ну я понял, mssql использует бинарный протокол и при этом еще и _параллельно_ парсит и конвертит запросы с плейсхолдерами в одну строку. Двойная работа.
А еще мне понравилось ваше высказывание, что раз IN(..) редко используется, значит и проблемы нет.
Вы понимаете, что если хотя бы раз оно используется, то уже надо что-то делать чтоб заменить плейсхолдеры?
— при попытке вывести результирующий SQL мы видим все тот же запрос с плейсхолдерами, и выполнить его для отладки в консоли без плясок с бубном несколько затруднительно.
Сильные духом пишут специальный код для динамического составления оператора IN… И вместо сокращения кода мы получили его разрастание в несколько раз… Совсем не так все красиво оказалось, как в рекламе?
Ну и по производительности. В силу технологических особенностей большинства веб-приложений (скрипт запускается для обслуживания реквеста и умирает) все преимущества сводятся на нет, а вот очевидная задержка — из-за того что для выполнения каждого запроса скрипт обращается к БД по два раза — объективно присутствует.
I would appreciate if everybody recommending prepared statements as a best practice teaches the pros and cons of the technology in the context of PHP applications: neither does a portable standard definition for server-side prepared statements exist nor did PDO manage to provide a convincing solution for client-side (emulated) prepared statements. Consider that when talking about the best practice “prepared statements”…
$sql = 'select * from reports_'.$_GET['year'];) — бесполезны и mysql_escape_string, и prepared statements, и прочее. Тут надо самого программиста бить, и больно :).
Немного о связываемых переменных (prepared statements)