MySQL 中非空列中的空字符串?
我曾经使用标准 mysql_connect()、mysql_query() 等语句从 PHP 执行 MySQL 操作。 最近我开始改用美妙的 MDB2 类。 除此之外,我还使用准备好的语句,因此我不必担心逃避输入和 SQL 注入攻击。
然而,我遇到了一个问题。 我有一个包含一些 VARCHAR 列的表,这些列被指定为非空(即不允许 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违反了not-null constraint
"
作为临时解决方法,我检查 $value
是否为空,并将其更改为 " "
(单个空格),但这是一个可怕的黑客行为并可能导致其他问题。
我应该如何使用准备好的语句插入空字符串,而不尝试插入 NULL?
编辑:这个项目太大了,无法遍历我的整个代码库,找到所有使用空字符串“”并将其更改为使用 NULL 的地方。 我需要知道的是为什么标准 MySQL 查询将“”和 NULL 视为两个独立的事物(我认为是正确的),但准备好的语句将“”转换为 NULL。
请注意,“”和 NULL 不是同一件事。 例如,SELECT NULL = "";
返回 NULL
,而不是您期望的 1
。
I used to use the standard mysql_connect(), mysql_query(), etc statements for doing MySQL stuff from PHP. Lately I've been switching over to using the wonderful MDB2 class. Along with it, I'm using prepared statements, so I don't have to worry about escaping my input and SQL injection attacks.
However, there's one problem I'm running into. I have a table with a few VARCHAR columns, that are specified as not-null (that is, do not allow NULL values). Using the old MySQL PHP commands, I could do things like this without any problem:
INSERT INTO mytable SET somevarchar = '';
Now, however, if I have a query like:
INSERT INTO mytable SET somevarchar = ?;
And then in PHP I have:
$value = "";
$prepared = $db->prepare($query, array('text'));
$result = $prepared->execute($value);
This will throw the error "null value violates not-null constraint
"
As a temporary workaround, I check if $value
is empty, and change it to " "
(a single space), but that's a horrible hack and might cause other issues.
How am I supposed to insert empty strings with prepared statements, without it trying to instead insert a NULL?
EDIT: It's too big of a project to go through my entire codebase, find everywhere that uses an empty string "" and change it to use NULL instead. What I need to know is why standard MySQL queries treat "" and NULL as two separate things (as I think is correct), but prepared statements converts "" into NULL.
Note that "" and NULL are not the same thing. For Example, SELECT NULL = "";
returns NULL
instead of 1
as you'd expect.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
感谢一些答案,我意识到问题可能出在 MDB2 API 中,而不是在 PHP 或 MYSQL 命令本身中。 果然,我在 MDB2 FAQ 中发现了这一点:
感谢所有提供深思熟虑答案的人。
Thanks to some of the answers, I realized that the problem may be in the MDB2 API, and not in the PHP or MYSQL commands themselves. Sure enough, I found this in the MDB2 FAQ:
Thanks to everyone who provided thoughtful answers.
这听起来像是 MDB2 API 摸索 PHP 的鸭子类型语义的问题。 因为 PHP 中的空字符串相当于 NULL,所以 MDB2 可能错误地这样对待它。 理想的解决方案是在其 API 中找到解决方法,但我对它不太熟悉。
不过,您应该考虑的一件事是 SQL 中的空字符串不是 NULL 值。 您可以将它们插入声明为“NOT NULL”的行中:
如果您无法在 MDB2 API 中找到(或实现)解决方法,则可能有一种黑客解决方案(尽管比您当前使用的解决方案稍好一些)为空字符串定义 用户变量 --
最后,如果您需要在 INSERT 语句中使用空字符串但发现自己无法做到,MySQL 中字符串类型的默认值是空字符串。 因此,您可以简单地从 INSERT 语句中省略该列,它会自动设置为空字符串(假设该列具有 NOT NULL 约束)。
This sounds like a problem with the MDB2 API fumbling PHP's duck typing semantics. Because the empty string in PHP is equivalent to NULL, MDB2 is probably mis-treating it as such. The ideal solution would be to find a workaround for it within it's API, but I'm not overly familiar with it.
One thing that you should consider, though, is that an empty string in SQL is not a NULL value. You can insert them into rows declared 'NOT NULL' just fine:
If you're unable to find (or implement) a workaround in the MDB2 API, one hackish solution (though slightly better than the one you're currently using) might be to define a user variable for the empty string --
Finally, if you need to use the empty string in an INSERT statement but find yourself unable to, the default value for string types in MySQL is an empty string. So you could simply omit the column from INSERT statement and it would automatically get set to the empty string (provided the column has a NOT NULL constraint).
我意识到这个问题几乎已经得到解答并已退休,但我在寻找类似情况的答案时发现了它,并且我忍不住投身其中。
如果不知道 NULL/"" 列与什么相关,我就无法知道空字符串的真正含义。 空字符串本身是否意味着什么(例如,如果我说服法官让我将我的名字更改为空,如果我的名字在我的驾驶执照上显示为 NULL,我会非常生气。我的名字会是!
但是,空字符串(或空白,或空无一物,不仅仅是缺少任何东西(如 NULL))也可能只是意味着“NOT NULL”或“什么都没有,但仍然不为 Null”,您甚至可以走另一个方向。并建议缺少 NULL 值使其比 Null 更不重要,因为 Null 至少有一个可以大声说出的名称!
我的观点是,如果空字符串是某些数据的直接表示(例如名称,或者我更喜欢在我的电话号码中的数字之间插入什么,等等),那么你的选择要么是争论,直到你对空字符串的合法使用感到痛苦,要么使用代表不为 NULL 的空字符串的东西(例如 ASCII 控制字符或某些 unicode 等效项、某种正则表达式值,或者更糟糕的是,任意但完全未使用的标记,例如: ◘
如果空单元格确实意味着 NOT NULL,那么您可以考虑其他一些表达它的方式。 一种愚蠢而明显的方式是短语“Not NULL”。 但我有一种预感,NULL 意味着“根本不属于这个团体”,而空字符串意味着“这个家伙很酷,他只是还没有得到他的帮派纹身”。 在这种情况下,我会为这种情况提出一个术语/名称/想法,例如“默认”或“新秀”或“待定”。
现在,如果有某种疯狂的机会,您实际上想要空字符串来表示甚至不值得 NULL 的内容,请再次为此提出一个更重要的符号,例如“-1”或“SUPERNULL”或“UGLIES”。
在印度种姓制度中,最低种姓是首陀罗:农民和劳工。 在这个种姓之下的是达利特人:“贱民”。 他们不被视为较低种姓,因为将他们设置为最低种姓会被视为对整个系统的污染。
所以不要因为我认为空字符串可能比 NULL 更糟糕而说我疯了!
直到下次。
I realize this question is pretty much answered and retired, but I found it while looking for answers to a similar situation and I can't resist throwing my hat in the ring.
Without knowing what the NULL/"" column relates to, I can't know how the true significance of an empty string. Does empty string mean something unto itself (like, if I convinced a judge to let me change my name to simply nothing, I would be really irritated if my name showed up on my Driver's License as NULL. My name would be !
However, the empty string (or blank, or the nothingness that is SOMETHING, not simply the lack of anything (like NULL)) could also simply just mean "NOT NULL" or "Nothing, but still not Null". You could even go the other direction and suggest that the absence of the value NULL makes it even LESS something than Null, cuz at least Null has a name you can say aloud!
My point is, that if the empty string is a direct representation of some data (like a name, or what I prefer be inserted between the numbers in my phone number, etc), then your options are either to argue until you're sore for the legitimate use of empty string or to use something that represents an empty string that isn't NULL (Like an ASCII control character or some unicode equivalent, a regex value of some kind, or, even worse, an arbitrary yet totally unused token, like: ◘
If the empty cell really just means NOT NULL, then you could think of some other way of expressing it. One silly and obvious way is the phrase "Not NULL". But I have a hunch that NULL means something like "Not part of this group at all" while the empty string means something like "this guy is cool, he just hasn't gotten his gang tattoos yet". In which case I would come up with a term/name/idea for this situation, like "default" or "rookie" or "Pending".
Now, if by some crazy chance you actually want empty string to represent that which is not even worthy of NULL, again, come up with a more significant symbol for that, such as "-1" or "SUPERNULL" or "UGLIES".
In the Indian Caste System, the lowest Caste are Shudra: Farmers and Laborers. Beneath this caste are the Dalit: "The Untouchables". They are not considered a lower caste, because setting them as the lowest caste would be considered a contamination of the entire system.
So don't call me crazy for thinking empty strings may be WORSE than NULL!
'Til next time.
我找到了解决方案!
MDB2 将空字符串转换为 NULL,因为默认情况下可移植性选项 MDB2_PORTABILITY_EMPTY_TO_NULL 处于启用状态(感谢 Oracle 将空字符串视为 null)。
连接到数据库时关闭此选项:
I found the solution!
MDB2 converts empty strings to NULL because portability option MDB2_PORTABILITY_EMPTY_TO_NULL is on by default (thanks to Oracle which considers empty strings to be null).
Switch this options off when you connect to the database:
0 和空字符串都是变量,NULL 表示没有数据。 要容易得多:/
相信我,编写一个查询来
SELECT * from table where Mything IS NULL
比尝试查询空字符串While 0 and empty strings are variables NULL is the absence of data. And trust me, it's a lot easier to write a query to
SELECT * from table where mything IS NULL
than to try to query for empty strings :/空引号
""
不可以做到这一点吗?Doesn't an empty set of quotes,
""
do that?我很困惑。 看起来您正在使用 mysqli OO (从标签和样式来看),但语法与 手册 上说要这样做:
I'm confused. It looks like you're using mysqli OO (from the tags and style), but the syntax is different than the manual on php.net, which says to do this instead: