UPDATE `user` SET `mobile`='13888888888'
where `id`=1 AND 全 user 表 mobile 字段所有记录没有等于 13888888888
现在的实现方法需要分两步
1、先查有没有 mobile 记录值等于 13888888888 2、没有才 UPDATE
繁琐又有风险,怕在查询和 update 的间隔被插入 但是在表上面这个字段又不能做唯一限制 因为这个值初始插入是可以为空的
这个业务需求能用一条 sql 语句实现吗
1
Nicksxs 2017-04-27 11:56:30 +08:00
子查询咯
``` UPDATE `user` SET `mobile`='13888888888' where 1 > (select count(*) from (select * from user) a where `mobile` = '13888888888') and `id` = 1; ``` |
2
azh7138m 2017-04-27 12:01:10 +08:00 via Android
> 怕在查询和 update 的间隔被插入
呃,事务不是用来干这种事情的吗? |
3
msg7086 2017-04-27 13:25:57 +08:00
MySQL 的唯一索引支持 NULL 值啊……
|
4
abcdefghi OP 蟹蟹各位
根据 1 楼的方法又找到了一种方法 ``` UPDATE `zc_users` SET `mobile`='13888888888' where 1 > (select count(*) from (select * from zc_users) a where `mobile` = '13888888888') and `user_id` = 1; ``` ``` update zc_users set mobile='13888888888' where user_id=1 And not exists(select user_id from (select * from zc_users) a where mobile='13888888888'); ``` |
5
reus 2017-04-27 14:57:33 +08:00
可以把 mobile 另外存一个表,这样就可以用 unique 索引了。
或者换用 Postgresql,可以建 partial index:CREATE UNIQUE INDEX unique_mobile ON user (mobile) WHERE mobile IS NOT NULL。 |
6
geelaw 2017-04-27 18:02:45 +08:00 via iPhone
我的妈……你们没有用过 UNIQUE constraint 吗?
|
11
geelaw 2017-04-27 20:22:52 +08:00
@reus SQL Server 的 UNIQUE 可以不检查 NULL,这是 ANSI 标准 SQL: 92, SQL: 1999, SQL: 2003 要求的。此外 MySQL、PostgreSQL、SQLite、Oracle、Firebird 也都允许多重 NULL。
提问之前先查阅文档和自己试试。 |
12
geelaw 2017-04-27 20:29:58 +08:00
另外即使你使用的数据库引擎在 UNIQUE constraint 里面要求只有最多一个 NULL,鉴于手机号一般也是字符串存储(你不会想用数字,这是一个很恶心的事情),假设你用 char(50),你可以用 '@' + CONVERT(CHAR(40), NEWID()) 表示 NULL,然后你可以用一个 CHECK constraint 确保手机号具有正确的格式(要么是 11 位以 1 开头的数,要么是 '@' 开头)。
|
13
ryd994 2017-04-28 08:10:24 +08:00 via Android
说真的,这个其实没必要掐死
相信你这个也是用户输入的 两个用户同时操作,输入同一个手机号,而且间隔够小能出竞态,那明显是自己作 只能说活该丫的 加一个索引还影响性能 看你本身需求吧,如果手机号就有索引那加个 unique 几乎免费 |
14
woshixiaohao1982 2017-04-28 08:36:20 +08:00
主键 或者 唯一约束 unique index 都是可以的,实际上没有必要上事务,事务通常是针对有价值的数据,而且事务会产生锁,很烦人的,通常针对注册这种业务,unique index 就搞定了
|