4

CakePHPの複雑な検索'OR'演算子がnullで正しく機能していません...

$conditions = array(
    'Person.id' => array(2, 4, 1, 23, 45, 11),
    'OR' => array(
    array(
        array('NOT' => array('Person.image' => null)),
        array('NOT' => array('Person.image' => '')),
    ),
    array(
        array('NOT' => array('Person.photos' => null)),
        array('NOT' => array('Person.photos' => '')),
    )
    )
);

以下のような対応するケーキSQLダンプ出力クエリ

SELECT `Person`.`id`, `Person`.`created`, `Person`.`modified` 
FROM `people` AS `Person` WHERE `Person`.`id` IN (2, 4, 1, 23, 45, 11)  AND 
((((NOT (`Person`.`image` IS NULL)) AND (NOT (`Person`.`image` = NULL))))   OR 
(((NOT (`Person`.`photos` IS NULL)) AND (NOT (`Person`.`photos` = ''))))) 
ORDER BY FIELD(`Person`.`id`, 2, 4, 1, 23, 45, 11) ASC LIMIT 3

ケーキ条件配列では、Person.imageis not nullorを指定しまし''たが、対応するcakesql出力は。(NOT (Person.image IS NULL)) AND (NOT (Person.image = NULL))のようになり(NOT (Person.image IS NULL)) AND (NOT (Person.image = ''))ます。

ここでPerson.imageは、両方がNULL自体( ISNULLおよび=NULL)と比較されます。ここで、Person.image = NULLは、 Person.image=''のような空の文字列と比較します。

こちら'Person.image'がタイプですが'INT'、現段階からタイプを変更することは困難です。'Person.photos''VARCHAR'

どうすれば修正できますか?

4

4 に答える 4

3

条件を定義するために連想配列を使用する必要はありません。次のように定義できます。

$conditions = array(
    'Person.id' => array(2, 4, 1, 23, 45, 11),
    'OR' => array(
    array(
        array('NOT' => array('Person.image' => null)),
        array('NOT' => array('Person.image = "" ')),
    ),
    array(
        array('NOT' => array('Person.photos' => null)),
        array('NOT' => array('Person.photos = "" ')),
    )
    )
);
于 2012-06-12T08:16:47.370 に答える
1

Cakeのnull比較は、データベースのフィールドタイプに依存しているようです。フィールドが整数型の場合、Cakeは''をNullとして再定義します。Varcharsは再定義されません。

MySQLに移動して、Person.imageタイプをvarcharに変更できますか?

その場合は、変更を登録するために、Cakeのapp / tmp / cache/modelsのキャッシュをクリアすることを忘れないでください。

更新:スキーマタイプを手動で変更すると、cakeはフィールドタイプを定義どおりに処理するように強制されます。したがって、クエリの前に次のようなものが機能します。

$this->Person->_schema['image']['type']='string';
于 2012-06-11T21:04:20.883 に答える
1

'Person.image <>' => null厳密には有効なSQLではないため(少なくともMySQLでは)、解釈に問題がある可能性があります。

MySQLマニュアルから:

=、<、<>などの算術比較演算子を使用してNULLをテストすることはできません。

否定されたnull比較に置き換えてみることができます。

array('NOT' => array('Person.image' => null))

それを除けば、最後の2つのOR演算子は、それぞれに1つのステートメントしかないため、何もしません。あなたのアレイはあなたがそれをメンテするものを入れ子にしていますか?改行とインデントを追加すると、コードは次のようになります。

$conditions = array(
    'Person.id' => array(2, 4, 1, 23, 45, 11),
    'OR' => array(
        array(
            'OR' => array(
                'Person.image <>' => null
            ),
            array(
                'Person.image <>' => ''
            )
        ),
        array(
            'OR' => array(
                'Person.photos <>' => ''
            ),
            array(
                'Person.photos <>' => null
            )
        )
    )
);

...奇妙に見えます。

完全な変更は次のようになります。

$conditions = array(
    'Person.id' => array(2, 4, 1, 23, 45, 11),
    'OR' => array(
        array(
            array('NOT' => array('Person.image' => null)),
            array('NOT' => array('Person.image' => '')),
        ),
        array(
            array('NOT' => array('Person.photos' => null)),
            array('NOT' => array('Person.photos' => '')),
        )
    )
);
于 2012-06-07T13:53:33.340 に答える
0

申し訳ありませんが、これらの回答は100%正しいとは言えません。回避策は提供されますが、解決策はありません。

問題はデータベースの列タイプです。

Person.imageINTあり、タイプPerson.photosですVARCHAR

ええと、''(空の文字列)は整数の有効な値ではありません。NULL列に値を許可していると思いますPerson.imageので、cakeは適切に機能します。

整数フィールドに空の文字列の値があるかどうかを尋ねるのは意味がありません。整数フィールドはNULL、0、1、-1、2、-2など(符号付きの場合)のみになります。

ここで何が起こるかというと、cakeはデータ構造を認識しているため(フラグが0DESCRIBEより大きい場合のクエリに注意してくださいdebug)、ステートメントを次の有用なステートメント(NULL値のテスト)に修正しようとします。さらに、MySQLにDBのクエリを要求したとしても(または強制的にそうするように)、この条件のために(おそらく他の条件のために)効果はありません。

SELECT * FROM table WHERE my_int_column = ''は完全に正当なSQLですが、常に0の結果を返しますが、SELECT * FROM table WHERE NOT(my_int_column = '')常にすべての結果を返します。

結論:アプリが条件付きで動作する場合、=''条件なしでもまったく同じように動作します。

最後の注意:ただし、INSERT空の文字列を整数列に変換すると、MySQLによってに変換される0ため、それらを確認することをお勧めします。

于 2012-07-23T00:27:13.280 に答える