Пустая строка в ненулевом столбце в MySQL? - PullRequest
12 голосов
/ 05 ноября 2008

Я использовал стандартные операторы 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, как и следовало ожидать.

Ответы [ 7 ]

17 голосов
/ 05 ноября 2008

Благодаря некоторым ответам я понял, что проблема может быть в MDB2 API, а не в самих командах PHP или MYSQL. Конечно же, я нашел это в FAQ по MDB2:

  • Почему пустые строки заканчиваются как NULL в базе данных? Почему я получаю NULL не допускается в текстовых полях NOT NULL хотя значение по умолчанию ""?
    • Проблема в том, что для некоторых СУБД (особенно Oracle) пустой Строка имеет значение NULL. Поэтому MDB2 обеспечивает возможность переносимости обеспечить одинаковое поведение на всех RDBMS.
    • Поскольку все параметры переносимости включены по умолчанию, у вас будет отключить функцию, если вы не хочу иметь такое поведение: $ Mdb2-> SetOption ( 'портативность', MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL);

Спасибо всем, кто дал вдумчивые ответы.

12 голосов
/ 05 ноября 2008

Это звучит как проблема с API-интерфейсом MDB2. Поскольку пустая строка в 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

Если вы не можете найти (или внедрить) обходной путь в API-интерфейсе MDB2, одно хакерское решение (хотя и немного лучше, чем то, которое вы используете в настоящее время) может заключаться в определении пользовательской переменной для пустой строки -

SET @EMPTY_STRING = "";
UPDATE tbl SET row=@EMPTY_STRING;

Наконец, если вам нужно использовать пустую строку в операторе INSERT, но вы не можете это сделать, значением по умолчанию для строковых типов в MySQL является пустая строка. Таким образом, вы можете просто опустить столбец в операторе INSERT, и он будет автоматически установлен на пустую строку (при условии, что столбец имеет ограничение NOT NULL).

2 голосов
/ 19 июня 2009

Я понимаю, что на этот вопрос в значительной степени ответили и удалились, но я нашел его, когда искал ответы на подобную ситуацию, и я не могу удержаться, бросая свою шляпу на ринге.

Не зная, к чему относится столбец NULL / "", я не могу понять, каково истинное значение пустой строки. Означает ли пустая строка что-то для себя (например, если бы я убедил судью разрешить мне изменить свое имя на просто ничего, я был бы очень раздражен, если бы мое имя появилось в моих водительских правах как NULL. Моё имя было бы!

Однако, пустая строка (или пустая строка, или небытие, что-то, а не просто отсутствие чего-либо (например, NULL)) также может просто означать «NOT NULL» или «Nothing, но все же не Null». Можно даже пойти в другом направлении и предположить, что отсутствие значения NULL делает его даже МЕНЬШЕ чем-то, кроме Null, потому что, по крайней мере, у Null есть имя, которое вы можете произнести вслух!

Моя точка зрения такова, что если пустая строка является прямым представлением некоторых данных (например, имени или того, что я предпочитаю вставлять между номерами в моем номере телефона и т. Д.), То вы можете либо поспорить, пока вы нуждаетесь в законном использовании пустой строки или в использовании чего-либо, представляющего пустую строку, которая не равна NULL (например, управляющий символ ASCII или какой-то эквивалент в юникоде, какое-то значение регулярного выражения или, что еще хуже, произвольное полностью неиспользованный токен, например: 100

Если пустая ячейка действительно просто означает НЕ НУЛЬ, тогда вы можете подумать о каком-то другом способе выражения этого. Один глупый и очевидный способ - фраза «Не NULL». Но у меня есть догадка, что NULL означает что-то вроде «Не является частью этой группы вообще», в то время как пустая строка означает что-то вроде «этот парень классный, он просто еще не получил свои татуировки банды». В этом случае я бы придумал термин / имя / идею для этой ситуации, такой как «default», «rookie» или «Pending».

Теперь, если по какой-то безумной случайности вы действительно хотите, чтобы пустая строка представляла то, что даже не достойно NULL, опять же придумайте для этого более значимый символ, такой как «-1» или «SUPERNULL» или « Уроды».

В индийской кастовой системе низшей кастой являются шудры: фермеры и рабочие. Под этой кастой находятся далит: «Неприкасаемые». Они не считаются низшей кастой, потому что установление их в качестве низшей касты будет считаться загрязнением всей системы.

Так что не называй меня сумасшедшим, потому что я думаю, что пустые строки могут быть БОЛЬШЕ, чем NULL!

'До следующего раза.

1 голос
/ 01 июня 2011

Хотя 0 и пустые строки являются переменными, NULL - это отсутствие данных. И поверьте мне, гораздо проще написать запрос к

SELECT * from table where mything IS NULL, чем пытаться запросить пустые строки: /

1 голос
/ 19 февраля 2010

Я нашел решение!

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 голосов
/ 05 ноября 2008

Я в замешательстве. Похоже, вы используете mysqli OO (из тегов и стиля), но синтаксис отличается от manual на php.net, который говорит, что вместо этого нужно сделать:

$query = "INSERT INTO mytable SET somevarchar = ?";
$value = "";
$prepared = $db->prepare($query);
$prepared->bind_param("s", $value);
$result = $prepared->execute();
0 голосов
/ 05 ноября 2008

Разве не пустой набор цитат, "" делает это?

...