Когда вы используете PDO
с драйвер MSSQL вы фактически используете FreeTDS как драйвер низкого уровня. Существует несколько способов выполнения хранимых процедур - языковых запросов и вызов RPC.
FreeTDS также поддерживает протокол TDS версии 4.2 и 7.x. Основное различие между ними - поведение вызова хранимой процедуры. Microsoft изменила поведение от протокола 4.2 до 7.0 не возвращая выходные параметры из языковых запросов. Языковые запросы главным образом отправляют текстовый запрос на сервер, упаковывая в пакет TDS.
Пример языкового запроса с PDO (из php.net)
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)");
$value = 'Hello!';
$stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);
$stmt->execute();
print "The output is $value\n";
На самом деле вы отправляете что-то вроде "EXEC sp_takes....". И если вы запустите образец выше с MSSQL, вы получите пустой параметр вывода в TDS 7.х и ожидаемый результат с 4.2. Почему мы не можем использовать 4.2 и быть счастливыми? В нем много ограничений :
- Только ASCII, конечно.
- RPC и BCP не поддерживаются.
- Поля varchar ограничены 255 символами. Если ваша таблица определяет более длинные поля, они будут усечены.
- динамические запросы (также называемые
prepared statements
) не поддерживаются.
Итак, 4.2 не является вариантом.
Пример вызова RPC (из расширение php.net odbtp)
$stmt = mssql_init('sp_takes_string_returns_string');
$value = 'Hello!';
mssql_bind($stmt, 1, $value, SQLVARCHAR, true, false, 4000);
mssql_execute($stmt);
print "The output is $value\n";
Используя пример выше с собственным расширением mssql в php, вы получили правильный результат с помощью TDS 7.2. Фактически вы отправляете бинарный пакет RPC с этим кодом.
Вопрос
Есть ли способ сделать вызов RPC для хранимой процедуры с драйверами PDO и MSSQL?