SQL服务器-怎么插入一个记录和确保它是独一无二的
-
06-07-2019 - |
题
我试图找出最佳的方式插入一个记录并入一张单一的表格,但只有如果该项目已经不存在。关键在这种情况下,是一个限(400)领域。对这个例子,让我们假装这个名字 字 在牛津英语词典/插入你的最爱的字典里。还有,我猜我需要作词领域的一个主要关键。(该表还将有一个独特的识别符PK也同样)。
所以..我可能会得到这些话,我需要增加表...
例如。
- 猫
- 狗
- Foo
- 酒吧
- PewPew
- 等等...
所以,在传统上,我会尝试下(伪代码)
SELECT WordID FROM Words WHERE Word = @Word
IF WordID IS NULL OR WordID <= 0
INSERT INTO Words VALUES (@Word)
ie。 如果不存在,然后插入它。
现在..这问题我担心的是,我们获得了大量的命..因此,它是可能的,这个词可插入另一个进程之间的选择和插入..然后扔约束的错误?(ie。一个 比赛的状况).
然后我想,我可能是能够做到以下...
INSERT INTO Words (Word)
SELECT @Word
WHERE NOT EXISTS (SELECT WordID FROM Words WHERE Word = @Word)
基本上, 插入一个词时并不存在。
坏法笑,我不知道如果这是不好或良好,因为它是如何锁下表(如果它不会)而不是高性能的上一个表,它获得巨大的读取和充足的写。
所以-你怎么Sql大师认为/做什么?
我希望有一个简单的插入和'抓住,对任何错误。
解决方案
你的解决方案:
INSERT INTO Words (Word)
SELECT @Word
WHERE NOT EXISTS (SELECT WordID FROM Words WHERE Word = @Word)
...是良好的,因为它得到。你可以简化到这样的:
INSERT INTO Words (Word)
SELECT @Word
WHERE NOT EXISTS (SELECT * FROM Words WHERE Word = @Word)
...因为存在着实际上并不需要返回的任何记录,所以优化查询不会打扰寻找在这一领域的你提出的要求。
如你所提及,但是,这并不是特别高性能的,因为它将锁定整个期间表的插入。不同之处在于,如果添加一个独特的指标(它不需要的主要钥)一词,然后它就只需要锁定的相关网页。
您最好的选择是,以模拟预期的负荷,并期待在性能与SQL Server分析器。与任何其他领域,过早优化是一件坏事。定义可以接受的绩效指标,然后衡量之前做什么。
如果这还不能给你足够的性能,再有就是一堆技术从数据仓库的字段可能会有帮助。
其他提示
我想我已经找到一个更好地(或至少得更快)的答案。创建一个指标,如:
CREATE UNIQUE NONCLUSTERED INDEX [IndexTableUniqueRows] ON [dbo].[table]
(
[Col1] ASC,
[Col2] ASC,
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = ON, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
包括所有列定义的独特性。重要的部分是IGNORE_DUP_KEY=。变成不独特的插入的警告。SSIS忽略了这些警告你仍然可以使用快速装载。
如果你正在使用MS SQL服务器,您可以创建一个独特的索引表的列需要是唯一(记录 在这里,):
CREATE UNIQUE [ CLUSTERED | NONCLUSTERED ] INDEX <index_name>
ON Words ( word [ ASC | DESC ])
指定 Clustered
或 NonClustered
, 根据你的情况。还有,如果你想要它排(使能更快寻求),指定 ASC
或 DESC
对于排列顺序。
看看 在这里,, 如果你想了解更多关于指数结构。
否则,你可以使用 UNIQUE CONSTRAINTS
像记录 在这里,:
ALTER TABLE Words
ADD CONSTRAINT UniqueWord
UNIQUE (Word);
我有类似的问题,这是我解决了它
insert into Words
( selectWord , Fixword)
SELECT word,'theFixword'
FROM OldWordsTable
WHERE
(
(word LIKE 'junk%') OR
(word LIKE 'orSomthing')
)
and word not in
(
SELECT selectWord FROM words WHERE selectWord = word
)
而唯一约束certaily一的路要走,你也可以使用这个为你的插入的逻辑:http://www.sqlteam.com/article/application-locks-or-mutexes-in-sql-server-2005
现在只可以不把任何锁在下面的表因此不用担心的读 而你的存在检查将执行确定。
这是一个互斥在sql代码。
我不能说话的资料,MS SQL,但有一点的一个主要关键在SQL是保证独特性。所以,通过的定义,在一般SQL方面,一个主要关键之一或更多的领域是唯一一个表中。虽然有不同的方式来执行这一行为(更换老入新的一对拒绝新的一)我会惊讶如果MS SQL两个没有一个机制,用于执行这一行为并不是拒绝的新条目。只是确定设置的主要关键领域,这个词 应该 的工作。
再次,虽然,我不这都是我的知识,从MySQL我的编程和数据库类,这样的道歉如果我的错综复杂的MS SQL。
declare @Error int
begin transaction
INSERT INTO Words (Word) values(@word)
set @Error = @@ERROR
if @Error <> 0 --if error is raised
begin
goto LogError
end
commit transaction
goto ProcEnd
LogError:
rollback transaction