我正在努力让所有用户拥有相同的项目,因为我正在对我的应用进行实验,并需要对展平数据进行实验控制。
我在上次尝试中使用了以下SQL语句:
insert into has (email,id,qty,price,item_info,image)
select 'b@localhost.com',id,qty,price,item_info,image
from
(
select * from has
where email != 'b@localhost.com'
) as o
where o.id not in
(
select id from has
where email = 'b@localhost.com'
);
这应该添加所有项目' b@localhost.com'没有,但其他用户确实拥有,以及' b@localhost.com' s库存。 ('有'表)
但是,我收到以下错误:
语句已中止,因为它会在唯一或主键约束或唯一索引中导致重复键值
我理解这个错误意味着什么,但我不明白它为什么会发生。我的声明会插入电子邮件已经存在的所有记录,因此不应该有任何重复的ID /电子邮件对。
数据库结构如下所示,圆圈是属性,方块是表格,菱形是关系集。 HAS表是在USER_ACCOUNT和ITEM上设置的关系,其中主键分别是email和id。
答案 0 :(得分:0)
请尝试以下方法......
INSERT INTO has ( email,
id,
qty,
price,
item_info,
image )
SELECT a.email,
b.id,
a.qty,
a.price,
a.item_info,
a.image
FROM has a
CROSS JOIN has b
JOIN
(
SELECT email,
id
FROM has
) c ON a.email = c.email AND
b.id <> c.id;
CROSS JOIN
将每行has
的副本附加到has
的每一行。有关CROSS JOIN
的更多信息,请参阅http://www.w3resource.com/sql/joins/cross-join.php。
结果数据集的每一行将包含两个id
字段,两个email
字段,两个qty
字段等。通过为每个has
实例提供一个别名,我们创建字段a.id
,b.id
,a.email
等
然后,我们将“旧”email
地址和“新”id
的每个组合与现有email
/ id
组合列表进行比较,并插入旧值新的id
将旧的has
替换为CROSS JOIN
如果您有任何问题或意见,请随时发表评论。
进一步阅读
http://www.w3resource.com/sql/joins/cross-join.php了解有关WHERE
https://www.w3schools.com/sql/sql_in.asp了解有关IN
的{{1}}运营商
https://www.w3schools.com/sql/sql_groupby.asp了解有关GROUP BY
答案 1 :(得分:0)
我认为这里的问题不是代码试图插入已经存在的东西,而是它试图用相同的PK插入多个东西。代替回复我的评论,这是解决问题的一种方法:
INSERT INTO has (email,id,qty,price,item_info,image)
SELECT
'b@localhost.com',
source.id,
source.qty,
source.price,
source.item_info,
source.image
FROM
(
SELECT email, id, qyt, price, item_info, image FROM has
) as source
JOIN
(
SELECT min(email) as min_email, id FROM has GROUP BY by id)
) as filter ON
filter.min_email = source.email
WHERE
source.id not in
(
SELECT id from has WHERE email = 'b@localhost.com'
);
与原始代码的主要区别在于我对子查询的额外加入,我将其别名为filter
。这限制了您从每个has
email
插入id
个详细信息。还有其他方法可以做同样的事情,但我认为这对于得到德比的支持是一个安全的选择。
我从WHERE
子查询中删除了source
子句,因为它是由最终WHERE
处理的。