我想写一个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);
答案 0 :(得分:1)
我想你想要这样的东西:
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);
答案 1 :(得分:1)
您可以在id
和url
列添加唯一索引:
ALTER TABLE LinkClicks ADD UNIQUE u_idx (id, url);
有了这个约束,尝试插入已经出现id
和url
值组合的记录将在数据库级别失败。
这可能比您正在尝试的查询更可取,因为它可以保证MySQL将拒绝重复的插入尝试。查询也可以用于此效果,但稍后可能使用您的代码库的其他人可能会忘记这一点。
答案 2 :(得分:0)
事实上你应该接受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,其中ID相同但URL不同或ID不同但URL相同。
我唯一的保留是源表中的'dupes'问题(在本例中为LINKCLICKS1)。如果源表中存在重复项,则它们都不会插入到目标表中。这将打败查询的对象。
答案是,如果您在源表中有重复项或任何重复风险,那么您应该在运行此表之前将“重复数据删除代码”应用于源表。
如果您需要任何重复数据删除代码,请在下方发表评论。