質問

以前は、mysql_connect()、mysql_query()などの標準ステートメントを使用して、PHPからMySQLを実行していました。最近、素晴らしいMDB2クラスを使用するように切り替えています。それに加えて、準備されたステートメントを使用しているので、入力やSQLインジェクション攻撃を逃れる心配はありません。

しかし、私が遭遇している問題が1つあります。非ヌルとして指定された(つまり、NULL値を許可しない)いくつかのVARCHAR列を持つテーブルがあります。古いMySQL PHPコマンドを使用すると、問題なくこのようなことができます。

INSERT INTO mytable SET somevarchar = '';

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

INSERT INTO mytable SET somevarchar = ?;

そしてPHPには次のようなものがあります:

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

これはエラーをスローします" null値がnot-null制約に違反しています"

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

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

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

""とNULLは同じではありません。たとえば、 SELECT NULL ="&quot ;; は、予想どおり 1 ではなく NULL を返します。

役に立ちましたか?

解決

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

ただし、SQLの空の文字列はNULL値ではないことを考慮する必要があります。 'NOT NULL'と宣言された行にそれらをうまく挿入できます:

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制約がある場合)。

他のヒント

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

  
      
  • データベースで空の文字列がNULLになるのはなぜですか?なぜNULLを取得するのですか   NOT NULLテキストフィールドでは使用できません   デフォルト値は""ですが、      
        
    • 問題は、一部のRDBMS(最も注目すべきOracle)では空   文字列はNULLです。したがって、MDB2   移植性オプションを提供します   すべてに同じ動作を強制する   RDBMS。
    •   
    • すべての移植性オプションがデフォルトで有効になっているため、   いけない場合に機能を無効にする   この動作をしたい:   $ mdb2-> setOption( 'portability'、   MDB2_PORTABILITY_ALL ^   MDB2_PORTABILITY_EMPTY_TO_NULL);
    •   
  •   

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

この質問はほとんど答えられ、引退したことはわかっていますが、似たような状況への答えを探しているうちにそれを見つけました。リングに帽子を投げることに抵抗できません。

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

ただし、空の文字列(または空白、または何かの不足(NULLなど)ではなく、何か無意味)は、単に「NOT NULL」を意味する場合もあります。または" Nothing、but still not Null"。別の方向に進み、値NULLが存在しないことで、Nullよりも少なくなることを提案することもできます。少なくともNullには声に出せる名前があるからです!

私のポイントは、空の文字列がいくつかのデータ(名前、または電話番号の数字の間に挿入したいものなど)の直接表現である場合、オプションはあなたが主張するまで議論することです'空の文字列の合法的な使用、またはNULLでない空の文字列を表すものを使用するために痛いです(ASCII制御文字または同等のUnicodeのように、ある種の正規表現値、さらに悪いことに、任意のまだ次のような完全に未使用のトークン:◘

空のセルが実際にはNOT NULLを意味する場合、他の表現方法を考えることができます。愚かで明白な方法の1つは、「Not NULL」というフレーズです。しかし、NULLは「このグループの一部ではない」という意味です。空の文字列は「この男はかっこいいが、彼はまだギャングのタトゥーを受け取っていない」などのような意味です。その場合、「デフォルト」のようなこの状況の用語/名前/アイデアを思いつきます。または「新人」または「保留中」。

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

インドのカースト制度では、最下位のカーストはシュドラです。農民と労働者です。このカーストの下にあるのはダリット:「The Untouchables」です。最下位カーストとして設定すると、システム全体の汚染と見なされるため、下位カーストとは見なされません。

空の文字列はNULLよりも悪いかもしれないと思うので、私を夢中にしないでください!

「次回まで。

解決策を見つけました!

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

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

$options = array(
    'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL
);
$res= & MDB2::connect("mysql://user:password@server/dbase", $options);

0および空の文字列は変数ですが、NULLはデータが存在しないことを示します。信頼してください。クエリを書く方がずっと簡単です

SELECT * mything IS NULLのテーブルから空の文字列を照会しようとするより:/

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

混乱しています。 (タグとスタイルから)mysqli OOを使用しているようですが、構文はマニュアル php.netで、代わりにこれを行うように言っています:

$query = "INSERT INTO mytable SET somevarchar = ?";
$value = "";
$prepared = $db->prepare($query);
$prepared->bind_param("s", $value);
$result = $prepared->execute();
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top