【问题标题】:Insert multiple values and ignore duplicates on not key field插入多个值并忽略非关键字段上的重复项
【发布时间】:2015-09-06 11:35:45
【问题描述】:

如果我想在包含字段的表中插入多个值:

ID | name | content  
---+------+------------------
 1 | john | some content  
 2 | bob  | another content

现在我想插入多个值:

INSERT INTO persons (name,content)
VALUES
("Foo","meh"),
("Moo","beh"),
("bob","huh"),
("dude","haha")

结果应该是:

ID | name | content  
---+------+------------------
 1 | john | some content  
 2 | bob  | another content
 3 | Foo  | meh
 4 | Moo  | beh
 5 | dude | haha

查询忽略了重复的名字,所以“bob”|“huh”没有被插入,名字不是关键字段。我在任何地方都找不到它的语法,我知道它应该很简单。

我正在使用 MySQL 数据库。

【问题讨论】:

    标签: mysql sql sql-insert


    【解决方案1】:

    使用LEFT JOIN判断记录是否已经在表中

    SqlFiddleDemo

    CREATE TABLE persons(ID INT AUTO_INCREMENT PRIMARY KEY,
          name VARCHAR(100),
          content VARCHAR(100));
    
    INSERT INTO persons (name, content)
    VALUES ('john', 'some content'), ('bob', 'another content');
    
    INSERT INTO persons (name,content)
    SELECT t.name, t.content
    FROM
    (
      SELECT "Foo" AS name,"meh" AS content
      UNION ALL
      SELECT "Moo","beh"
      UNION ALL
      SELECT "bob","huh"
      UNION ALL
      SELECT "dude","haha"
    ) AS t
    LEFT JOIN persons p
    ON p.name = t.name
    WHERE p.id IS NULL;
    
    SELECT *
    FROM persons;
    

    同样使用NOT EXISTS

    INSERT INTO persons (name,content)
    SELECT t.name, t.content
    FROM
    (
      SELECT "Foo" AS name,"meh" AS content
      UNION ALL
      SELECT "Moo","beh"
      UNION ALL
      SELECT "bob","huh"
      UNION ALL
      SELECT "dude","haha"
    ) AS t
    WHERE NOT EXISTS 
         (SELECT 1 FROM persons p WHERE p.name = t.name)
    

    编辑:

    添加UNIQUE KEY 并使用INSERT IGNORE INTO

    SqlFiddleDemo

    CREATE TABLE persons(ID INT AUTO_INCREMENT PRIMARY KEY,
          name VARCHAR(100) UNIQUE KEY,
          content VARCHAR(100));
    
    INSERT INTO persons (name, content)
    VALUES ('john', 'some content'), ('bob', 'another content');
    
    
    INSERT IGNORE INTO persons (name,content)
    VALUES
    ("Foo","meh"),
    ("Moo","beh"),
    ("bob","huh"),
    ("dude","haha");
    
    SELECT *
    FROM persons;
    

    【讨论】:

    • 我还建议添加一个 UNIQUE INDEX/KEY 以防止表中有多个同名的人。
    • @lad2025 和 uri 非常感谢。我使用了 lad2025 的第二个答案,效果很好,如果你真的不想碰你的表格结构,效果很好,但更好的方法是在这个字段上设置 UNIQUE KEY 正如你们所说的那样,对于未来我要去使用它。非常感谢!
    【解决方案2】:

    这是在 tsql 中,但您可以使用具有表类型(名称和内容作为列)作为参数的合并语句创建存储过程,以便在插入之前检查名称。如果名称匹配,则不会插入,但如果不匹配,则会插入新记录。

    BEGIN TRANSACTION
    
    -- setup tables for merge
    MERGE dbo.persons AS t
    
    USING @NameContentTable AS s
        ON t.name = s.name      
    
    -- do nothing if matched
    
    -- insert if not matched
    WHEN NOT MATCHED THEN   
        INSERT (name, 
                content)
        VALUES (s.name,
                s.content);
    
    -- error handling
    IF @@ERROR <> 0 
    BEGIN
        SELECT 'Unexpected error occurred'
        ROLLBACK TRAN 
        RETURN -1
    END
    
    COMMIT TRANSACTION
    

    【讨论】:

    • 谢谢@hines,我正在使用 mysql,所以我假设 tsql 你的回答很好:),祝你有美好的一天!
    猜你喜欢
    • 1970-01-01
    • 2020-05-19
    • 2017-06-06
    • 1970-01-01
    • 1970-01-01
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    相关资源
    最近更新 更多