我曾经使用标准的mysql_connect(),mysql_query()等语句从PHP做MySQL的东西。最近我一直在转向使用精彩的MDB2课程。除此之外,我正在使用预处理语句,所以我不必担心逃避输入和SQL注入攻击。
但是,我遇到了一个问题。我有一个包含几个VARCHAR列的表,指定为非null(即,不允许NULL值)。使用旧的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 value violates not-null constraint
”
作为一种临时解决方法,我会检查$value
是否为空,并将其更改为" "
(单个空格),但这可能会导致其他问题。
我应该如何使用预准备语句插入空字符串,而不是尝试插入NULL?
编辑:通过我的整个代码库,找到使用空字符串“”并将其更改为使用NULL的项目,这个项目太大了。我需要知道的是为什么标准的MySQL查询将“”和NULL视为两个独立的东西(我认为是正确的),但是准备好的语句将“”转换为NULL。
请注意,“”和NULL 不是相同。例如,SELECT NULL = "";
会返回NULL
而不是1
,正如您所期望的那样。
答案 0 :(得分:17)
由于一些答案,我意识到问题可能出在MDB2 API中,而不是PHP或MYSQL命令本身。果然,我在MDB2 FAQ中找到了这个:
- 为什么空字符串在数据库中最终为NULL?为什么我得到一个NULL 不允许在NOT NULL文本字段中 虽然默认值是“”?
- 问题是对于某些RDBMS(最值得注意的是Oracle)是空的 string为NULL。因此MDB2 提供了一个可移植性选项 对所有人强制执行相同的行为 RDBMS。
- 由于默认情况下启用了所有可移植性选项,因此您将拥有 如果你没有禁用该功能 想要有这种行为: $ mdb2->的SetOption( '便携', MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL);
感谢所有提供深思熟虑答案的人。
答案 1 :(得分:12)
这听起来像是MDB2 API愚弄PHP的鸭子类型语义的问题。因为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中找到(或实施)变通方法,那么一个hackish解决方案(虽然略好于您当前使用的解决方案)可能是为空定义user variable字符串 -
SET @EMPTY_STRING = "";
UPDATE tbl SET row=@EMPTY_STRING;
最后,如果您需要在INSERT语句中使用空字符串但发现自己无法使用,则MySQL中字符串类型的默认值为空字符串。所以你可以简单地省略INSERT语句中的列,它会自动设置为空字符串(假设列有一个NOT NULL约束)。
答案 2 :(得分:2)
我意识到这个问题已得到很好的回答和退休,但我在寻找类似情况的答案时找到了它,我无法抗拒将我的帽子戴在戒指上。
在不知道NULL /“”列的相关内容的情况下,我无法知道空字符串的真正意义。空字符串本身就意味着什么(就像,如果我说服一位法官让我改变我的名字,我会真的很恼火,如果我的名字出现在我的驾驶执照上为NULL。我的名字就是!
然而,空字符串(或空白,或者是没有任何东西(如NULL)的虚无)也可能只是意味着“NOT NULL”或“Nothing,但仍然不是Null”。你甚至可以走向另一个方向,并建议缺少值NULL使它甚至比Null更少,因为至少Null有一个你可以大声说出的名字!
我的观点是,如果空字符串是某些数据的直接表示(如姓名,或者我喜欢插入电话号码中的数字之间等),那么您的选择要么是争论直到你'对于合法使用空字符串感到痛苦,或者使用表示非空字符串的东西(就像ASCII控制字符或某些unicode等价物,某种类型的正则表达式值,或者更糟糕的是,是一种任意的完全未使用的令牌,如:◘
如果空单元格实际上只是意味着NOT NULL,那么你可以想出一些表达它的方法。一个愚蠢而明显的方式是短语“Not NULL”。但我有一种预感,即NULL意味着“根本不属于这个群体”,而空字符串意味着“这个家伙很酷,他还没有得到他的帮派纹身”。在这种情况下,我会针对这种情况提出一个术语/名称/想法,例如“默认”或“新手”或“待定”。
现在,如果有一些疯狂的机会你真的希望空字符串代表那些甚至不值得为NULL的字符串,那么再次提出一个更重要的符号,例如“-1”或“SUPERNULL”或“ UGLIES”。
在印度种姓制度中,最低的种姓是Shudra:农民和劳动者。在这个种姓之下是达利特:“不可触犯”。它们不被视为较低种姓,因为将它们设置为最低种姓将被视为整个系统的污染。
所以不要因为我认为空字符串可能比NULL更糟糕而感到疯狂!
'下一次。
答案 3 :(得分:1)
我找到了解决方案!
MDB2将空字符串转换为NULL,因为默认情况下可移植性选项MDB2_PORTABILITY_EMPTY_TO_NULL处于打开状态(感谢Oracle认为空字符串为空)。
连接数据库时关闭此选项:
$options = array(
'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL
);
$res= & MDB2::connect("mysql://user:password@server/dbase", $options);
答案 4 :(得分:1)
当0和空字符串是变量时,NULL是缺少数据。相信我,将查询写入
要容易得多 SELECT * from table where mything IS NULL
而不是尝试查询空字符串:/
答案 5 :(得分:0)
不是一组空的引号""
吗?
答案 6 :(得分:-1)
我很困惑。看起来你正在使用mysqli OO(来自标签和样式),但语法与php.net上的manual不同,后者说这样做:
$query = "INSERT INTO mytable SET somevarchar = ?";
$value = "";
$prepared = $db->prepare($query);
$prepared->bind_param("s", $value);
$result = $prepared->execute();