Я создал таблицу с ограничениями NOT NULL
для некоторых столбцов в MySQL. Затем в PHP я написал скрипт для вставки данных с запросом на вставку. Когда я опускаю один из столбцов NOT NULL
в этой инструкции вставки, я ожидаю сообщение об ошибке от MySQL, и я ожидал бы, что мой скрипт завершится с ошибкой. Вместо этого MySQL вставляет пустые строки в поля NOT NULL
. В других пропущенных полях данные NULL, что отлично. Может ли кто-нибудь сказать мне, что я сделал не так?
Я использую эту таблицу:
CREATE TABLE IF NOT EXISTS tblCustomers ( cust_id int(11) NOT NULL AUTO_INCREMENT, custname varchar(50) NOT NULL, company varchar(50), phone varchar(50), email varchar(50) NOT NULL, country varchar(50) NOT NULL, ... date_added timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (cust_id) ) ;
И это заявление вставки:
$sql = "INSERT INTO tblCustomers (custname,company) VALUES ('".$customerName."','".$_POST["CustomerCompany"]."')"; $res = mysqli_query($mysqli, $sql);
Или используя переменные связывания:
$stmt = mysqli_prepare($mysqli, "INSERT INTO tblCustomers (custname,company, email, country) VALUES (?, ?, ?, ?)"); mysqli_stmt_bind_param($stmt, 'ssss', $customerName, $_POST["CustomerCompany"], $_POST["CustomerEmail"], $_POST["AddressCountry"]); mysqli_stmt_execute($stmt); mysqli_stmt_close($stmt);
Если вы уверены, что не используете явные значения по умолчанию, проверьте свой строгий режим:
SELECT @@GLOBAL.sql_mode; SELECT @@SESSION.sql_mode;
Значения по умолчанию для типа данных MySQL
Начиная с MySQL 5.0.2, если определение столбца не содержит явного значения DEFAULT, MySQL определяет значение по умолчанию следующим образом:
Если столбец может принимать значение NULL в качестве значения, столбец определяется с явным предложением DEFAULT NULL. Это то же самое, что и до 5.0.2.
Если столбец не может принимать значение NULL в качестве значения, MySQL определяет столбец без явного предложения DEFAULT. Для ввода данных, если оператор INSERT или REPLACE не содержит значения для столбца, или оператор UPDATE устанавливает столбец в NULL, MySQL обрабатывает столбец в соответствии с действующим в данный момент режимом SQL:
Если строгий режим SQL не включен, MySQL устанавливает столбец неявным значением по умолчанию для типа данных столбца.
Если включен строгий режим, возникает ошибка для транзакционных таблиц, и инструкция возвращается. Для нетранзакционных таблиц возникает ошибка, но если это произойдет для второй или следующей строки оператора с несколькими строками, предыдущие строки будут вставлены.
Режимы сервера SQL
То, что вы делаете неправильно, заключается в создании запроса с использованием строк вместо использования параметров привязки.
Помимо уязвимости SQL-инъекции, нулевые значения преобразуются в пустые строки еще до того, как база данных увидит их.
$x = null; print_r("VALUES ('$x', 42)");
Выходы:
VALUES ('', 42)
Другими словами, вы вставляете пустую строку, а не NULL. Чтобы вставить NULL, вам нужно было бы написать это:
VALUES (NULL, 42)
Если вы используете параметры привязки, вы не получите эту проблему, и в качестве бонуса ваш сайт не будет иметь столько дыр в безопасности. Я предлагаю вам прочитать ответ на этот вопрос и следовать совету. Это позволит решить вашу непосредственную проблему, а также повысить безопасность вашего сайта.
Я согласен с Марком Байерсом – ваш php неверен для вашего поведения.
Re: Комментарий Марка о параметрах привязки, проверить PDO в PHP
Если вы все еще не хотите использовать параметры, вы можете попробовать следующее:
if (isset($customerName) && $customerName != '') { $c = '\'' . $customerName . '\''; } else { $c = 'null'; } if (isset($_POST['CustomerCompany']) && $_POST['CustomerCompany'] != '') { $cc = '\'' . $_POST['CustomerCompany'] . '\''; } else { $cc = 'null'; } $sql = 'INSERT INTO tblCustomers (custname,company) VALUES ('.$c.','.$cc.')';
Изменить. Вы считали, что просто проверяете свой PHP-код, чтобы убедиться, что значения сначала не пусты / null? Таким образом, вы могли бы избежать поездки в базу данных вообще (на основе моей интерпретации вашего комментария)? Не совсем ответ на поведение MySQL, но может решить вашу проблему.