sql - SQLite 查询问题,以及事务的原子性
问题描述
问题:我有两个表(members1
和members2
),它们只是用户名列表。我需要更改 中的用户名members1
,但前提是新用户名尚未出现在任一表中(换句话说,用户名在两个表中必须是唯一的)。
SQL 超出了我的舒适区,但经过几个小时的谷歌搜索后,我想出了下面的查询。我实际上使用的是 SQLite 的 C API,所以这只是一个用于检查语法的测试 shell 脚本。该脚本将旧名称更改为新名称,其中$1
旧名称为旧名称,$2
新名称为:
#!/usr/bin/env bash
sqlite3 test.db <<EOF
update members1 set uname=
case
exists(select 1 from members1 where uname='$2') or
exists(select 1 from members2 where uname='$2')
when 1 then '$1'
else '$2'
end
where uname='$1';
EOF
问题:
- 这似乎有效,但它有意义吗?似乎很啰嗦。有一个更好的方法吗?特别是如果出现名称冲突,是否真的需要更新
members1
才能将旧名称改回自己? - 如果多个进程同时做同样的事情,这有多安全?进程 A 是否可以将 'john' 更改为 'jim',而进程 B 同时将 'jo' 更改为 'jim',从而使 'jim' 在数据库中出现两次?
- 实际上大写/小写的协议是什么?上面的代码运行没有问题,但网络上的所有内容都是大写的。
谢谢。
解决方案
如果我是你。我制作了一个独特的“umembers”表。
我用触发器填充它。(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=$2
where uname='$1' and not exists (select 1 from umembers where uname= $2);
EOF
当然,您应该在 umembers 上创建唯一约束。如果有并行更新,那么第二个可能会抛出异常。但我认为索引锁定它,并且不会发生。
安全性表示使用不区分大小写的登录。
https://security.stackexchange.com/questions/241701/case-sensitive-logins
推荐阅读
- wordpress - 创建 api 时无法获取图像 url acf
- neo4j - Neo4j 中没有名字的节点
- c# - 使用 C# 驱动程序以类型化方式更新 MongoDB 中的字典
- flutter - Flutter:如何将焦点放在自动完成字段上?
- heroku - Heroku Postgres 错误:语言 c 的权限被拒绝
- java - 确保 Android Studio 构建不依赖于物理设备的任何缓存版本
- amazon-web-services - AWS 云存储针对文件检索进行了优化
- r - 列出目录中的图像,但排除子目录
- reactjs - Reactjs 不允许 dir="rtl" 显示文本 RTL
- javascript - 在对服务器的获取请求完成后,如何循环遍历数组并将信息添加到 firebase?