2010-03-23 11 views
8

Ich habe eine Tabelle mit NOT NULL Einschränkungen für einige Spalten in MySQL erstellt. Dann schrieb ich in PHP ein Skript zum Einfügen von Daten mit einer Einfügeabfrage. Wenn ich eine der NOT NULL Spalten in dieser Einfügeanweisung weglasse, würde ich eine Fehlermeldung von MySQL erwarten, und ich würde erwarten, dass mein Skript fehlschlägt. Stattdessen fügt MySQL leere Zeichenfolgen in die Felder NOT NULL ein. In anderen weggelassenen Feldern sind die Daten NULL, was in Ordnung ist. Könnte mir jemand sagen, was ich hier falsch gemacht habe?MySQL ignoriert die Bedingung NOT NULL

Ich verwende diese Tabelle:

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) 
) ; 

Und dieses Insert-Anweisung:

$sql = "INSERT INTO tblCustomers (custname,company) 
     VALUES ('".$customerName."','".$_POST["CustomerCompany"]."')"; 
$res = mysqli_query($mysqli, $sql); 

Oder mit Bind-Variablen:

$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); 

Antwort

14

Wenn Sie sicher sind, dass Sie nicht explizit Standardwerte verwenden, dann überprüfen Sie die Strict-Modus:

SELECT @@GLOBAL.sql_mode; 
SELECT @@SESSION.sql_mode; 

MySQL Data Type Default Values

Ab MySQL 5.0.2, wenn eine Spalte Definition keinen expliziten DEFAULT-Wert enthält, bestimmt MySQL den Standardwert wie folgt:

Wenn die Spalte NULL als Wert annehmen kann, wobei die Säule mit einer expliziten DEFAULT NULL Klausel definiert ist. Dies ist das gleiche wie vor 5.0.2. Wenn die Spalte NULL nicht als -Wert annehmen kann, definiert MySQL die Spalte mit keine explizite DEFAULT-Klausel. Für die Daten Eintrag, wenn ein INSERT oder REPLACE Anweisung keinen Wert für die Spalt enthält, oder eine UPDATE Anweisung setzt die Spalte auf NULL, Griffe MySQL die Spalt entsprechend den SQL-Modus in zum Zeitpunkt:

  • Wenn strikter SQL-Modus nicht aktiviert ist, setzt MySQL die Spalte auf den impliziten Standardwert für den Spalte Datentyp.

  • Wenn der strikte Modus aktiviert ist, tritt ein Fehler bei den Transaktionstabellen auf und die Anweisung wird zurückgesetzt. Für nicht transaktionale Tabellen tritt ein Fehler auf, aber wenn dies für die zweite oder folgende Zeile einer mehrzeiligen Anweisung geschieht, werden die vorhergehenden Zeilen eingefügt.

Server SQL Modes

+0

Der strikte Modus hat es geschafft! Vielen Dank! Zumindest wenn ich einen Wert weglasse, wird der Datensatz nicht eingefügt. Wenn $ _POST ["CustomerEmail"] leer ist, wird der Datensatz immer noch mit einer leeren Zeichenfolge eingefügt, aber das war nicht der Bereich dieser Frage. Die Suche nach dem Einfügen einer leeren Zeichenfolge wird fortgesetzt. – Whakkee

+0

Um Ihre zweite Frage zu beantworten, sollten Sie die Parameterbindung verwenden, wie in anderen Antworten erklärt, aber denken Sie darüber nach. Du brauchst kein '.' Concat-Operator zum Erstellen einer Abfrage, wenn doppelte Anführungszeichen verwendet werden. Sie können dies "VALUES ($ customerEmail)" tun. Deshalb: if (! Leer ($ _ POST ['CustomerEmail']) {$ customerEmail = '' $ _POST ['CustomerEmail'] '";} else {$ customerEmail =" NULL ";} –

+0

Danke für den Hinweis, ich schon benutzte Parameterbindungen, als Mark Byers es gepostet habe ich meinen Code geändert, und ... Ich überprüfe bereits auf der PHP-Seite, ob es leer ist oder nicht.Ich suche nach einer Datenbankprüfung, wie eine Prüfbeschränkung, die ich mit Oracle-Datenbanken verwendet habe Um ehrlich zu sein: Ich würde keine Prüfbedingung in Oracle brauchen, da eine leere Zeichenkette in Oracle als NULL behandelt wird Eine leere Zeichenkette ist in diesem Fall genauso schlecht wie NULL, also wenn ich noch eine leere einfügen kann string, die NOT NULL-Einschränkung ist für mich ziemlich nutzlos, vielleicht sollte ich eine neue Frage dazu stellen. – Whakkee

4

Was Sie tun, ist falsch Aufbau Ihrer Abfrage mithilfe von Zeichenfolgen anstelle von Bindeparametern.

Abgesehen von der SQL-Injection-Schwachstelle werden die Nullwerte in leere Strings konvertiert, noch bevor die Datenbank sie sieht.

$x = null; 
print_r("VALUES ('$x', 42)"); 

Ausgänge:

VALUES ('', 42) 

Mit anderen Worten: Sie einen leeren String einfügen, kein NULL. Um einen NULL einfügen Sie gebraucht hätte, dies zu schreiben:

VALUES (NULL, 42) 

Wenn Sie binden Parameter verwenden, dann werden Sie dieses Problem nicht erhalten und als Bonus Ihre Website wird nicht so viele Sicherheitslücken aufweisen. Ich schlage vor, Sie lesen die Antwort auf this question und folgen Sie den Ratschlägen dort. Dies wird Ihr unmittelbares Problem lösen und die Sicherheit Ihrer Website verbessern.

+0

Ich muss zugeben, dass eine bessere Verwendung von bindungs ​​Parameter ist, aber es ist mein Problem noch nicht lösen. Ich werde jetzt in die strikte Moduseinstellung schauen ... – Whakkee

1

Ich stimme Mark Byers zu - Ihr PHP ist falsch für das Verhalten, das Sie wollen.

Re: Markus Kommentar über Bindungsparameter Besuche PDO in PHP

Wenn Sie noch Parameter nicht verwenden möchten, können Sie versuchen, die folgenden:


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.')'; 

Edit: Haben Sie darüber nachgedacht Einfach den PHP-Code einchecken, um sicher zu gehen, dass die Werte nicht leer sind. Auf diese Weise könntest du den Trip zur Datenbank komplett vermeiden (basierend auf meiner Interpretation deines Kommentars)? Nicht wirklich eine Antwort auf das MySQL-Verhalten, aber könnte Ihr Problem lösen.

+0

"&& $ _POST ['CustomerCompany']! = ''" Ist redundant. Wenn $ _POST ['CustomerCompany'] eine Zeichenfolge mit der Länge null ist, gibt isset ($ _ POST ['CustomerCompany']) false zurück. – jmucchiello