Раньше я использовал стандартные операторы mysql_connect (), mysql_query () и т. д. Для работы с MySQL из PHP. В последнее время я перехожу на использование замечательного класса 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 violates not-null constraint".
В качестве временного обходного пути я проверяю, пуст ли $value, и меняю его на " " (один пробел), но это ужасный взлом и может вызвать другие проблемы.
Как я должен вставлять пустые строки с подготовленными операторами, не пытаясь вместо этого вставить NULL?
Обновлено: Это слишком большой проект, чтобы просмотреть всю мою кодовую базу, найти везде, где используется пустая строка "", и изменить ее, чтобы вместо этого использовать NULL. Мне нужно знать, почему стандартные запросы MySQL рассматривают "" и NULL как две отдельные вещи (как я считаю правильным), а подготовленные операторы преобразуют "" в NULL.
Обратите внимание, что "" и NULL - это нет одно и то же. Например, SELECT NULL = ""; возвращает NULL вместо 1, как и следовало ожидать.
он "в основном" равен нулю, так же как 0 является "в основном" ложным. они похожи, но на самом деле совсем разные.
NULL означает «нет значения», а не «пустая строка»
Потому что у меня есть код, который выглядит так: SELECT FROM table WHERE column = "", а "" не равно NULL.
Это правда, но хранение «пустого» в том смысле, что оно не содержит данных, значения, почти положительное, стоит дороже, чем хранение NULL.
Вы правы, что NULL - это не то же самое, что "", но вы не должны проводить сравнение, например, SELECT NULL = ""; они всегда будут возвращать null независимо от того, какое значение вы сравниваете с null






Разве это не пустой набор кавычек, ""?
Нет, "" и NULL - разные вещи и ведут себя по-разному в большинстве баз данных.
@davr - именно поэтому я сказал это сделать - он пытается получить значение NOT NULL в базу данных, а пустые кавычки
Я запутался. Похоже, вы используете mysqli OO (из тегов и стиля), но синтаксис отличается от руководство по эксплуатации на php.net, в котором вместо этого говорится:
$query = "INSERT INTO mytable SET somevarchar = ?";
$value = "";
$prepared = $db->prepare($query);
$prepared->bind_param("s", $value);
$result = $prepared->execute();
Я использую MDB2, который внутренне использует mysqli.
Это похоже на проблему с API MDB2, который неуклюже искажает семантику 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, одно из хакерских решений (хотя и немного лучше, чем то, которое вы сейчас используете) может заключаться в определении переменная пользователя для пустой строки -
SET @EMPTY_STRING = "";
UPDATE tbl SET row=@EMPTY_STRING;
Наконец, если вам нужно использовать пустую строку в операторе INSERT, но вы не можете этого сделать, значение по умолчанию для строковых типов в MySQL - это пустая строка. Таким образом, вы можете просто опустить столбец из оператора INSERT, и он автоматически установит пустую строку (при условии, что столбец имеет ограничение NOT NULL).
Вот и все, я не думал, что виноват сам MDB2. Спасибо.
Благодаря некоторым ответам я понял, что проблема может быть в API MDB2, а не в самих командах PHP или MYSQL. Конечно же, я нашел это в FAQ по MDB2:
- Why do empty strings end up as NULL in the database? Why do I get an NULL not allowed in NOT NULL text fields eventhough the default value is ""?
- The problem is that for some RDBMS (most noteably Oracle) an empty string is NULL. Therefore MDB2 provides a portability option to enforce the same behaviour on all RDBMS.
- Since all portability options are enabled by default you will have to disable the feature if you dont want to have this behaviour: $mdb2->setOption('portability', MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL);
Спасибо всем, кто дал обстоятельные ответы.
Я понимаю, что на этот вопрос в значительной степени дан ответ и он снят, но я нашел его, ища ответы на аналогичную ситуацию, и я не могу удержаться от того, чтобы бросить свою шляпу на ринг.
Не зная, к чему относится столбец NULL / "", я не могу понять истинное значение пустой строки. Означает ли пустая строка что-то само по себе (например, если бы я убедил судью позволить мне изменить мое имя на просто ничто, я был бы очень раздражен, если бы мое имя появилось в моих водительских правах как NULL. Моё имя было бы!
Однако пустая строка (или пробел, или ничто, являющееся ЧТО-ТО, а не просто отсутствие чего-либо (например, NULL)) также может просто означать «NOT NULL» или «Nothing, но все же не NULL». Вы даже можете пойти в другом направлении и предположить, что отсутствие значения NULL делает его даже МЕНЬШЕ чем-то, чем Null, потому что, по крайней мере, у Null есть имя, которое вы можете произнести вслух!
Я хочу сказать, что если пустая строка является прямым представлением некоторых данных (например, имени или того, что я предпочитаю вставлять между числами в моем номере телефона и т. д.), Тогда вы можете спорить, пока не почувствуете боль. для законного использования пустой строки или для использования чего-то, что представляет собой пустую строку, которая не является NULL (например, управляющий символ ASCII или некоторый эквивалент Unicode, какое-либо значение регулярного выражения или, что еще хуже, произвольный, но полностью неиспользуемый токен , например: ◘
Если пустая ячейка на самом деле означает НЕ NULL, вы можете придумать другой способ выразить это. Один глупый и очевидный способ - это фраза «Not NULL». Но у меня есть подозрение, что NULL означает что-то вроде «Не входит в эту группу вообще», а пустая строка означает что-то вроде «этот парень крутой, просто у него еще нет татуировок банды». В этом случае я бы предложил термин / название / идею для этой ситуации, например «по умолчанию», «новичок» или «ожидает рассмотрения».
Теперь, если по какой-то безумной случайности вы действительно хотите, чтобы пустая строка представляла то, что даже не достойно NULL, снова придумайте для этого более значимый символ, такой как «-1», «SUPERNULL» или «UGLIES».
В индийской кастовой системе низшая каста - это шудра: фермеры и рабочие. Под этой кастой находятся далиты: «Неприкасаемые». Они не считаются низшей кастой, потому что установка их как низшей касты будет считаться заражением всей системы.
Так что не называйте меня сумасшедшим из-за того, что я считаю, что пустые строки могут быть ХУЖЕ, чем NULL!
До следующего раза.
Я нашел решение!
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);
ммм ... Я написал этот точный ответ больше года назад.
В то время как 0 и пустые строки являются переменными, NULL означает отсутствие данных. И поверьте мне, намного проще написать запрос к
SELECT * from table where mything IS NULL, чем пытаться запросить пустые строки: /
Если вы вставляете "", который в основном имеет значение null, почему бы не изменить поле в базе данных, чтобы разрешить null.