我有一张现有的表
id, name, user
15, bob, 1
25, alice, 2
30, ann, 1
55, bob, 2
66, candy, 1
我们希望用户1的名称记录现在设置为此字符串中的值:
"ann, candy, dave"
如果我这么做的话很简单
delete from table where user = 1
insert into table (name,user) values (ann,1), (candy,1), (dave,1)`
然后表格现在看起来像这样
id, name, user
25, alice, 2
55, bob, 2
67, ann, 1
68, candy, 1
69, dave, 1
即。新行已创建。我不想要新的身份,随着时间的推移,这会导致碎片和身份漏洞等等。 SQL中最有效的方法是将其减少到实际的2个所需操作:
从表中删除user = 1且name不在字符串" ann,candy,dave"中,以便表格为:
25, alice, 2
30, ann, 1
55,鲍勃,2
66,糖果,1
`
插入表user = 1,name =来自" ann,candy,dave"的任何值与name / user = 1不匹配,因此表格为:
25, alice, 2
30, ann, 1
55, bob, 2
66, candy, 1
67, dave, 1
答案 0 :(得分:1)
听起来你有一个列表,想要处理两次,一次用于删除,一次用于插入。将列表存储在临时表中并将其用于处理。
一路上,从user, name
上的唯一索引开始,以防止更新到表中:
create unique index idx_table_user_name on table(user, name);
这似乎是您数据的要求,因此请让数据库强制执行。然后处理代码如下:
create temporary table toprocess as (
select 1 as user, 'ann' as name union all
select 1, 'candy' union all
select 1, 'dave'
);
create index idx_toprocess_user_name on toprocess(user, name);
delete t
from table t
where t.user in (select p.user from toprocess p) and
not exists (select 1 from toprocess p where p.user = t.user and p.name = t.name);
insert into table(user, name)
select user, name
from toprocess
on duplicate key update user = values(user);
虽然这可能看起来有点复杂,但它允许您同时处理多个用户。并且,处理列表只输入一次,这减少了错误的范围。
答案 1 :(得分:0)
目前尚不清楚,但可能是您想要的:
delete from table where user = 1 and name not in('ann', 'candy', 'dave')
insert into table
select * from(select 'ann' as name
union all
select 'candy'
union all
select 'dave') t
where t.name not in(select name from table where user = 1)