В очередной раз связавшись с взаимодействием Microsoft SQL Server и PHP, в том числе через Yii 2, наступил на пару граблей о которых хотел бы рассказать.
Установка кодировки UTF-8
Подключаясь к MS-SQL серверу напрямую через PDO невозможно поставить кодировку отличную от CP1251, а чтобы поставить UTF-8 лучше использовать прослойку FreeTDS, которая ставится на сервер и прозрачно проксирует все запросы на удаленный сервер. Стандартная установка в Debian/Ubuntu через apt-get
:
apt-get install php5-sybase freetds-bin freetds-dev
Когда все установлено необходимо добавить в конфигурацию FreeTDS новую секцию с параметрами MS-SQL сервера:
[mssqlserver]
; Если servername составной (10.10.0.1/production),
; то необходимо разбить на host и instance
; и не указывать port
host = 10.10.0.1
instance = production
client charset = UTF-8
tds version = 7.0
text size = 20971520
А в Yii 2 приложении строку подключения необходимо модифицировать, заменив адрес сервера на название секции из конфига FreeTDS. Например стандартный файл /config/db.php
может иметь вид:
<?php
return [
'class' => 'yii\db\Connection',
'dsn' => 'dblib:host=mssqlserver;dbname=my_database',
'username' => 'sa',
'password' => 'superpass',
'charset' => 'utf8',
];
Хранимые процедуры
С хранимыми процедурами MS-SQL не все так однозначно, и если они возвращают курсор, то в этом случае нет проблем и можно вызывать так:
$command = Yii::$app->db->createCommand('EXEC GetOrderInfo @guid=:orderguid');
$command->bindValue(':orderguid', '43b9f14e-4953-416a-a83e-6bb9e8cd0493');
$result = $command->queryAll();
Если же процедура (в примере ниже Proc2
) возвращает int
, то описанный выше метод не сработает и необходимо выкручиваться описывая курсор самостоятельно, используя такую конструкцию:
$command = Yii::$app->db->createCommand("EXEC ('
DECLARE @result int;
EXEC @result = Proc2;
SELECT @result;
')");
$result = $command->queryScalar();
И наконец небольшой SQL запрос для тех хочет получить полный текст процедуры, а также получить список и тип входящих параметров, которые администратры MS-SQL серверов так не любят описывать в документации:
SELECT OBJECT_DEFINITION (OBJECT_ID(N'Proc2'))