Did*_*evy 148 sql-server insert-update
我有一个Competitions
结果表,一方面保存团队成员的名字和他们的排名.
另一方面,我需要维护一个独特的竞争对手名称表:
CREATE TABLE Competitors (cName nvarchar(64) primary key)
Run Code Online (Sandbox Code Playgroud)
现在我在第一个表中有大约200,000个结果,当竞争对手表空时,我可以执行此操作:
INSERT INTO Competitors SELECT DISTINCT Name FROM CompResults
Run Code Online (Sandbox Code Playgroud)
查询只需要大约5秒钟就可以插入大约11,000个名称.
到目前为止,这不是一个关键应用程序,因此我可以考虑每月截断一次竞争对手表,当我收到大约10,000行的新竞争结果时.
但是,当新的和现有的竞争对手增加新的结果时,最佳做法是什么?我不想截断现有的竞争对手表
我只需要为新的竞争对手执行INSERT语句,如果它们存在则不执行任何操作.
gbn*_*gbn 204
在语义上你要求"插入竞争对手尚不存在的地方":
INSERT Competitors (cName)
SELECT DISTINCT Name
FROM CompResults cr
WHERE
NOT EXISTS (SELECT * FROM Competitors c
WHERE cr.Name = c.cName)
Run Code Online (Sandbox Code Playgroud)
pco*_*fre 53
另一个选择是将您的结果表与您现有的竞争对手表连接起来,并通过过滤与联接中不匹配的不同记录来查找新的竞争对手:
INSERT Competitors (cName)
SELECT DISTINCT cr.Name
FROM CompResults cr left join
Competitors c on cr.Name = c.cName
where c.cName is null
Run Code Online (Sandbox Code Playgroud)
新语法MERGE还提供了一种紧凑,优雅和高效的方法:
MERGE INTO Competitors AS Target
USING (SELECT DISTINCT Name FROM CompResults) AS Source ON Target.Name = Source.Name
WHEN NOT MATCHED THEN
INSERT (Name) VALUES (Source.Name);
Run Code Online (Sandbox Code Playgroud)
Tra*_*lie 32
不知道为什么其他人还没有说过这个;
NORMALIZE.
你有一张比赛模型表吗?比赛是由竞争对手组成的?您需要在一个或多个比赛中列出不同的参赛者名单......
你应该有以下表格.....
CREATE TABLE Competitor (
[CompetitorID] INT IDENTITY(1,1) PRIMARY KEY
, [CompetitorName] NVARCHAR(255)
)
CREATE TABLE Competition (
[CompetitionID] INT IDENTITY(1,1) PRIMARY KEY
, [CompetitionName] NVARCHAR(255)
)
CREATE TABLE CompetitionCompetitors (
[CompetitionID] INT
, [CompetitorID] INT
, [Score] INT
, PRIMARY KEY (
[CompetitionID]
, [CompetitorID]
)
)
Run Code Online (Sandbox Code Playgroud)
对CompetitionCompetitors.CompetitionID和CompetitorID的约束指向其他表.
有了这种表结构 - 你的键都是简单的INTS - 似乎没有一个适合模型的好的自然键,所以我认为SURROGATE KEY非常适合这里.
因此,如果你有这个,那么在特定的竞争中获得不同的竞争者列表,你可以发出这样的查询:
DECLARE @CompetitionName VARCHAR(50) SET @CompetitionName = 'London Marathon'
SELECT
p.[CompetitorName] AS [CompetitorName]
FROM
Competitor AS p
WHERE
EXISTS (
SELECT 1
FROM
CompetitionCompetitor AS cc
JOIN Competition AS c ON c.[ID] = cc.[CompetitionID]
WHERE
cc.[CompetitorID] = p.[CompetitorID]
AND cc.[CompetitionName] = @CompetitionNAme
)
Run Code Online (Sandbox Code Playgroud)
如果你想要每个比赛的得分,竞争对手是:
SELECT
p.[CompetitorName]
, c.[CompetitionName]
, cc.[Score]
FROM
Competitor AS p
JOIN CompetitionCompetitor AS cc ON cc.[CompetitorID] = p.[CompetitorID]
JOIN Competition AS c ON c.[ID] = cc.[CompetitionID]
Run Code Online (Sandbox Code Playgroud)
当您与新竞争对手进行新竞争时,您只需检查竞争对手表中已存在的竞争对手.如果它们已经存在,那么您不会为竞争对手插入竞争对手并插入新的竞争对手.
然后你插入新的竞赛比赛,最后你只需在CompetitionCompetitors中建立所有链接.
ric*_*ard 10
您需要将表格加在一起,并获得一个尚未存在的独特竞争对手列表Competitors
.
这将插入唯一记录.
INSERT Competitors (cName)
SELECT DISTINCT Name
FROM CompResults cr LEFT JOIN Competitors c ON cr.Name = c.cName
WHERE c.Name IS NULL
Run Code Online (Sandbox Code Playgroud)
可能有一段时间需要快速完成此插入而无法等待选择唯一名称.在这种情况下,您可以将唯一名称插入临时表,然后使用该临时表插入到您的真实表中.这很有效,因为所有处理都在您插入临时表时发生,因此它不会影响您的真实表.然后,当您完成所有处理后,您可以快速插入真实表格.我甚至可以在事务中将最后一部分插入真实表中.
小智 5
上面关于标准化的答案非常棒!但是,如果您发现自己处于像我一样的位置,不允许您接触数据库模式或结构,该怎么办?例如,DBA 是“神”,所有建议的修订都会转到 /dev/null?
在这方面,我觉得这个 Stack Overflow 帖子也已经回答了上面所有提供代码示例的用户的问题。
我重新发布了INSERT VALUES WHERE NOT EXISTS中的代码,这对我帮助最大,因为我无法更改任何底层数据库表:
INSERT INTO #table1 (Id, guidd, TimeAdded, ExtraData)
SELECT Id, guidd, TimeAdded, ExtraData
FROM #table2
WHERE NOT EXISTS (Select Id, guidd From #table1 WHERE #table1.id = #table2.id)
-----------------------------------
MERGE #table1 as [Target]
USING (select Id, guidd, TimeAdded, ExtraData from #table2) as [Source]
(id, guidd, TimeAdded, ExtraData)
on [Target].id =[Source].id
WHEN NOT MATCHED THEN
INSERT (id, guidd, TimeAdded, ExtraData)
VALUES ([Source].id, [Source].guidd, [Source].TimeAdded, [Source].ExtraData);
------------------------------
INSERT INTO #table1 (id, guidd, TimeAdded, ExtraData)
SELECT id, guidd, TimeAdded, ExtraData from #table2
EXCEPT
SELECT id, guidd, TimeAdded, ExtraData from #table1
------------------------------
INSERT INTO #table1 (id, guidd, TimeAdded, ExtraData)
SELECT #table2.id, #table2.guidd, #table2.TimeAdded, #table2.ExtraData
FROM #table2
LEFT JOIN #table1 on #table1.id = #table2.id
WHERE #table1.id is null
Run Code Online (Sandbox Code Playgroud)
上面的代码使用的字段与您所拥有的字段不同,但您可以通过各种技术获得一般要点。
请注意,根据 Stack Overflow 上的原始答案,此代码是从此处复制的。
无论如何,我的观点是“最佳实践”通常归结为你能做什么和不能做什么以及理论。
祝你好运!
归档时间: |
|
查看次数: |
323578 次 |
最近记录: |