web-dev-qa-db-ja.com

準備したSELECTステートメントで「N」を使用するには

PdoとSQL ServerのODBC Driver 13を使用してSQL Server 2008データベースに接続しています。

データベースで中国語の文字を検索する次のクエリを実行しようとしています。

SELECT TOP (10) ... WHERE (sItemName LIKE N:term1)

        $text = "%简况%";
            $query = $this->DBH->prepare($sql);
            $query->bindParam(':term1', $text, PDO::PARAM_STR );
        $query->execute();

このクエリはランダムな文字で結果を返すため、文字エンコーディングが何らかの形で正しくないようです。

Heidiを使用してDBで直接このクエリを実行することで、同じ結果を返すことができました。

SELECT TOP (10) ... WHERE (sItemName LIKE '%简况%')

文字列が正しい結果を返す前に「N」を追加して、クエリを次のように変更します。

SELECT TOP (10) ... WHERE (sItemName LIKE N'%简况%')

しかし、以下に示すように準備したステートメントで同じことを実行しようとすると、構文エラーが発生します。

SELECT TOP (10) ... WHERE (CI.sItemName LIKE N:term1)

        $text = "%简况%";
            $query = $this->DBH->prepare($sql);
            $query->bindParam(':term1', $text, PDO::PARAM_STR );
        $query->execute();

ここにエラーがあります:

構文エラーまたはアクセス違反:102 [Microsoft] [ODBC Driver 13 for SQL Server] [SQL Server]「N:」付近の構文が正しくありません。

したがって、私の質問は、エラーが発生することなく準備されたステートメントで「N」をどのように使用するかです。私は取引でDBOではないので、何かを省いても申し訳ありません。

これは期待される結果を返します:

$seach_term = (string)'简况';
$text = '%'.$seach_term.'%';
$query = $this->DBH->prepare("SELECT * FROM Articles WHERE sHeadline LIKE :term");
$query->bindParam(':term', $text, PDO::PARAM_STR);   

ただし、PARAM_STR_NATL定数を使用しても何も返されません。

$query->bindParam(':term', $text, PDO::PARAM_STR_NATL);
2
Los Porcos

(比較的新しい)PDO_PARAM_STR_NATL定数を使用してそれらをバインドする必要があります。この定数は、PHP 7.2以降で使用できます。希望するNプレフィックスが追加されます。

$query->bindParam(':term1', $text, PDO::PDO_PARAM_STR_NATL);

興味がある場合は、いくつかの履歴をここで見つけることができます:
https://bugs.php.net/bug.php?id=60818

そこでリンクされているGithubコミットは、Nがどのように追加されるかを示しています(行178〜184)。
https://github.com/php/php-src/commit/4afce8ec8c6660ebd9f9eb174d2614361d1c6129

2
Peter B

Nはリテラルにのみ必要です。準備済みステートメントでは、型付きパラメーターをパラメータープレースホルダーにバインドします。パラメータはNVarcharとして入力され、Unicode値に設定されます。