Małe a cieszy: sp_executesql

Aplikacja, nad którą obecnie pracuję, dostaje od użytkowników zapytania SQL, które wykonuje na wielu bazach danych MS SQL. Zapytania mogą być najróżniejszego typu, od prostych SELECTów po złożone skrypty w Transact SQL-u. Wykonywanie takich złożonych zapytań przez PDO i odczytywanie wyników mogłoby być kłoptliwe, analiza zapytań i rozbijanie ich na pojedyncze kwerendy jeszcze bardziej. Bólu głowy mozna sobie oszczędzić w bardzo prosty sposób – z pomoca przychodzi sp_executesql. Nasze złożone zapytania możemy wykonać poprzez tę funkcję przerzucając rozwiązanie wspomnianych problemów na bazę danych.

$statement = $dbh->prepare("EXEC sp_executesql N" . $dbh->quote($query));
$statement->execute($params);
$rows = $statement->fetchAll();

PDO dblib a parametr charset

Dzisiaj zmagałem się z kodowaniem znaków w bazach danych Microsoft SQL. Sytuacja wyglądała następująco: PHP na Linuksie, aplikacja w UTF-8, na innym serwerze kilkadziesiąt baz danych Microsoft SQL, a żeby było zabawniej bazy używały kilku kodowań znaków.

Do baz łączyłem się przez PDO ze sterownikiem dblib. Pomysł z konwertowaniem kodowania w aplikacji szybko odrzuciłem, zamiast tego zainteresowałem się parametrem charset. W dokumentacji nie jest jasno opisany, ale łatwo można się domyślić, że informuje sterownik o oczekiwanym kodowaniu.

$dbh = new \PDO('dblib:charset=UTF-8;host=10.12.34.56;dbname=nazwa_bazy', $dbUser, $dbPassword);

Niestety to nie działało. Rozwiązaniem okazała się zmiana konfiguracji FreeTDS w pliku /etc/freetds/freetds.conf.

tds version = 7.0

Ta zmiana wymusza połaczenia z użyciem wersji 7.0 protokołu. Wedle dokumentacji dopiero w tej wersji działa parametr client charset.