sql >> Databasteknik >  >> RDS >> Mysql

villkorat av dubblettnyckeluppdatering

Du kan använda vanliga sql-konstruktioner i ON DUBLIKATNYCKEL syntax. Så för att göra villkorliga uppdateringar under en infogning kan du göra följande:

INSERT INTO tbl (hat, mittens, name) 
VALUES ('yellow','purple','jimmy')
ON DUPLICATE KEY UPDATE name = CASE WHEN name <> VALUES(name) 
                                    THEN VALUES(name) ELSE name END;

Detta kommer att ändra värdet till det du angav i insert-satsen när det skiljer sig från det som finns i raden och kommer att ställa in värdet till att vara vad det redan är om det inte har ändrats och kommer att resultera i att MySQL inte gör något för att bevara raden last_update tidsstämpel som Quassnoi påpekade.

Om du ville vara 100 % säker på att du inte litade på beteendet hos MySQL där den inte uppdaterar en rad om du ställer in ett värde till sig själv kan du göra följande för att tvinga tidsstämpeln:

INSERT INTO tbl (hat, mittens, name) 
VALUES ('yellow','purple','jimmy')
ON DUPLICATE KEY UPDATE name = CASE WHEN name <> VALUES(name) 
                                    THEN VALUES(name) ELSE name END
                      , last_update = CASE WHEN name <> VALUES(name) 
                                      THEN now() ELSE last_update END;

Detta kommer bara att uppdatera last_update till now() när namnet har ändrats annars kommer det att tala om för MySQL att behålla värdet för last_update .

I avsnittet ON DUPLICATE KEY i uttalandet kan du också hänvisa till kolumnerna i tabellen med deras namn och du kan få de värden som du angav i avsnittet Infoga satsvärden med hjälp av VÄRDEN(kolumnnamn) funktion.

Följande är en logg som visar att den senaste satsen fungerar även på 4.1 där de andra inte fungerar på grund av en bugg som fixades i version 5.0.

C:\mysql\bin>mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 4.1.22-community

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show databases;
+----------+
| Database |
+----------+
| mysql    |
| test     |
+----------+
2 rows in set (0.00 sec)

mysql> use test;
Database changed
mysql> show tables;
Empty set (0.00 sec)

mysql> CREATE TABLE `tbl` (
    -> `hat` varchar(11) default NULL,
    -> `mittens` varchar(11) default NULL,
    -> `name` varchar(11) default NULL,
    -> `stamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
    -> UNIQUE KEY `clothes` (`hat`,`mittens`)
    -> ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO tbl (hat,mittens,name) VALUES ('blue','green','george');
Query OK, 1 row affected (0.00 sec)

mysql> select * from tbl;
+------+---------+--------+---------------------+
| hat  | mittens | name   | stamp               |
+------+---------+--------+---------------------+
| blue | green   | george | 2009-06-27 12:15:16 |
+------+---------+--------+---------------------+
1 row in set (0.00 sec)

mysql> INSERT INTO tbl (hat,mittens,name) VALUES ('blue','green','george') ON DUPLICATE KEY UPDATE name='george';
Query OK, 2 rows affected (0.00 sec)

mysql> select * from tbl;
+------+---------+--------+---------------------+
| hat  | mittens | name   | stamp               |
+------+---------+--------+---------------------+
| blue | green   | george | 2009-06-27 12:15:30 |
+------+---------+--------+---------------------+
1 row in set (0.00 sec)

mysql> INSERT INTO tbl (hat, mittens, name) VALUES ('blue','green','george') ON DUPLICATE KEY UPDATE name=CASE WHEN name <> VALUES(name) THEN VALUES(name) ELSE name END;
Query OK, 2 rows affected (0.00 sec)

mysql> select * from tbl;
+------+---------+--------+---------------------+
| hat  | mittens | name   | stamp               |
+------+---------+--------+---------------------+
| blue | green   | george | 2009-06-27 12:15:42 |
+------+---------+--------+---------------------+
1 row in set (0.00 sec)

mysql> INSERT INTO tbl (hat,mittens,name) VALUES ('blue','green','george') ON DUPLICATE KEY UPDATE name = CASE WHEN name <> VALUES(name) THEN VALUES(name) ELSE name END, stamp = CASE WHEN name <> VALUES(name) THEN now() ELSE stamp END;
Query OK, 2 rows affected (0.00 sec)

mysql> select * from tbl;
+------+---------+--------+---------------------+
| hat  | mittens | name   | stamp               |
+------+---------+--------+---------------------+
| blue | green   | george | 2009-06-27 12:15:42 |
+------+---------+--------+---------------------+
1 row in set (0.00 sec)

mysql>

Kontakta mig om du har några frågor.

HTH,

-Dipin



  1. Patchhistoriktabeller i Oracle Apps (11i/R12.1/R12.2)

  2. MySQL-syntaxfel för lagrad procedur efter BEGIN

  3. Kan inte lagra UTF8-tecken i MySQL

  4. Räkna förekomsten av DISTINCT-värden