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

Insert row if there isn't already a row with the same id and url (two column values)

我想编写一个 SQL 语句,在数据库中没有一行的情况下向数据库中插入一个新行。一行的唯一标识符是id和url。假设 table 架构如下所示:

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

我想你想要这样的东西:

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

您可以在 idurl 列上添加唯一索引:

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

有了这个约束,尝试插入一条已经出现 idurl 值组合的记录将在数据库级别失败。

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

事实上,您应该采纳 Tim 的建议,将唯一索引放在 table 上,但在这样做时,您需要一种故障安全的方法来确保您不会尝试放置重复项(id 和 url) 到 table 中(否则会出现大量红色墨水消息)。这样看来还可以:

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 组合与目标 table 中已有行不同的那些行。它非常乐意插入 ID 相同但 URL 不同或 ID 不同但 URL 相同的行。

我唯一的保留意见是来源 table 中 'dupes' 的问题(在本例中为 LINKCLICKS1)。如果源 table 中有重复项,其中 none 将被插入到目标 table 中。这将打败查询对象。

答案是,如果您有重复项,或者在源 table 中有任何重复的风险,那么您应该在 [=34] 之前将 'de-dupe code' 应用到源 table =] 这个.

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