2010-03-17 4 views
15

MySQL INSERT Handbuch Zitiert - Gleiches gilt für UPDATE:Vorbereiten einer MySQL INSERT/UPDATE-Anweisung mit Standardwerten

Use the keyword DEFAULT to set a column explicitly to its default value. This makes it easier to write INSERT statements that assign values to all but a few columns, because it enables you to avoid writing an incomplete VALUES list that does not include a value for each column in the table. Otherwise, you would have to write out the list of column names corresponding to each value in the VALUES list.

Also kurz gesagt, wenn ich

INSERT INTO table1 (column1,column2) values ('value1',DEFAULT); 

eine neue Zeile mit column2 schreiben gesetzt, wie sein Standardwert - was auch immer es sein mag - wird eingefügt.

Allerdings, wenn ich eine Aussage in PHP erstellen und auszuführen:

$statement = $pdoObject-> 
    prepare("INSERT INTO table1 (column1,column2) values (?,?)"); 
$statement->execute(array('value1','DEFAULT')); 

Die neue Zeile wird ‚Standard‘ als Textwert enthält - wenn die Spalte der Lage ist, Textwerte zu speichern.

Jetzt habe ich eine Abstraktionsschicht zu PDO geschrieben (ich es nicht erforderlich), um dieses Problem zu bekommen ich angesichts einer

const DEFAULT_VALUE = "randomstring"; 

einzuführen So konnte ich Aussagen wie folgt ausführen:

$statement->execute(array('value1',mysql::DEFAULT_VALUE)); 

Und dann in der Methode, die die Bindung tut, würde ich durch Werte gehen, die gesendet werden, um gebunden zu sein, und wenn einige gleich sind self::DEFAULT_VALUE, entsprechend handeln.

Ich bin mir ziemlich sicher, es gibt einen besseren Weg, dies zu tun. Hat jemand anderes ähnliche Situationen erlebt?

+0

Da PDO Ihre Werte Verarbeitung als Strings eingegeben werden, es sieht aus wie Sie müssen möglicherweise die ändern Code ein bisschen, wenn das möglich ist. Sie könnten es so ändern, dass Sie '... execute (array ('\' value1 \ '', 'DEFAULT'))' eingeben, aber ich nehme an, dass PDO diese Werte für Sie mit mysql_real_escape_string() verarbeitet. 'usw. Dies würde diese Funktion zunichte machen. Sie müssen es wahrscheinlich direkt in das 'prepare()' Argument einfügen. – Jonah

+1

Warum sollten Sie nicht einfach Spalten in Ihre INSERT-Anweisung aufnehmen, die Sie auf einen anderen Wert als den Standardwert setzen? –

+1

Das Problem ist mit "UPDATE" und eine leere Eingabe gesendet. Ich brauche es als Standard, nicht zum Beispiel '0000-00-00' für Datumsfelder, wenn '' ''als neuer Wert festgelegt wird. – raveren

Antwort

8

Die einzige „Abhilfe“ Ich weiß, dies ist Coalesce() und Default(fieldname)

verwenden Z. B.

$pdo = new PDO("mysql:host=localhost;dbname=test", 'localonly', 'localonly'); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

$pdo->exec(" 
    CREATE TEMPORARY TABLE foo (
    id int auto_increment, 
    x int NOT NULL DEFAULT 99, 
    y DATETIME NOT NULL DEFAULT '2010-03-17 01:00:00', 
    z varchar(64) NOT NULL DEFAULT 'abc', 
    primary key(id) 
) 
"); 


$stmt = $pdo->prepare(' 
    INSERT INTO 
    foo 
    (x,y,z) 
    VALUES 
    (
     Coalesce(:x, Default(x)), 
     Coalesce(:y, Default(y)), 
     Coalesce(:z, Default(z)) 
    ) 
'); 
$stmt->bindParam(':x', $x); 
$stmt->bindParam(':y', $y); 
$stmt->bindParam(':z', $z); 


$testdata = array(
    array(null, null, null), 
    array(1, null, 'lalala'), 
    array(null, '2009-12-24 18:00:00', null) 
); 
foreach($testdata as $row) { 
    list($x,$y,$z) = $row; 
    $stmt->execute(); 
} 
unset($stmt); 
foreach($pdo->query('SELECT id,x,y,z FROM foo', PDO::FETCH_NUM) as $row) { 
    echo join(', ', $row), "\n"; 
} 

druckt

1, 99, 2010-03-17 01:00:00, abc 
2, 1, 2010-03-17 01:00:00, lalala 
3, 99, 2009-12-24 18:00:00, abc 
+1

Standard (x) kann DEFAULT sein. Wenn Sie den Standardwert für diese Spalte in derselben Spalte angeben möchten, müssen Sie den Spaltennamen nicht angeben. Es ist fehlerträchtig. UPDATE t SET x = STANDARD; –

+0

Tolles Denken! Nicht perfekt, aber schlägt meine Lösung! – raveren

+3

@Frank: Es muss Standard (Feldname) sein, wenn es als Argument für Coalesce() verwendet wird. – VolkerK

0

Versuchen Sie, diese:

$statement = $pdoObject-> 
    prepare("INSERT INTO table1 (column1,column2) values (?,?)"); 
$statement->execute(array('value1','DEFAULT')); 

Um dies:

$statement = $pdoObject-> 
    prepare("INSERT INTO table1 (column1,column2) values (?,DEFAULT)"); 
$statement->execute(array('value1')); 

Es scheint mir, dass Ihr Original-Code wird Ihnen dies:

INSERT INTO table1 (column1,column2) values ('value1','DEFAULT') 

Mein Code sollte Ihnen dies:

INSERT INTO table1 (column1,column2) values ('value1',DEFAULT) 
+0

Wer könnte jemals andere Werte wollen, aber trotzdem default. – raveren

1

Ich versuchte VolkerK Antwort antworten, bekam aber nicht, wie zu finden. :(Ich bin ein bisschen neu für alle diese

Wie auch immer, ich eine MySQL-Funktion erstellt in Verbindung mit seiner COALESCE Idee

CREATE FUNCTION NULLDEFAULT(colname VARCHAR(64), tablename VARCHAR(64), dbname VARCHAR(64)) RETURNS longtext DETERMINISTIC READS SQL DATA 
BEGIN 
    DECLARE retval longtext; 
    SELECT 
     COLUMN_DEFAULT INTO retval 
    FROM 
     information_schema.COLUMNS 
    WHERE 
     TABLE_NAME = tablename 
    AND 
     COLUMN_NAME = colname 
    AND 
     TABLE_SCHEMA = dbname; 

    RETURN retval; 
END 

Sie es wie folgt verwenden würde zu verwenden.

$stmt = $pdo->prepare(" 
    INSERT INTO 
    foo 
    (x,y,z) 
    VALUES 
    (
     Coalesce(:x, NULLDEFAULT('x', 'foo', 'database')), 
     Coalesce(:y, NULLDEFAULT('y', 'foo', 'database')), 
     Coalesce(:z, NULLDEFAULT('z', 'foo', 'database')) 
    ) 
"); 

Das gibt null zurück, wenn die Spalte keinen Standardwert hat, und löst den Fehler "Spalte hat keinen Standardwert" aus.

Natürlich könnte man es ändern, um nicht auf die Datenbank benötigen Parameter

+0

Ich denke nicht, dass es leistungsmäßig halten würde. AFAIK mysql wird die Ergebnisse von Funktionen nicht zwischenspeichern, daher würden Sie Ihre Abfrage für jede Zeile und jede Spalte in der Einfügeabfrage aufrufen. Es ist viel besser, vorher die Standardwerte über PHP zu bekommen, aber wie ich bereits festgestellt habe, ist meine Lektion, die ich hier gelernt habe, dass man sich nicht auf die Standard-MySQL-Werte verlässt. Ich gebe dir immer noch eine +1 für die Mühe. – raveren

+0

Gemäß der Dokumentation teilt das Schlüsselwort DETERMINISTIC mysql mit, dass die Funktion immer die gleichen Werte mit den gleichen Parametern zurückgibt, so dass ich glauben würde, dass das Ergebnis zwischengespeichert wird. Aber ich habe es nicht ausgiebig probiert, ich benutze es in einem kleinen Intranet ohne merkliche Geschwindigkeitseinbußen. –

0

ich denke, dass es die Zeichenfolge ‚Standard‘ ist das Schreiben, weil es von gU entkommen ist, so gibt es Parameter für bindValue wo Sie den Typ angeben können der angegebene Wert, so dass Sie eine Null ohne Anführungszeichen senden können und es wird PDO :: PARAM_NULL; und dann die Standardwerte gesetzt werden, aber ich bin nicht sicher, ob es ähnliche Parameter beim Binden mit ausführen

if(is_int($param)){$pdoParam = PDO::PARAM_INT;} 
     elseif(is_bool($param)){$pdoParam = PDO::PARAM_BOOL;} 
     elseif(is_null($param)){ $pdoParam = PDO::PARAM_NULL;} 
     elseif(is_string($param)){$pdoParam = PDO::PARAM_STR;} 
            else{$pdoParam = FALSE;} 
       $this->_query->bindValue($k,$param,$pdoParam); 
+0

Was ist '$ pdoParam = FALSE;' soll erreicht werden? Der Standardwert ist 'PARAM_STR'. – DanMan