如何使表中的所有行与1字段的异常相同?

时间:2017-04-17 02:20:23

标签: sql derby

我正在努力让所有用户拥有相同的项目,因为我正在对我的应用进行实验,并需要对展平数据进行实验控制。

我在上次尝试中使用了以下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。 enter image description here

2 个答案:

答案 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.idb.ida.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处理的。