【问题标题】:With MySQL, how do I insert into a table on condition that the value does not exist in another table?使用 MySQL,如何在另一个表中不存在该值的情况下插入一个表?
【发布时间】:2010-10-07 22:34:13
【问题描述】:

我有一个 MySQL 数据库,我想在一个表中插入一些值,假设我插入的特定值与不同表中的值不匹配。

这是一个简化/示例结构:

Table: invites
    id : int (auto-increment index)
    name : varchar
    message : varchar

Table: donotinvite
    name : varchar (index)

假设“名称”与“donotinvite”表中的任何“名称”都不匹配,是否可以通过单个语句将“名称”和“消息”对有条件地插入到“邀请”表中?

大概是这样的吧?

INSERT INTO invites
    SET name = 'joe', message = 'This is an invite'
WHERE NOT EXISTS 
    (SELECT name 
    FROM donotinvite
    WHERE name = 'joe')

【问题讨论】:

    标签: sql mysql insert conditional


    【解决方案1】:

    (我是 MSSQL 人,所以不确定是否都适合 MySQL)

    INSERT INTO invites
    (
        name, message
    )
    SELECT name = 'joe', message = 'This is an invite'
    WHERE NOT EXISTS 
        (SELECT *
        FROM donotinvite
        WHERE name = 'joe')
    

    在实践中,您可能会将所有名称/消息放在一个临时表中,然后执行以下操作:

    INSERT INTO invites
    (
        name, message
    )
    SELECT T.name, T.message
    FROM MyTempTable AS T
    WHERE NOT EXISTS 
    (
        SELECT *
        FROM donotinvite AS DNI
        WHERE DNI.name = T.name
    )
    

    【讨论】:

      【解决方案2】:

      这可以完成这项工作,但我不确定它是否会表现得那么好。它可能适用于您的应用程序:

      INSERT INTO invites(name, message) 
      SELECT p.name, "This is an invite" 
      FROM people AS p  
      WHERE p.name NOT IN (SELECT name FROM donotinvite);
      

      你有没有像people 这样的表格,一个你可以向其发送邀请的所有人的目录?

      【讨论】:

      • 希望 MySQL 足够聪明,可以将其归结为快速哈希/索引检查。或者,它可能很慢。 +1 无论如何
      • 是的,理想情况下,所有涉及的表都将在名称上进行良好索引。或者更好的是,您的生产应用可能会使用数字 ID 和外键,这会导致键更短,性能更好。
      • 实际上,所描述的表是在'name'字段上建立索引的,因此由MySQL来适当地优化查询。
      • 或者只是在原地创建带有文本字符串的 SQL - 即将 "FROM (SELECT @name AS name, @message AS message) a" 更改为 "FROM (SELECT 'Joe' AS name, 'This是一个邀请'AS 消息)a" - 虽然我似乎记得读过这样的嵌套子选择在 MySQL 中是不允许的??
      【解决方案3】:
      INSERT
      INTO invites (name, message)
      SELECT a.name, a.message
      FROM (SELECT @name AS name, @message AS message) a
      LEFT JOIN donotinvite d
      ON a.name = d.name
      WHERE d.name IS NULL
      

      【讨论】:

        【解决方案4】:

        这里是jonstjohn奇怪删除的答案的重新发布,我稍微修改了一下:

        INSERT INTO invites (name, message) 
            SELECT 'joe','This is an invite' 
            FROM donotinvite 
            WHERE name <> 'joe'
        

        编辑:这不是我想要的:)。

        【讨论】:

        • 我更喜欢 Quassnoi 的答案,它是经过适当参数化的(不像我的 :( ),因此“joe”不会以可能导致人为错误的方式复制
        • 这将邀请乔的次数与您不想邀请的非乔一样多。如果您的黑名单中有 20 个人,并且没有一个是 Joe,那么 Joe 将被邀请 20 次。如果乔在黑名单中,他只会被邀请 19 次。这就是你想要的吗?
        • 这也意味着如果黑名单为空,您将无法邀请任何人。
        • 嗯,Quassnoi 的回答看起来像 SQL Server 样式参数。这是一个 MySQL 数据库的问题,我的示例仅包含内联数据以简化问题。可以在实践中假设参数化。这是一个正交问题。
        • 啊,我明白了。谢谢。我希望他的原始答案留下了解释问题的评论,而不是被删除。
        【解决方案5】:
        INSERT INTO invites (name, message) 
        SELECT 'joe', 'This is an invite' FROM (SELECT 1) t 
        WHERE NOT EXISTS (SELECT * FROM donotinvite WHERE name = 'joe');
        

        【讨论】:

          猜你喜欢
          • 2011-08-26
          • 1970-01-01
          • 2014-07-14
          • 2012-09-17
          • 1970-01-01
          • 2023-01-11
          • 2014-04-29
          • 1970-01-01
          • 2023-03-29
          相关资源
          最近更新 更多