我曾经使用标准的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
您期望的.
感谢一些答案,我意识到问题可能出在MDB2 API中,而不是PHP或MYSQL命令本身.果然,我在MDB2 FAQ中找到了这个:
为什么空字符串在数据库中最终为NULL?为什么我的NOT NULL文本字段中不允许使用NULL,而默认值为""?
问题是对于某些RDBMS(最值得注意的是Oracle),空字符串为NULL.因此,MDB2提供了一个可移植性选项,以在所有RDBMS上强制执行相同的行为.
由于默认情况下启用了所有可移植性选项,因此如果您不希望出现此行为,则必须禁用该功能:$ mdb2-> setOption('portability',MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL);
感谢所有提供深思熟虑答案的人.
这听起来像是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解决方案(虽然比您当前使用的解决方案略好)可能是为空字符串定义用户变量 -
SET @EMPTY_STRING = ""; UPDATE tbl SET row=@EMPTY_STRING;
最后,如果您需要在INSERT语句中使用空字符串但发现自己无法使用,则MySQL中字符串类型的默认值为空字符串.因此,您可以简单地省略INSERT语句中的列,它将自动设置为空字符串(前提是该列具有NOT NULL约束).