0

私は、物流プロセスを促進するために使用するデータを収集して保存するための小さなイントラネット Web サイトを作成しました。現在、検索機能を追加中です。その基準に一致するレコードが見つかった場合、ユーザーはそのデータの一部をすばやく選択して、新しい配送リクエストにデータを事前入力できます (たとえば、ユーザーは「受信者名入力テキストボックスに Mar'、住所入力テキストボックスに '109' を入力すると、クエリは {"Mary Smith", "1090 South Central St"} と {"Mark Swanson", "109 E. 31st" の 2 つのレコードを返します。セント」})。

現時点では、検索基準を入力して送信するときに、単一の基準 (受信者名など) が入力された場合にのみ、PHP のクエリから返されるデータは 100% 正確です。PHP で 2 つの異なる検索基準を使用しようとすると、レコードの結果が Oracle PL/SQL Developer で同じクエリを実行したときの結果と一致しません。3 つの異なる検索基準が使用された場合、PHP で実行されたクエリは 0 レコードを返します。前述の 3 つのシナリオすべてで、クエリは Oracle PL/SQL Developer でエラーなく実行されます。

次のコードは、私の PHP 検索機能からのものです。この関数への入力データは、フィールド名の連想配列と、ユーザーがそのフィールドに入力した検索基準データです。

     public function Search()
     {
        if($this->dbcon)
        {
            $query = "SELECT * FROM ship_request ";
            $postCount = count($this->post_data);
            $counter = 0;

            if ($postCount > 0) 
            {
                $query .= "WHERE ";
            }

            foreach ($this->post_data as $k => $v)
            {
                $counter++;
                if (strlen($v) > 0)
                {
                    if ($k == 'SR_DATE') 
                    {
                        $query .= $k . " = :" . $k . " AND ";
                    } else {
                        $query .= "upper(" . $k . ") like upper(:" . $k . ") AND ";
                    }
                }
            } 

            if (substr($query,-4) == "AND ")
            {
                $query = substr($query, 0, strlen($query) - 4);
            }

            $stid = oci_parse($this->ifsdb, $query);

             foreach ($this->post_data as $k => $v)
            {
                if (strlen($v) > 0)
                {
                    if ($k == 'SR_DATE') 
                    {
                        $this->post_data[$k] = date("d-M-y", strtotime($this->post_data[$k]));
                        $placeHolder = $this->post_data[$k];
                    } else {
                        $placeHolder = '%' . $this->post_data[$k] . '%';

                    }
                    oci_bind_by_name($stid, $k, $placeHolder);
                }
            }
            oci_execute($stid);
            $nrows = oci_fetch_all($stid, $recordsFound);
            $recordsFound = json_encode($recordsFound);
            oci_free_statement($stid);
            echo $recordsFound;
        } else {
            die("Could not connect to database!");
        }
    }
}

$query で var_dump を実行して、複数の検索基準値を入力したときにクエリが実際にどのように表示されるかを確認しました。これは私が見るものの例です:

select * from HOL_SHIP_REQUEST where upper(sr_shipper_name) like upper(:sr_shipper_name) and upper(sr_recipient_name) like upper(:sr_recipient_name) and sr_recipient_phone like upper(:sr_recipient_phone)

荷送人名に「a」、受取人名に「m」、電話番号に「2」を入力すると、そのクエリは 0 レコードを返します。

ただし、このクエリを Oracle PL/SQL Developer で実行すると、27 件のレコードが返されます。

select * from HOL_SHIP_REQUEST where upper(sr_shipper_name) like upper('%a%') and upper(sr_recipient_name) like upper('%m%') and sr_recipient_phone like upper('%2%')

PHP でパラメーターをバインドしようとしている方法に何か問題がありますか? like複数のステートメントを使用するときに何か別のことをしなければなりませんか?

4

1 に答える 1

3

%作成したクエリ文字列のワイルドカード文字を忘れました。DB インターフェース ライブラリは、作成中のクエリを解析せず、句を探しませんLIKE。実行しようとしている一致の種類を推測するのは彼らの仕事ではありません。例えば、あなたはやっていますか

WHERE a LIKE 'b'
WHERE a LIKE 'b%'
WHERE a LIKE '%b'
WHERE a LIKE '%b%'

適切なワイルドカードを提供するのはあなた次第です。プレースホルダーを使用しているため、自分で行う必要があります。

WHERE UPPER(sr_shipper_name) LIKE CONCAT('%', :sr_shipper_name, '%')

あなたがそれを次のようにするとしたら:

$shipper = '%foo%';

WHERE  ... LIKE :shipper

あなたは次のようになります:

WHERE ... LIKE '\%foo\%'

また、プレースホルダー システムは、提供されたテキストを解析せず、本当にワイルドカードを使用しようとしているのか、それともリテラル%char を渡しているだけなのかを判断しようとします。そのため、CONCATハックを使用して適切なワイルドカード構造を構築する必要があります。

于 2013-08-19T19:09:24.193 に答える