【问题标题】:Using MySQL IGNORE on one column under certain conditions在特定条件下在一列上使用 MySQL IGNORE
【发布时间】:2013-07-12 06:14:51
【问题描述】:

我想将 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. 电话号码可能为空,但带有电子邮件条目,这可能会破坏独特的模式

问题说明

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

【问题讨论】:

  • 我有点困惑——运行 700 个查询或 1400 个查询的选项——为什么?您可以将所有结果放入一个表中,然后在您的帐户表中运行一条插入语句以满足您的需求。
  • 如何确保表中每个 account_id 没有重复项?
  • 您的数据来自哪里?您是否有一个文本文件正在尝试使用 700 个插入语句运行?或者这 700 行是否已经在一个表中,而您只是想将它们的部分/全部/子集放到帐户表中?
  • 我从 Gmail 导入并将我的数据放在一个数组中。
  • 恕我直言,您必须使用相关示例数据来说明您的问题,其中每个 account_id 的电子邮件和电话号码中的重复项和所需的输出。这可能会帮助您更快地得到答案。现在还不清楚如果有重复的电子邮件但每个 account_id 有不同的电话号码,你想做什么,反之亦然。什么应该去目标表?

标签: php mysql sql insert


【解决方案1】:

所以听起来您正在使用脚本语言(php 似乎在 mysql 中很流行)来存储来自 gmail 的联系人数组?

如果是这样,如果帐户 ID 不存在于表中,则此插入语句将插入记录 - 这使用带有 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

编辑:

假设我了解 cmets,那么只需添加到外连接:

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

这应确保没有重新插入具有匹配电话或电子邮件的帐户。

【讨论】:

  • 非常感谢您的反馈。如何使用查询执行多行插入
  • @OguguaBelonwu -- 我的印象是你循环遍历数组中的 700 条记录,不是吗?只需将上面的值替换为准备好的语句即可。
  • 请举一个有2条记录的例子,让我更清楚地了解如何连接准备好的语句
  • 请检查我的更新。 account_id 在表中不是唯一的;而对于列表中的每个 account_id,每个电子邮件/电话都必须是唯一的。
【解决方案2】:

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

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

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

【讨论】:

  • 为了进一步解决这个问题,不能使电子邮件/电话唯一,因为该列应该支持重复的电子邮件,但对于表中的每个 account_id 都是唯一的。
  • @OguguaBelonwu - 所以帐户 ID 不是唯一的。如果是这样的话,你是对的,这个解决方案将无济于事。看看另一篇文章——看起来对这种情况很有用。最好的问候。
  • 不,account_id 也不是唯一的,因为每个帐户可以有多个记录
【解决方案3】:
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)中,即根据需要删除重复项。

【讨论】:

    【解决方案4】:

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

    • 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);
    

    这两个索引可能同时存在于您的表中。两者都可能引发“重复键违规”错误,并会触发插入的 IGNOREON DUPLICATE 子句。


    话虽如此,您的结构存在问题。您将复制与客户有业务往来的每个account_id 的客户详细信息。

    您应该有一个 customers 表,其中包含您所有客户的联系方式(仅此而已),另一个 accounts 表——如果我理解正确的话,你的“办公室”——最后是一个模型的关系表n-n relationshipcustomersaccounts 之间:

    CREATE 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)
    );
    

    【讨论】:

    • +1 。 . .尽管我从未见过在这种情况下使用“单一性”。你考虑过“独特性”吗?
    • 检查了英语中“unicity”的定义(与法语中的“unicité”相比),我的措辞确实很有趣:)谢谢!
    【解决方案5】:

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

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

    添加唯一(account_id,电子邮件)

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

    添加唯一(account_id,电话)

    (除此之外:一般建议是您通常不会在一个表上拥有多个唯一性,因为它可能会让人感到困惑和混乱,但这可能是您需要的,这很好 - 只要您能处理逻辑)

    【讨论】:

    • +1 用于提及 NULL 值被 UNIQUE 约束忽略。 NULL 等于没有,甚至不等于NULL(试试SELECT NULL = NULL;)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    相关资源
    最近更新 更多