代码之家  ›  专栏  ›  技术社区  ›  Captain Stack

如果没有具有相同id和url的行(两列值),请插入行

  •  -1
  • Captain Stack  · 技术社区  · 7 年前

    我想写一个SQL语句,如果数据库中还没有一行,那么它会向数据库中插入一个新行。行的唯一标识符是id和url。假设表模式如下所示:

    LinkClicks: (id, url, clicks)
    

    现在让我们假设有一行包含参数化SQL插入。我正在尝试这样做:

    INSERT (id, url, clicks) 
    INTO LinkClicks Values(@id, @url, @clicks) 
    WHERE @url NOT IN 
        (SELECT url FROM LinkClicks WHERE id=@id);
    
    3 回复  |  直到 7 年前
        1
  •  1
  •   Gordon Linoff    7 年前

    INSERT INTO LinkClicks(id, url, clicks)
        SELECT id, url, clicks
        FROM (SELECT @id as id, @url as url, @clicks as clicks) t
        WHERE t.url NOT IN (SELECT url FROM LinkClicks WHERE id = @id);
    
        2
  •  1
  •   Tim Biegeleisen    7 年前

    您可以在 id url 柱:

    ALTER TABLE LinkClicks ADD UNIQUE u_idx (id, url);
    

    有了这个约束,尝试插入一个 身份证件 url 已经出现的值组合将在数据库级别失败。

    这可能比您尝试的查询更好,因为它保证MySQL将拒绝重复的插入尝试。也可以使用查询来实现这一效果,但稍后,使用您的代码库的其他人可能会忘记这一点。

        3
  •  0
  •   russ    7 年前

    事实上,您应该采纳Tim的建议,将唯一索引放在表中,但在这样做的过程中,您需要一种故障安全的方法来确保您不会试图将重复项(id和url)放入表中(否则会加载大量的红色消息)。这样似乎可以:

    DROP TABLE LINKCLICKS
    DROP TABLE LINKCLICKS1
    
    CREATE TABLE LINKCLICKS
    (
    [ID] INT,
    [URL] CHAR(11),
    CLICKS BIGINT
    )
    GO
    INSERT INTO LINKCLICKS VALUES (1001,'www.abc.com',40000)
    INSERT INTO LINKCLICKS VALUES (1002,'www.def.com',40000)
    INSERT INTO LINKCLICKS VALUES (1003,'www.ghi.com',40000)
    GO
    
    CREATE TABLE LINKCLICKS1
    (
    [ID] INT,
    [URL] CHAR(11),
    CLICKS BIGINT
    )
    GO
    INSERT INTO LINKCLICKS1 VALUES (1001,'www.abc.com',40000)
    INSERT INTO LINKCLICKS1 VALUES (1003,'www.def.com',40000)
    INSERT INTO LINKCLICKS1 VALUES (1004,'www.ghi.com',40000)
    GO
    
    WITH CTE1 AS
    (
    SELECT *,'d' AS [Source] FROM LINKCLICKS
    UNION ALL
    SELECT *,'s' AS [Source] FROM LINKCLICKS1
    )
    ,
    CTE2 AS
    (
    SELECT ID,[URL] FROM CTE1 GROUP BY ID,[URL] HAVING COUNT(ID) =1 AND COUNT([URL]) =1
    )
    INSERT INTO LINKCLICKS
    SELECT ID,[URL],CLICKS 
    FROM CTE1 
    WHERE [Source] <> 'd' 
    AND 
    (
    ID IN (SELECT ID FROM CTE2) AND [URL] IN (SELECT [URL] FROM CTE2)
    )
    
    SELECT * FROM LINKCLICKS ORDER BY [ID],URL
    GO
    

    INSERT语句仅插入ID和URL组合与目标表中已有行不同的行。它很乐意插入ID相同但URL不同或ID不同但URL相同的行。

    我唯一的保留意见是源表中的“重复”问题(在本例中为LINKCLICKS1)。如果源表中存在重复项,则不会将其插入到目标表中。这将破坏查询对象。

    答案是,如果源表中存在重复项或任何重复风险,则应在运行此操作之前对源表应用“重复数据消除代码”。

    如果您需要任何重复数据消除代码,请在下面发表评论。