15

私は、PHPからMySQLを実行するために、標準のmysql_connect()、mysql_query()などのステートメントを使用していました。最近、私は素晴らしいMDB2クラスの使用に切り替えています。それに加えて、プリペアドステートメントを使用しているので、入力やSQLインジェクション攻撃を逃れることを心配する必要はありません。

しかし、私が直面している問題が1つあります。null以外として指定されている(つまり、NULL値を許可しない)VARCHAR列がいくつかあるテーブルがあります。古いMySQLPHPコマンドを使用すると、次のようなことが問題なく実行できます。

INSERT INTO mytable SET somevarchar = '';

ただし、次のようなクエリがある場合:

INSERT INTO mytable SET somevarchar = ?;

そして、PHPでは次のようになります。

$value = "";
$prepared = $db->prepare($query, array('text'));
$result = $prepared->execute($value);

null value violates not-null constraintこれにより、エラー「 」がスローされます

一時的な回避策として、$value空かどうかを確認し、 " "(単一のスペース)に変更しますが、これは恐ろしいハックであり、他の問題を引き起こす可能性があります。

代わりにNULLを挿入しようとせずに、プリペアドステートメントで空の文字列を挿入するにはどうすればよいですか?

編集:プロジェクトが大きすぎてコードベース全体を調べ、空の文字列 ""を使用しているすべての場所を見つけて、代わりにNULLを使用するように変更します。私が知る必要があるのは、標準のMySQLクエリが「」とNULLを2つの別個のものとして扱うのに(私が正しいと思うように)、プリペアドステートメントが「」をNULLに変換する理由です。

「」とNULLは同じものではないことに注意してください。たとえば、期待どおりの代わりにSELECT NULL = "";戻ります。NULL1

4

7 に答える 7

18

いくつかの回答のおかげで、PHP や MYSQL コマンド自体ではなく、MDB2 API に問題がある可能性があることに気付きました。案の定、MDB2 FAQ でこれを見つけました。

  • 空の文字列がデータベースで NULL になるのはなぜですか? デフォルト値が "" であるにもかかわらず、NOT NULL テキスト フィールドで許可されていない NULL を取得するのはなぜですか?
    • 問題は、一部の RDBMS (特に Oracle) では空の文字列が NULL になることです。したがって、MDB2 は、すべての RDBMS で同じ動作を強制する移植性オプションを提供します。
    • すべての移植性オプションはデフォルトで有効になっているため、この動作を望まない場合は、この機能を無効にする必要があります。

思慮深い回答を提供してくれたすべての人に感謝します。

于 2008-11-05T20:33:36.193 に答える
14

これは、PHPのダックタイピングセマンティクスをいじくり回すMDB2APIの問題のように聞こえます。PHPの空の文字列はNULLと同等であるため、MDB2はおそらくそれをそのように誤って扱っています。理想的な解決策は、API内で回避策を見つけることですが、私はそれについてあまり詳しくありません。

ただし、考慮すべきことの1つは、SQLの空の文字列はNULL値ではないということです。'NOTNULL'と宣言された行にそれらを挿入できます。

mysql> CREATE TABLE tbl( row CHAR(128) NOT NULL );
Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO tbl VALUES( 'not empty' ), ( '' );
Query OK, 2 rows affected (0.02 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT row, row IS NULL FROM tbl;
+-----------+-------------+
| row       | row IS NULL |
+-----------+-------------+
| not empty |           0 | 
|           |           0 | 
+-----------+-------------+
2 rows in set (0.00 sec)

mysql> INSERT INTO tbl VALUES( NULL );
ERROR 1048 (23000): Column 'row' cannot be null

MDB2 APIで回避策を見つける(または実装する)ことができない場合、1つのハック的な解決策(現在使用しているものよりもわずかに優れていますが)は、空の文字列のユーザー変数を定義することです-

SET @EMPTY_STRING = "";
UPDATE tbl SET row=@EMPTY_STRING;

最後に、INSERTステートメントで空の文字列を使用する必要があるが、使用できない場合、MySQLの文字列型のデフォルト値は空の文字列です。したがって、INSERTステートメントから列を省略するだけで、自動的に空の文字列に設定されます(列にNOT NULL制約がある場合)。

于 2008-11-05T20:26:58.123 に答える
1

0 と空の文字列は変数ですが、NULL はデータの不在です。そして、私を信じてください、クエリを書くのはずっと簡単です

SELECT * from table where mything IS NULL空の文字列をクエリしようとするよりも:/

于 2011-05-31T21:00:46.203 に答える
1

解決策を見つけました!

移植性オプション MDB2_PORTABILITY_EMPTY_TO_NULL がデフォルトでオンになっているため、MDB2 は空の文字列を NULL に変換します (空の文字列を null と見なす Oracle に感謝します)。

データベースに接続するときは、このオプションをオフにします。

$options = array(
    'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL
);
$res= & MDB2::connect("mysql://user:password@server/dbase", $options);
于 2010-02-19T07:05:11.580 に答える
1

この質問はほとんど答えられ、引退したことを認識していますが、同様の状況への答えを探しているときに見つけたので、リングに帽子を投げずにはいられません.

NULL/"" 列が何に関連しているのかを知らなければ、空の文字列の真の意味を知ることができません。空の文字列はそれ自体に何か意味がありますか (たとえば、判事に自分の名前を単純に何も変更させないよう説得した場合、運転免許証に自分の名前が NULL として表示されたら、本当に腹が立ちます。私の名前は !

ただし、空の文字列 (または空白、または何もない (NULL など) だけでなく、何かである何もない) は、単純に「NOT NULL」または「Nothing, but still not Null」を意味する場合もあります。別の方向に進んで、値 NULL が存在しないことで、値が Null よりも小さいものになることを示唆することもできます。少なくとも、Null には声に出して言える名前があるからです。

私の要点は、空の文字列が何らかのデータ (名前、または電話番号の数字の間に挿入することを好むものなど) の直接的な表現である場合、あなたの選択肢は、疲れるまで議論することです。空の文字列を正当に使用するため、または NULL ではない空の文字列を表すものを使用するため (ASCII 制御文字または同等の Unicode、ある種の正規表現値、さらに悪いことに、任意だが完全に未使用のトークンなど)など: ◘</p>

空のセルが本当に NOT NULL を意味する場合は、それを表現する他の方法を考えることができます。愚かで明白な方法の 1 つは、"Not NULL" というフレーズです。しかし、NULL は「このグループの一部ではない」などを意味し、空の文字列は「この男はクールだ、ギャングのタトゥーをまだ入れていない」などを意味するという予感があります。その場合、「デフォルト」、「ルーキー」、「保留中」など、この状況の用語/名前/アイデアを思いつきます。

ここで、偶然にも NULL に値しないものを実際に空の文字列で表現したい場合は、「-1」、「SUPERNULL」、「UGLIES」など、より重要な記号を考え出してください。

インドのカースト制度では、最下層のカーストはシュードラ(農民と労働者)です。このカーストの下には、「アンタッチャブル」というダリットがいます。彼らを最低カーストに設定すると、システム全体の汚染と見なされるため、彼らは下層カーストとは見なされません。

ですから、空の文字列が NULL よりも悪いかもしれないと考えているからといって、私が狂っているとは思わないでください。

次回まで。

于 2009-06-19T01:32:42.957 に答える
0

空の引用符のセットではあり""ませんか?

于 2008-11-05T20:12:08.310 に答える
-1

よくわかりません。(タグとスタイルから)mysqli OOを使用しているように見えますが、構文はphp.netのマニュアルとは異なり、代わりにこれを行うように指示されています。

$query = "INSERT INTO mytable SET somevarchar = ?";
$value = "";
$prepared = $db->prepare($query);
$prepared->bind_param("s", $value);
$result = $prepared->execute();
于 2008-11-05T20:25:41.137 に答える