SQLite 查询问题,以及事务的原子性

SQLite query problem, and atomicity of transactions

问题:我有两个 table(members1members2),它们只是用户名列表。我需要在 members1 中更改用户名,但前提是新用户名尚未出现在 table 中(换句话说,用户名在两个 table 中必须是唯一的)。

SQL 超出了我的舒适范围,但经过几个小时的谷歌搜索后,我提出了以下查询。我实际上正在使用 SQLite 的 C API,所以这只是一个测试 shell 脚本来检查语法。该脚本将旧名称更改为新名称,其中 </code> 是旧名称,<code> 是新名称:

#!/usr/bin/env bash
sqlite3 test.db <<EOF

update members1 set uname=
  case 
    exists(select 1 from members1 where uname='') or
    exists(select 1 from members2 where uname='')
  when 1 then ''
  else ''
  end
where uname='';

EOF

问题:

  1. 这似乎行得通,但它有意义吗?显得很啰嗦。有一个更好的方法吗?特别是,如果有名称冲突,是否真的需要更新 members1 将旧名称改回自己?
  2. 如果多个进程同时做同一件事,这有多安全?有没有可能进程A把'john'改成'jim',进程B同时把'jo'改成'jim',这样数据库里就出现了两次'jim' ?
  3. upper/lower-case 的协议究竟是什么?上面的代码运行没有问题,但是网络上的所有内容都是大写的。

谢谢。

如果我是你。我做了一个独一无二的 'umembers' table.

我用触发器填充了它。 (members1 和 members2 也是)你可以找出更新触发器。

CREATE TRIGGER IF NOT EXISTS members1trigger
BEFORE INSERT ON members1 
BEGIN
    INSERT INTO umembers VALUES(new.uname, other properties);
END;

那你的更新真快

#!/usr/bin/env bash
sqlite3 test.db <<EOF

update members1 set uname=
where uname='' and not exists (select 1 from umembers where uname= );

EOF
  1. 当然你应该对 umembers 创建唯一约束。 如果有并行更新,那么第二个可能会抛出异常。 但我认为索引锁定它,并且不会发生。

  2. 安全性表明使用不区分大小写的登录。

https://security.stackexchange.com/questions/241701/case-sensitive-logins