在某些条件下在一列上使用MySQL IGNORE

时间:2013-07-14 03:44:37

标签: php mysql sql insert

我想将Gmail中的记录导入到表格中,而且每个帐户都不需要重复记录。

说明

我有一个名为list的表,其定义如下:

id int(11),
account_id int(11),
email varchar(255),
phone varchar(30),
primary key(id),
FOREIGN KEY (account_id) REFERENCES accounts (id)

此表包含不同帐户的记录,并且电子邮件可被视为对两个或多个帐户有效。这意味着电子邮件可以在表格中重复,但每个account_id只能出现一次。

我从Gmail导入了我的联系人(超过700个联系人,其他用户可能拥有更多联系人)。

挑战:

我可以选择运行两个查询(一个用于检查是否存在电子邮件或电话,第二个用于插入记录),每个记录在我的情况下是1,400个SQL查询,以便我插入所有导入的记录,确保没有列表中每个account_id的重复项。

我查看了MySQL IGNORE和类似的关键字,例如ON DUPLICATE KEY UPDATE,但它们似乎在这种情况下无效,因为我无法使电子邮件和电话列唯一,因为它们可能包含重复的内容。

插入这700条记录的最佳方法是什么,确保每个account_id不会重复电子邮件和电话,而不必运行1,400个查询?

问题更新:

我不认为INSERT IGNORE可以在此处使用以下原因:

  1. 我无法制作电子邮件和手机专栏
  2. 电话号码可能为空但有电子邮件条目,这可能会破坏独特的模式
  3. 问题说明

    我有两个办公室使用该表来存储他们的客户记录。有人可以成为两个办事处的客户。这意味着他的记录可以在表格中出现两次,但对于表格中的每个account_id只能出现一次。 现在的挑战是在表格中插入几条记录,确保每条account_id都不会重复记录。

5 个答案:

答案 0 :(得分:5)

你想要实现的目标对我来说不是很清楚,但它看起来非常像你只需要添加一些两列独特的约束。

  • 对于给定email的人来说account_id必须是唯一的:
ALTER TABLE your_table ADD UNIQUE (account_id, email);
  • phone number account_id必须是唯一的ALTER TABLE your_table ADD UNIQUE (account_id, phone);
IGNORE

两个索引可能同时存在于您的表中。可能会引发“重复键违规”错误,并会触发您插入的ON DUPLICATEaccount_id条款。


话虽如此,您的结构中存在问题。您即将重复与客户合作的每个customers客户的详细信息。

你应该有一个accounts表,其中包含所有客户的联系方式(仅限于此),另一个customers表 - 您的“办公室”,如果我理解正确的话 - 最后一个关系表,用于对accountsCREATE TABLE customers_accounts ( customer_id INT NOT NULL, account_id INT NOT NULL, PRIMARY KEY (customer_id, account_id), FOREIGN KEY (customer_id) REFERENCES customers(id) FOREIGN KEY (account_id) REFERENCES accounts(id) ); 之间的n-n relationship进行建模:

{{1}}

答案 1 :(得分:2)

您有答案:使用“INSERT IGNORE”,但您可能没有做的是添加复合唯一索引(上面提到的RamdomSeed),和/或将空白字段设置为NULL。

1)使用帐户ID创建综合索引。这意味着该电子邮件必须对该用户是唯一的。

ADD UNIQUE(account_id,email)

2)关于手机“可能是空白”,空白时将其设置为NULL。唯一索引忽略NULLS。 (一个小问题,但可能在这里对你有利,为什么会这样。你也可以添加

ADD UNIQUE(account_id,phone)

(旁白:一般的建议是你通常不会在桌子上有多个唯一身份因为它可能会让人感到困惑和混乱,但它可能就是你所需要的而且没关系 - 只要你能处理逻辑)< / p>

答案 2 :(得分:0)

所以听起来你正在使用脚本语言(php似乎很受mysql欢迎)来存储来自gmail的联系人数组?

如果是这样,如果表中不存在帐户ID,则此insert语句将插入记录 - 这使用带有Null检查的外部联接,但您也可以使用Not In或Not Exists:

Insert Into YourTable (Id, AccountId, Email, Phone)
Select t.Id, t.AccountId, t.Email, t.Phone
From (Select 1 Id, 1 AccountId, 'someemail' Email, 'somephone' Phone) t
    Left Join YourTable t2 On t.AccountId = t2.AccountId
Where t2.AccountId Is Null

编辑:

假设我理解了这些评论,那么只需添加到外部加入:

Insert Into YourTable (Id, AccountId, Email, Phone)
Select t.Id, t.AccountId, t.Email, t.Phone
From (Select 1 Id, 1 AccountId, 'someemail' Email, 'somephone' Phone) t
    Left Join YourTable t2 On t.AccountId = t2.AccountId
        And (t.email = t2.email Or t.phone = t2.phone)
Where t2.AccountId Is Null

如果他们有匹配的电话或电子邮件,这应该确保不会重新插入帐户。

答案 3 :(得分:0)

似乎您可以使用INSERT IGNORE,假设AccountId是您的唯一标识符:

INSERT IGNORE INTO table
SET field = someValue,
    anotherfield = someothervalue

但是,如果您可以使用多个电子邮件拥有相同的帐户,那么这可能不是您要查找的内容。

答案 4 :(得分:0)

Insert Into YourTable (Id, Account_Id, Email, Phone)
Select a.id, a.Account_Id, a.Email, a.Phone
From (Select t.id, t.Account_Id,  t.Email,  t.Phone from t
   group by account_id,email,phone )a;

建议将记录导入临时表(t)。然后只将记录过滤到另一个表(yourtable),即根据需要删除副本。