Статьи

Хранимые процедуры на PHP и Microsoft SQL Server

Хотя это не столь распространенная комбинация, как PHP и MySQL, PHP и Microsoft SQL Server могут быть мощной командой. Вы можете легко и эффективно запрашивать базы данных SQL Server, используя уровень абстракции базы данных PEAR, так же как и базу данных MySQL. Но как только вы начинаете пытаться использовать одно из основных преимуществ SQL Server над MySQL, а именно хранимые процедуры, быстро становятся очевидными некоторые проблемы:

Во-первых, ваш PHP-код часто почти такой же беспорядочный, как если бы вы динамически создавали операторы SQL для выполнения. Возьмите следующее определение хранимой процедуры:

GetCustomerList @StoreId int, 
@CustomerType varchar(50)

и рассмотрим код PHP, необходимый для построения оператора SQL, который будет выполнять эту процедуру из некоторой отправки страницы:

 $sql = "EXEC GetCustomerList @StoreId="; 
$sql .= intval($_GET['StoreId']);
$sql .= ', @CustomerType=';
if ($_GET['CustomerType'] == '') {
 $sql .= 'NULL';
}
else {
 $sql .= "'" . $_GET['CustomerType'] . "'" ;
}

// Assume you have an open PEAR database connection ($pearDB)
$arrResults = $pearDB->getAll($sql);

Не совсем самый читаемый или эстетически приятный кусок кода, не так ли?

Во-вторых, что делать, когда вы хотите сделать что-то более сложное, чем вызвать хранимую процедуру, которая просто запрашивает список результатов? Скажем, например, что вы хотите получить возвращаемые значения или использовать выходные параметры в ваших хранимых процедурах? Там нет ничего встроенного непосредственно в библиотеку базы данных PEAR, что позволит это сделать.

Наконец, и самое главное, подумайте о безопасности. Приведенный выше код, который создает строку SQL, необходимую для вызова процедуры GetCustomerList Поскольку значение $_GET['CustomerType'] Большинство из нас слишком часто читали об атаках с использованием SQL-инъекций, чтобы воспринимать их как должное (если нет, я настоятельно рекомендую вам ознакомиться с ними сейчас).

К счастью, в PHP встроены некоторые функции, которые могут помочь свести к минимуму вероятность таких атак — например, «волшебные кавычки» и связанная с ними функция «полоски». Эта функциональность PHP может использоваться для «автоматического» экранирования одинарных кавычек во всех строках, вводимых через значения GETPOST Однако, если вы совсем не похожи на меня, вам может показаться, что работать с магическими кавычками немного неудобно через некоторое время. Кроме того, я лично считаю, что чем меньше глобальных параметров, от которых я зависит, тем лучше — я слишком много раз переносил свой код на новые машины, чтобы зависеть от того, чтобы идентичные конфигурации серверов были чем-то иным, кроме исключения из правила.

Enter: класс SqlCommand

Класс SqlCommand Основное использование довольно просто, содержит только 6 общедоступных открытых методов (необязательные параметры указаны в квадратных скобках):

 SqlCommand([$sCommandText], [$bGetReturnValue])

Реализация класса, обычно используемая для определения имени хранимой процедуры.

 addParam($sParamName, [$oValue], [$sType], [$iLength], [$bForOutput])

Настройте параметр, который должен быть передан в хранимую процедуру. Показанная здесь опция $ sType является точным именем SQL Server типа переменной. В настоящее время поддерживаются следующие значения: bit, int, smallint, tinyint, real, float, money, text, char, varchar, datetime и smalldatetime.

 execute($oDB)

Выполнить без получения набора результатов (например, для вставки / обновления / удаления).

 getAll($oDB, [$mode])

Выполните и получите набор результатов (например, для операторов выбора).

 getReturnValue()

Получить возвращаемое значение хранимой процедуры.

 getOutputValue($sParamName)

Получить значение любого выходного параметра, определенного в хранимой процедуре.

Чтобы фактически использовать класс SqlCommandSqlCommand Затем вы можете выполнить вашу хранимую процедуру с возможностью возврата набора результатов или нет ( getAll()execute() Попутно объект SqlCommand

Например, для вызова определенной хранимой процедуры, определенной выше, вы должны использовать следующие строки кода:

 $oQuery = new SqlCommand('GetCustomerList');  
$oQuery->addParam('StoreId', $_GET['StoreId'], 'int');  
$oQuery->addParam('CustomerType', $_GET['CustomerType'], 'varchar', 50);  
 
// Assume you have an open PEAR database connection ($pearDB)  
$arrResults = $oQuery->getAll($pearDB);

Это кажется немного более читабельным, чем динамическое построение строки SQL для самостоятельного вызова этой процедуры, не так ли? И так как вы определяете каждый параметр для хранимой процедуры с фактическим типом поля базы данных, класс SqlCommand Например:

  • Значения intintval()
  • значения datetime
  • Значения varchar
Как насчет возвращаемых значений и выходных параметров?

Хорошо, я упоминал об этом, не так ли? Что ж, возможность получения возвращаемых значений включена по умолчанию с классом SqlCommand Итак, в нашем примере, если вы хотите получить фактическое возвращаемое значение процедуры GetCustomerList$oQuery->getReturnValue()

Выходные параметры почти так же легко получить, но при настройке объекта SqlCommand Давайте предположим, что у нас есть другая хранимая процедура, которая на самом деле использует некоторые выходные параметры, например:

 GetStoreCustomerCount @StoreId int, @CustomerCount int OUTPUT

В этом случае вы можете изменить конфигурацию класса SqlCommand

 $oQuery = new SqlCommand('GetStoreCustomerCount');  
$oQuery->addParam('StoreId', $_GET['StoreId'], 'int');  
$oQuery->addParam('CustomerCount', null, 'int');  
 
// One extra method call is required to configure a parameter for output  
$oQuery->setParamDirection('CustomerCount', true);  
 
// Assume you have an open PEAR database connection ($pearDB)  
$arrResults = $oQuery->getAll($pearDB);  
 
// Now retrieve the value of your output parameter  
$count = $oQuery->getOutputValue('CustomerCount');

Это все, что нужно сделать. Вы можете настроить любое количество выходных параметров и получить их значения (а также возвращаемое значение хранимой процедуры), а также любые результаты запроса, которые ваши хранимые процедуры получат, с помощью SELECT

Что на самом деле происходит за кулисами?

Если вы когда-нибудь выполняли хранимую процедуру непосредственно через Microsoft Query Analyzer, вы будете знать, что возвращаемые значения и выходные параметры там тоже не возвращаются автоматически — вам придется проделать небольшую дополнительную работу. Например, чтобы найти возвращаемое значение для хранимой процедуры, вам нужно написать что-то вроде этого:

 DECLARE @res int  
EXEC @res = GetCustomerList 1, 'SomeType'  
SELECT @res

Результат запроса для SELECT @res Получение значений выходных параметров выглядит примерно так:

 DECLARE @out_value int  
EXEC GetStoreCustomerCount 1, @out_value OUTPUT  
SELECT @out_value

Каждое возвращаемое значение или выходной параметр, который вы хотите отслеживать, должны сначала быть соответствующим образом объявлены (правильного типа данных), а затем включены в ваш фактический вызов хранимой процедуры. Сами значения могут быть возвращены с помощью SELECT Класс SqlCommand

Вывод

Хранимые процедуры — это мощный инструмент, который следует широко использовать при разработке программного обеспечения, взаимодействующего с SQL Server. Хотя вы можете использовать их непосредственно в PHP — подобно динамически создаваемым операторам запросов — ваш код может выиграть от использования более структурированного подхода. Класс SqlCommand

Не забудьте скачать код из этой статьи здесь .