it-swarm.com.de

So führen Sie ein UPSERT durch, damit ich im Aktualisierungsteil sowohl neue als auch alte Werte verwenden kann

Dummes, aber einfaches Beispiel: Angenommen, ich habe eine Tabelle "Artikel", in der ich die Gesamtmenge der erhaltenen Artikel aufbewahre.

Item_Name              Items_In_Stock

Der Name des Elements ist hier der Primärschlüssel. Wie erreiche ich Folgendes, wenn ich Artikel A in Menge X erhalte? 

Wenn der Artikel nicht vorhanden ist, füge ich einen neuen Eintrag für Artikel A ein und setze die Artikel auf Lager auf X. Wenn ein Datensatz vorhanden ist, bei dem Artikel auf Lager Y waren, lautet der neue Wert in Artikel auf Lager (X + Y).

INSERT INTO `item`
(`item_name`, items_in_stock)
VALUES( 'A', 27)
ON DUPLICATE KEY UPDATE
`new_items_count` = 27 + (SELECT items_in_stock where item_name = 'A' )

Mein Problem ist, dass ich mehrere Spalten in meiner aktuellen Tabelle habe. Ist es eine gute Idee, mehrere Select-Anweisungen in den Aktualisierungsteil zu schreiben?

Natürlich kann ich es im Code machen, aber gibt es einen besseren Weg?

54

Wie in meinem Kommentar erwähnt, müssen Sie nicht die Unterauswahl ausführen, um auf die Zeile zu verweisen, die ON DUPLICATE KEY ausgelöst hat. In Ihrem Beispiel können Sie also Folgendes verwenden:

INSERT INTO `item`
(`item_name`, items_in_stock)
VALUES( 'A', 27)
ON DUPLICATE KEY UPDATE
`new_items_count` = `new_items_count` + 27

Denken Sie daran, dass die meisten Dinge wirklich einfach sind. Wenn Sie sich dabei erwischen, etwas zu kompliziert zu machen, das einfach sein sollte, dann tun Sie es höchstwahrscheinlich falsch.

120
Michael J.V.

Sie können aus diesem Beispiel eine Idee bekommen:

Angenommen, Sie möchten sieben Tage Daten für den Benutzer hinzufügen

Es sollte einen eindeutigen Wert für userid und day like haben 

UNIQUE KEY `seven_day` (`userid`,`day`)

Hier ist der Tisch

CREATE TABLE `table_name` (
  `userid` char(4) NOT NULL,
  `day` char(3) NOT NULL,
  `open` char(5) NOT NULL,
  `close` char(5) NOT NULL,
  UNIQUE KEY `seven_day` (`userid`,`day`)
);

Und Ihre Frage wird sein

INSERT INTO table_name (userid,day,open,close) 
    VALUES ('val1', 'val2','val3','val4') 
        ON DUPLICATE KEY UPDATE open='val3', close='val4';

Beispiel:

<?php
//If your data is
$data= array(
        'sat'=>array("userid"=>"1001", "open"=>"01.01", "close"=>"11.01"),
        'Sun'=>array("userid"=>"1001", "open"=>"02.01", "close"=>"22.01"),
        'sat'=>array("userid"=>"1001", "open"=>"03.01", "close"=>"33.01"),
        'mon'=>array("userid"=>"1002", "open"=>"08.01", "close"=>"08.01"),
        'mon'=>array("userid"=>"1002", "open"=>"07.01", "close"=>"07.01")
    );


//If you query this in a loop
//$conn = mysql_connect("localhost","root","");
//mysql_select_db("test", $conn);

foreach($data as $day=>$info) {
    $sql = "INSERT INTO table_name (userid,day,open,close) 
                VALUES ('$info[userid]', '$day','$info[open]','$info[close]') 
            ON DUPLICATE KEY UPDATE open='$info[open]', close='$info[close]'";
    mysql_query($sql);
}
?>

Ihre Daten werden in der Tabelle sein:

+--------+-----+-------+-------+
| userid | day | open  | close |
+--------+-----+-------+-------+
| 1001   | sat | 03.01 | 33.01 |
| 1001   | Sun | 02.01 | 22.01 |
| 1002   | mon | 07.01 | 07.01 |
+--------+-----+-------+-------+
11
Salim

Obwohl Michaels Antwort die richtige ist, müssen Sie ein wenig mehr wissen, um den Upsert programmgesteuert durchzuführen:

Erstellen Sie zunächst Ihre Tabelle und geben Sie an, für welche Spalten ein eindeutiger Index erstellt werden soll:

CREATE TABLE IF NOT EXISTS Cell (
  cellId BIGINT UNSIGNED,
  attributeId BIGINT UNSIGNED,
  entityRowId BIGINT UNSIGNED,
  value DECIMAL(25,5),
  UNIQUE KEY `id_ce` (`cellId`,`entityRowId`)
)

Fügen Sie dann einige Werte ein:

INSERT INTO Cell VALUES( 1, 6, 199, 1.0 );

Versuchen Sie dasselbe noch einmal, und Sie erhalten einen Fehler beim Duplikatschlüssel, da cellId und entityRowId gleich sind:

INSERT INTO Cell VALUES( 1, 6, 199, 1.0 );

Doppelter Eintrag '1-199' für Schlüssel 'id_ce'

Deshalb verwenden wir den Befehl upsert:

INSERT INTO Cell ( cellId, attributeId, entityRowId, value, s, l, p, t )
VALUES( 1, 6, 199, 300.0 )
ON DUPLICATE KEY UPDATE `value` = `value` + VALUES(`value`)

Dieser Befehl nimmt den bereits vorhandenen Wert 1.0 als Wert an und führt einen value = value + 300.0 aus.

Selbst wenn der obige Befehl ausgeführt wird, enthält die Tabelle nur eine Zeile und der Wert ist 302.0.

5
Nav

Wenn Sie einen Wert für die PK-Spalte oder den eindeutigen Index für eine Spalte haben, die die Einheitlichkeit erfüllt, können Sie INSERT IGNORE, INSERT INTO ... ON DUPLICATE oder REPLACE verwenden.

Beispiel mit INSERT IGNORE

INSERT IGNORE INTO Table1
    (ID, serverID, channelID, channelROLE)
VALUES
    (....);

Beispiel mit INSERT INTO .. ON DUPLICATE KEY UPDATE

SET @id = 1,
    @serverId = 123545,
    @channelId = 512580,
    @channelRole = 'john';
INSERT INTO Table1
    (ID, serverID, channelID, channelROLE)
VALUES
    (@id, @serverId, @channelId, @channelRole)
ON DUPLICATE KEY UPDATE
    serverId = @serverId,
    channelId = @channelId,
    channelRole = @channelRole;

Beispiel mit Replace

REPLACE INTO table1
    (ID, serverID, channelID, channelROLE)
VALUES
    (...);
0
Simonare

Dies ist die Syntax für einen Upsert

INSERT INTO `{TABLE}` (`{PKCOLUMN}`, `{COLUMN}`) VALUES (:value)
ON DUPLICATE KEY UPDATE `{COLUMN}` = :value_dup';
0
relipse