PDO с драйвером MSSQL, как получить выходные параметры?

Когда вы используете 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 (из расширения odbtp php.net)

    $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?


person misterion    schedule 10.12.2013    source источник
comment
Я что-то помню о необходимости использовать набор результатов для назначения выходов. Вы пытались вызвать $stmt-›fetchAll(); после вашего вызова execute : mssql_execute($stmt); $stmt->fetchAll(); ... , но до использования значения $value.   -  person Gavin    schedule 21.12.2013
comment
К сожалению, не работает.   -  person misterion    schedule 22.12.2013
comment
Я нашел правильный синтаксис. Смотри мой ответ   -  person Marco Marsala    schedule 26.08.2015
comment
stackoverflow.com/a/32224294/2717254   -  person Marco Marsala    schedule 26.08.2015
comment
Возможный дубликат Вызов хранимой процедуры с параметром Out с использованием PDO   -  person Kaj    schedule 01.10.2015


Ответы (2)


Либо я пропустил FreeTDS, когда впервые ответил, либо этот вопрос был обновлен. Так или иначе...

FreeTDS не поддерживает выходные параметры в MSSQL Server 7 SP3 или выше. Это связано с изменениями, внесенными в SQL Server.

---Старый ответ ниже---

Я знаю, что это не совсем то, что вы ищете.
Я просмотрел некоторые старые файлы до единственного раза, когда я связался с MSSQL, и вытащил это.

$con = mssql_connect($db['host'], $db['user'], $db['pass']);
mssql_select_db($db['database'], $con);//Select DB
$result = mssql_query("my_Procedure_Name ".$propertyOne.", ".$propertyTwo."");

надеюсь, это поможет

person r007kit    schedule 19.05.2016

Попробуй это

 try {
    $hostname = "myhost";
    $port = 10060;
    $dbname = "tempdb";
    $username = "dbuser";
    $pw = "password";
    $dbh = new PDO ("dblib:host=$hostname:$port;dbname=$dbname","$username","$pw");
  } catch (PDOException $e) {
    echo "Failed to get DB handle: " . $e->getMessage() . "\n";
    exit;
  }
  $stmt = $dbh->prepare("select name from master..sysdatabases where name = db_name()");
  $stmt->execute();
  while ($row = $stmt->fetch()) {
    print_r($row);
  }
  unset($dbh); unset($stmt);
person Sujendra Kumar    schedule 03.11.2015
comment
Это никоим образом не относится к вопросу. - person Ben Jaguar Marshall; 06.01.2016