我试图找出最佳的方式插入一个记录并入一张单一的表格,但只有如果该项目已经不存在。关键在这种情况下,是一个限(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 ])

指定 ClusteredNonClustered, 根据你的情况。还有,如果你想要它排(使能更快寻求),指定 ASCDESC 对于排列顺序。

看看 在这里,, 如果你想了解更多关于指数结构。

否则,你可以使用 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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top