Имеем след процедуру: Код (Text): CREATE PROCEDURE dbo.pr_TestSP AS /* тестовая ХП - 1 рез набор данных и результат */ select 10 RETURN 20 Задача: Получить средствами PHP значение, возвращаемое по RETURN (в нашем случае 20)
To Simpliest: Не понял Вас. Есть некий скрипт, который должен вызвать приведенную выше процедуру. Необходимо: а) получить результирующий набор (в нашем случае - это число 10) б) получить код возврата (в нашем случае - это число 20) Можно так: Код (Text): DECLARE @return_code INT EXEC @return_code = some_stored_procedure @param=123 SELECT @return_code В принципе, в большинстве случаев должно устроить. Но могут возникнуть траблы при использование динамического SQL во вложенных хранимых процедурах. Например, если вышеуказанный кусок кода находится в хранимой процедуре, а сама some_stored_procedure использует динамический SQL. Для работы с MS SQL в проекте использую ф-ии mssql_xxxx. Вот у меня и возник вопрос, как у новичка PHP, имеются ли средства, позволяющие получить код возврата из хранимой процедуры.
Смотрел. Но позвольте, причем здесь множественные результирующие наборы, для работы с которыми и предназначен mssql_next_result()? Еще раз повторюсь: мне надо (точнее хотелось бы) получить кроме данных еще и код возврата по RETURN без финта ушами, типа оболочки для вызова хранимой процедуры из хранимой процедуры.
Да фиг его знает! Если б знал, не спрашивал бы. Вообще говоря, у MS SQL ЛЮБАЯ процедура даже без явного указания RETURN возвращает некое значение, при успешном выполнении - по умолчанию (если разработчик явно не указал RETURN) это 0, при ошибке - это не 0. В чем легко убедиться. Вот и возникла идея заюзать пользовательские ошибки, например, пришедшие некорректные параметры или ограничение в правах роли пользователя, возвратом некоего числового значения для последующего логгирования\либо чего-нибуть еще. А так как процедура может вернуть более 1 результирующего набора данных, то не хотелось бы привязываться к возврату кода ошибки через SELECT как еще один набор данных. Вот как-то так.
Если тут работает аналогично с php_mysqli, то результат будет всегда последним в независимости от числа SELECT внутри. Так что проблемы никакой не вижу.
Не знаю, как работает php_mysqli. На возможную проблему с динамическим SQL я указал выше. Еще одна проблема может возникнуть при использовании временных таблиц. Например, при вызове вложенных хранимых процедур можно в какой-то момент получить такое сообщение: Код (Text): Server: Msg 8164, Level 16, State 1, Procedure pr_TestSP2Res, Line 20 An INSERT EXEC statement cannot be nested. Поэтому не хотелось плодить процедуры, вызывающие другие процедуры.
uri Вам так сложно проверить что возвращает Для подобного запроса? Код (Text): EXECUTE dbo.pr_TestSP ?
Нет, мне не сложно это проверить. Возвращает Array ( [0] => 10 ). Код (Text): <?php $link = mssql_connect("имя_моего_серера", "мой_логин", "мой_пароль"); mssql_select_db("имя_моей_бд", $link); $sql = 'exec dbo.pr_TestSP'; $rs = mssql_query($sql, $link); do { while ($row = mssql_fetch_row($rs)) { print_r($row); } } while (mssql_next_result($rs)); mssql_free_result($rs); mssql_close($link); ?>
Охохонюшки http://www.php.net/manual/en/function.mssql-execute.php Читаем и делаем. Мне проверять негде.
Не вкурил про mssql_bind() Не пойму, где трабла: Код (Text): ... $conn=mssql_connect($cServer, $cLogin, $cPwd); if ($conn) { mssql_select_db($cDBName, $conn); $stmt=mssql_init($cProcName, $conn); mssql_bind($stmt, "RETVAL", &$val, SQLINT2); $result=mssql_execute($stmt); $arr=mssql_fetch_row($result); print_r($arr); echo("<br />"."RETVAL = $val"."<br />"); mssql_close($conn); } else print("Нет коннекта к $cServer"); ... Возвращает в RETVAL 0 вместо 20.
Гран мерси Simpliest. Подитожу, может кому будет интересны мои изыскания. Имеем как минимум 2 варианта получения результата, возвращаемого по RETURN из процедуры. Приведу только наиболее важные фрагменты кода 1) самый простой способ - формировать как еще один результирующий набор: Код (Text): ... // код процедуры pr_TestSP приведен в топике выше $sql = 'declare @nRes int exec @nRes = dbo.pr_TestSP select @nRes as Res'; // вместо - $sql = 'exec dbo.pr_TestSP'; !! $rs = mssql_query($sql, $link); // выводим записи активного набора данных do { while ($row = mssql_fetch_row($rs)) { print_r($row); } } while (mssql_next_result($rs)); ... Здесь используется чиcтый TSQL-код 2) Используем mssql_execute() Код (Text): ... // $conn - установленный коннект с нужной нам БД, // $cProcName - имя процедуры, у нас это - dbo.pr_TestSP $stmt=mssql_init($cProcName, $conn); mssql_bind($stmt, "RETVAL", &$val, SQLINT2); $result=mssql_execute($stmt); $arr=mssql_fetch_row($result); print_r($arr); while (mssql_next_result($result)) { $arr1 = mssql_fetch_row($result); print_r($arr1); } echo("<br />"."RETVAL = $val"."<br />"); ... Здесь с помощью mssql_bind() мы в $val будем ожидать результата P.S.: имеется 1 замечание по mssql_execute. Если вышеприведенный код преобразовать к виду Код (Text): ... $result=mssql_execute($stmt, TRUE); //// остальное закомментарил echo("<br />"."RETVAL = $val"."<br />"); ... сразу же получим интересующее нас значение. P.P.S.: К слову сказать, работа с OUTPUT-параметрами происходит аналогично. С помощью mssql_bind() связываем локальные перменные с OUTPUT-параметрами процедуры, указав им тип Немного преобразованный код из хелпа по ф-ии mssq_execute(): Код (Text): ... // ------- КОД тестовой процедуры ------------------- // SET QUOTED_IDENTIFIER ON // GO // SET ANSI_NULLS ON // GO // // ALTER PROCEDURE dbo.pr_TestSProc // ( // @sval varchar(50) OUTPUT, -- 1 выходной параметр // @intval int OUTPUT, -- 2 выходной параметр // @floatval decimal(6,4) OUTPUT -- 3 выходной параметр // ) AS // /* // тестовая процедура - 2 набора данных, 3 выходных параметра и значение по RETURN // */ // if @intval is null // select '@intval is null' as answer // else // select '@intval is NOT null' as answer // // // select '1' = 1, '2' = 2, '3' = 3 // // select 'aaaa' // // set @sval='Hello ' + @sval // set @intval=@intval+1 // set @floatval=@floatval+1 // // return 10 // // GO // SET QUOTED_IDENTIFIER OFF // GO // SET ANSI_NULLS ON // GO // -------------------------- $cProcName = 'dbo.pr_TestSProc'; $conn=mssql_connect($cServer, $cLogin, $cPwd); if ($conn) { mssql_select_db($cDBName,$conn); $stmt=mssql_init($cProcName,$conn); mssql_bind($stmt,"RETVAL",&$val,SQLINT4); $ival=11; $fval=2.1416; $sval="Frank"; mssql_bind($stmt,"@sval",&$sval,SQLVARCHAR,TRUE); mssql_bind($stmt,"@intval",&$ival,SQLINT4,TRUE); mssql_bind($stmt,"@floatval",&$fval,SQLFLT8,TRUE); echo('<br />'.'Начальные значения: '.'<br />'.'$ival='.$ival.'; $fval='.$fval.'; $sval='.$sval.'; <br />'); // вернем только OUTPUT-параметры и значение по RETURN, за это отвечает второй параметр, имеющий значение TRUE $result=mssql_execute($stmt, TRUE); // в нашем случае - бесполезен, ибо наборы данных не возвращаются! // $arr=mssql_fetch_row($result); print ("После вызова процедуры: " . $arr[0] . "<br>" ); print ("RETVAL = $val ; intval = $ival ; floatval = $fval ; string = $sval"); mssql_close($conn); } else print("ooops!"); ... P.P.P.S.: Хотелось бы узнать у знатоков (в плане самообразования) как то же самое проделать через ODBC\ADO
то же самое - что? И PHP участвует в этом празднике жизни? Если да, то http://php.net/odbc Если нет, то скорее всего не подскажут. (те кто знают - заняты, а остальные тупо не знают и не способны разобраться).