我正在尝试插入一个新行,但如果该键已存在,我想仅在表中的某个其他值不同时更新该行.这可能在mysql查询/语句中吗?
我的表由以下列组成:hat,mittens,name,last_update
帽子+手套构成独特的指数(比如"帽子"和"手套"的颜色是颜色)
我们假设这已经在表中:
1. hat=blue mittens=green name=george last_update=tuesday 2. hat=red mittens=green name=bill last_update=monday
在新密钥上,我想像往常一样插入.在重复键上,我想仅在名称更改时进行更新,否则忽略.原因是我想保留last_update值(timestamp).
hat=yellow mittens=purple name=jimmy -- insert new row hat=blue mittens=green name=george -- ignore hat=blue mittens=green name=betty -- update row
这是否可以不使用单独的语句来首先查找现有行,比较值然后在必要时发出更新?如果是这样,语法是什么?
谢谢你的回复.我尝试了所有这些.确实,只使用一个简单的UPDATE语句
update tbl set name='george' where hat='blue' and mittens='green'
Run Code Online (Sandbox Code Playgroud)
导致没有更新行.但是,使用其中之一
INSERT INTO tbl (hat,mittens,name) VALUES ('blue','green','george') ON DUPLICATE KEY UPDATE name='george';
Run Code Online (Sandbox Code Playgroud)
要么
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;
Run Code Online (Sandbox Code Playgroud)
不知何故导致行被更新(并且时间戳已更改).
FWIW,这是我正在使用的表格:
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
Run Code Online (Sandbox Code Playgroud)
MySQL是版本4.1.22(也许这很重要?)同样,我对所有回复表示赞赏.
Dip*_*pin 17
您可以在ON DUPLICATE KEY语法中使用普通的sql构造.因此,为了在插入期间执行条件更新,您可以执行以下操作:
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;
Run Code Online (Sandbox Code Playgroud)
这会将值更改为您提供给insert语句的值,当它与行中的内容不同时,如果它没有更改,则将值设置为已经存在的值,并且将导致MySQL不对行保留任何内容Quassnoi指出的last_update时间戳.
如果您想100%确定您不依赖于MySQL的行为,如果您为自己设置了值,则不会更新行,您可以执行以下操作来强制使用时间戳:
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;
Run Code Online (Sandbox Code Playgroud)
这将只更新last_update到now()时,名称已更改否则它会告诉MySQL保留的价值last_update.
此外,在语句的ON DUPLICATE KEY部分中,您可以通过名称引用表中的列,并且可以使用VALUES(column_name)函数获取您提供给insert语句值部分的值.
以下是一个日志,显示提供的最后一个语句甚至可以在4.1中工作,其他语句由于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>
Run Code Online (Sandbox Code Playgroud)
如果您有任何疑问,请告诉我.
HTH,
-蘸