4

スキップするパラメータとして :start を追加すると、次のエラーが発生します。SKIP/NEXT 値をハードコーディングし、:customerID をそのままにしておくと、SQL クエリが機能することがわかっています。:start 句を削除してそのままにしておくと、SKIP 1 FIRST 5 ... WHERE t1.customer_num = :customerID ...問題なく動作します。エラーが発生している理由がわかりません。

エラー

exception 'PDOException' with message 'SQLSTATE[HY004]: Invalid SQL data type: -11064 [Informix][Informix ODBC Driver]SQL data type out of range

私が試したもの:

  1. BindValue の代わりに BindParam を使用して、参照によってパラメーターをバインドします。
  2. PDO_STR を使用して :start を文字列としてバインドしようとします。失敗。
  3. :start の値を SQL クエリ自体にハード コーディングします。これは機能します。
  4. 使用$sql->bindValue(':start', (int) 1, PDO:PARAM_INT);— ダメ。
  5. 最初にPHP変数に代入して4番を試しても同じ結果です。

助言がありますか?PDOコネクタを使用してInformix 11でPHP 5.3.(最近のもの)を使用しています。繰り返しますが、customerID のみでは機能しますが、:start では機能せず、上記のエラーが返されます。

$sql = null;
$sql= $conn->prepare('SELECT SKIP :start FIRST 5 TRIM(loc_esi_id) FROM customer       t1,customer_ts_data t2 WHERE t1.customer_num = :customerID AND t1.customer_num = t2.customer_num');

//Bind values to parameters(by value)
$sql->bindValue(':start',   $start ,PDO::PARAM_INT);
$sql->bindValue(':customerID', $customerID, PDO::PARAM_INT);

//$sql->bindParam(':count',$count,PDO::PARAM_INT);
$results = null;
try{
$sql->execute();
$results = $sql->fetchAll();
} catch (PDOException $e) {
//Error Handling, etc.
4

1 に答える 1

2

一般に、:startプレースホルダーの表記は、標準の SQL 構文でも (ネイティブの) Informix 構文でもありません。?したがって、プレースホルダーにa を使用する必要があります。

$sql= $conn->prepare('SELECT SKIP ? FIRST 5 TRIM(loc_esi_id)
                        FROM customer t1
                        JOIN customer_ts_data t2 ON t1.customer_num = t2.customer_num
                       WHERE t1.customer_num = ? AND ');

(そして、PHP ですべてを 1 行にまとめる必要がある場合は、読みやすさのために正確さを犠牲にして申し訳ありません)。

現在、PDO システムが:start表記を?自動的に変換する可能性があります。その場合、別の問題が発生します。しかし、:name表記法が機能することを確信していない限り、... 確信が持てない理由の 1 つは、bindValue()呼び出しが必要とする可能性が高い番号ではなく、名前を必要としているように見えること?です。あなたのコードエラーはbindValue()呼び出しをチェックしましたか?

この ESQL/C コードは機能し、期待どおりの出力が生成されます。

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
    $ char *dbase = "stores";
    $ int num_skip = 3;
    $ int num_fetch = 5;
    if (argc > 2)
    {
    fprintf(stderr, "Usage: %s [dbase]\n", argv[0]);
    exit(1);
    }
    if (argc == 2)
    dbase = argv[1];

    exec sql whenever error stop;
    exec sql connect to :dbase;

    exec sql prepare p from "select skip ? first ? tabid, tabname from informix.systables";
    exec sql declare c cursor for p;

    exec sql open c using :num_skip, :num_fetch;
    while (sqlca.sqlcode == 0)
    {
    $ int4 tabid;
    $ varchar tabname[129];
    exec sql fetch c into :tabid, :tabname;
    if (sqlca.sqlcode != 0)
        break;
    printf("%d: %s\n", tabid, tabname);
    }
    exec sql close c;

    exec sql free c;
    exec sql free p;
    exec sql disconnect all;
    return 0;
}

出力

4: systabauth
5: syscolauth
6: sysviews
7: sysusers
8: sysdepend

これは、プレースホルダー表記が正しく使用されている場合、SKIP および FIRST のパラメーターを使用できることを示しています。

これを PDO で動作させる方法が見つからない場合は、バグが発生している可能性があります。環境変数を同様の値に設定してコードを実行できる場合はSQLIDEBUG=2:/tmp/your_sub_dir/check、サーバーに送信された内容の記録 (接続設定は別として) などの名前のファイルを見つける必要があります/tmp/your_sub_dir/check_21484_0_aedc1e0。数字のパターンは少し変わります。その後、ファイルに対してプログラムを実行し、sqliprintPDO がサーバーに送信している内容を確認できます。これは、PDO または Informix にバグがあるかどうかを判断する非常に迅速な方法です。

たとえば、私が得た出力の一部は次のsqliprintとおりです。

C->S (20)               Time: 2012-05-29 17:55:08.65225
    SQ_CONNECT
         "stores" [6]
         "stores" [6]

C->S (72)               Time: 2012-05-29 17:55:08.65239
    SQ_PREPARE
        # values: 2
        CMD.....: "select skip ? first ? tabid, tabname from informix.systables" [60]
    SQ_NDESCRIBE
    SQ_WANTDONE
    SQ_EOT

送信された SQL ステートメントを非常に明確に確認できます。プレースホルダーが表示されない場合?は、上流に問題があります。Informix の PDO ドライバが適切に機能していないか、誤用されています。プレースホルダーが表示されている場合は?、別の問題が発生する可能性がありますが、それが問題である場合は驚くでしょう.

SQLIDEBUG メカニズムの唯一の注意点は、データベースに接続しているプロセスの環境に設定された環境変数を取得する必要があることです。スタンドアロンの ESQL/C プログラムの場合、それは些細なことです。Web サーバーと PHP を使用している場合は、ややこしいかもしれませんが、実行できます。

于 2012-05-30T01:00:04.723 に答える