Вставить в пустые поля, бросая ошибки с пустыми значениями

MySQL v5.6.20; Стол в вопросе:

CREATE TABLE `invoices` (
`INVOICE_NUMBER` smallint(4) unsigned NOT NULL AUTO_INCREMENT,
`INVOICE_DATE` date DEFAULT NULL,
`PROJECT_NUMBER` smallint(4) unsigned DEFAULT NULL,
`CLIENT` tinytext COLLATE utf8_unicode_ci,
`PROJECT_DESCRIPTION` tinytext COLLATE utf8_unicode_ci,
`TOTAL_HOURS` text COLLATE utf8_unicode_ci,
`SUBTOTAL` decimal(10,2) unsigned DEFAULT NULL,
`TAX` decimal(10,2) unsigned DEFAULT NULL,
`INVOICE_TOTAL` decimal(10,2) unsigned DEFAULT NULL,
`DATE_SENT` date DEFAULT NULL,
`DATE_RECEIVED` date DEFAULT NULL,
`NOTES` text COLLATE utf8_unicode_ci,
PRIMARY KEY (`INVOICE_NUMBER`)
) ENGINE=InnoDB AUTO_INCREMENT=1005 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

И соответствующие биты моего process.php:

if (isset($_POST['submit'])) {
$invNum = $_POST['invNum'];
$invDate = $_POST['invDate'];
$projNum = $_POST['projNum'];
$client = $_POST['client'];
$projDesc = $_POST['projDesc'];
$totalHours = $_POST['totalHours'];
$subTotal = $_POST['subTotal'];
$tax = $_POST['tax'];
$invTotal = $_POST['invTotal'];
$dateSent = $_POST['dateSent'];
$dateReceived = $_POST['dateReceived'];
$notes = $_POST['notes'];
$notes = mysqli_real_escape_string($mysqli, $notes);

echo "<div class=\"debug\">
<table>
<snip>( SUCCESSFULLY ECHOING ALL VARIABLES/VALUES )</snip>
</table>
</div>";$stmt = $mysqli->stmt_init();
$query = "INSERT INTO Invoices
(INVOICE_NUMBER, INVOICE_DATE, PROJECT_NUMBER, CLIENT, PROJECT_DESCRIPTION, TOTAL_HOURS, SUBTOTAL, TAX, INVOICE_TOTAL, DATE_SENT, DATE_RECEIVED, NOTES)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
INVOICE_NUMBER          = VALUES(INVOICE_NUMBER),
INVOICE_DATE            = VALUES(INVOICE_DATE),
PROJECT_NUMBER          = VALUES(PROJECT_NUMBER),
CLIENT                  = VALUES(CLIENT),
PROJECT_DESCRIPTION = VALUES(PROJECT_DESCRIPTION),
TOTAL_HOURS             = VALUES(TOTAL_HOURS),
SUBTOTAL                    = VALUES(SUBTOTAL),
TAX                     = VALUES(TAX),
INVOICE_TOTAL           = VALUES(INVOICE_TOTAL),
DATE_SENT               = VALUES(DATE_SENT),
DATE_RECEIVED           = VALUES(DATE_RECEIVED),
NOTES                       = VALUES(NOTES)
";

if ($stmt->prepare($query)) {
$stmt -> bind_param("ssssssdddsss", $invNum, $invDate, $projNum, $client, $projDesc, $totalHours, $subTotal, $tax, $invTotal, $dateSent, $dateReceived, $notes);
echo $query; // debug
$stmt -> execute();
if ($mysqli->errno) {
echo "<div class=\"error\"><br />INSERT failed: (" . $mysqli->errno . ") " . $mysqli->error . "<br /><br /></div>";
}
else echo "Updated {$stmt->affected_rows} rows";

$result = $mysqli->query($query);

$affRows = mysqli_affected_rows($mysqli);
$my_id = mysqli_insert_id($mysqli); // last inserted ID (INVOICE_NUMBER)

if (($result) && ($affRows)) {
echo "<div class=\"debug\">
<p>
<strong>SUCCESS: RECORD INSERTED / UPDATED.</strong><br />
<strong>Records updated: " . $affRows . "</strong><br />
<strong>mysqli_insert_id = ".$my_id."</strong>
</p>
</div>";
}
$stmt->close();
}

Что касается моей первоначальной проблемы (которая сохраняется):

По моему незнанию, я не знал, что пустые строки недопустимы в десятичной & поля даты. Однако, хотя я не изменил десятичные поля, они теперь принимают пустые строки, поэтому мне интересно, есть ли что-то под капотом подготовленного оператора, которое переводит в нули? Если это так, то это не относится к полям даты (в моей таблице как десятичные поля, так и поля даты по умолчанию имеют значение null), что являются выбрасывать ошибки с пустой строкой. Очевидно поля даты ведут себя по-другому?

Если единственным решением является функция php, которая проверяет наличие пустых строк и отправляет соответственно null, то я вернусь к этому вопросу; На данный момент я сфокусирован на js, поэтому при необходимости у меня возникнет соблазн просто изменить типы полей и вернуться к изучению js.

Любое понимание или предложения с благодарностью,

SVS

-3

Решение

Итак, давайте посмотрим на фактическое сообщение об ошибке:

«Ошибка INSERT: (1366) Неверное десятичное значение:« для столбца «НАЛОГ» в строке 1 »

Не похоже, что он жалуется на NULL значение, похоже, что он жалуется на decimal значение. Он даже говорит вам ценность, на которую он жалуется:

''

Пустая строка не decimal, Это также не NULL, Это пустая строка. И вы не можете хранить строку в decimal колонка, как ни старайся.

Глядя на ваш запрос, довольно ясно, почему это происходит:

....
TAX = '$tax'
....

Что происходит, когда $tax пустой? Ваш запрос становится таким:

....
TAX = ''
....

Есть несколько способов справиться с этим. Вы мог добавьте много условной логики для построения запроса по одному полю за раз, проверяя значение в этом поле и полностью опуская его, если значение NULL (или включите его с явным NULL в запросе). Но лучше подход (и тот, который устранит вашу явную уязвимость SQL-инъекций) будет состоять в том, чтобы использовать параметризованный запрос и позволить ядру базы данных обрабатывать NULL значения, которые вы передаете. (Только обязательно передайте это NULL а не пустая строка.)

2

Другие решения

Когда вы строите строку, как это. , ,

$query = "INSERT INTO Invoices SET
...
TAX = '$tax',
...

и переменная PHP $ tax равна, скажем, 3.02, результирующая строка будет выглядеть следующим образом.

INSERT INTO Invoices SET ... TAX = '3.02' ...

Обратите внимание, что он пытается вставить строку, а не числовое значение. В общем, это все-таки получится.

Но переменная PHP $ tax равна NULL Полученная строка будет выглядеть следующим образом.

INSERT INTO Invoices SET ... TAX = 'NULL' ...

DBMS пытается установить значение для TAX на строка чье значение «NULL». Тот строка является не то же самое, что NULL,

Вместо построения запроса с использованием строковой интерполяции используйте MySQLi () или же PDO. Это также предотвратит внедрение SQL-кода, о котором, я уверен, вы скоро услышите.

0

По вопросам рекламы [email protected]