微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql – 有条件的重复键更新

我正在尝试插入一个新行,但是如果密钥已经存在,那么如果表中某个其他值不同,我只想更新该行.这是否可能在 mysql查询/语句中?

我的桌子由以下列组成:帽子,手套,名称,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'

导致没有更新行.但是,使用它们之一

INSERT INTO tbl (hat,mittens,name) VALUES ('blue','green','george') ON DUPLICATE KEY UPDATE name='george';

要么

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

以某种方式导致行被更新(并且时间戳更改).

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

MysqL是4.1.22版本(也许这很重要?)
再次感谢所有答复.

解决方法

您可以使用 ON DUPLICATE KEY语法中的普通sql结构.因此,为了在插入期间进行条件更新,您可以执行以下操作:
INSERT INTO tbl (hat,name) 
VALUES ('yellow','purple','jimmy')
ON DUPLICATE KEY UPDATE name = CASE WHEN name <> VALUES(name) 
                                    THEN VALUES(name) ELSE name END;

这将会将值提供给insert语句,当它与行中的内容不同时,将其值设置为已经是没有更改的值,并且将导致MysqL不对行进行任何保留Quassnoi指出的last_update时间戳记.

如果您希望100%确定您不依赖MysqL的行为,如果您将值设置为自身,则不会更新行,您可以执行以下操作来强制时间戳:

INSERT INTO tbl (hat,'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;

这将只会在名称更改时将update_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,'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,'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,'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,'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>

如果您有任何问题,请告诉我们.

HTH,

-Dipin

原文地址:https://www.jb51.cc/mssql/79140.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐