合并插入订单

spe*_*der 7 sql t-sql sql-server merge sql-server-2008

我的声明看起来像这样:

MERGE INTO someTable st
USING
(
    SELECT id,field1,field2,etc FROM otherTable
) ot on st.field1=ot.field1
WHEN NOT MATCHED THEN
    INSERT (field1,field2,etc)
    VALUES (ot.field1,ot.field2,ot.etc)
Run Code Online (Sandbox Code Playgroud)

其中otherTable有一个自动递增ID字段.

我想插入someTable为处于相同的顺序ID的字段otherTable,使得顺序ID被插入非字段匹配时,s的保留.

快速查看文档似乎表明没有功能可以支持这一点.

这是可能的,还是有另一种方法可以完成符合我要求的插入?

编辑:一种方法是向someTable添加一个捕获排序的附加字段.如果可能的话,我宁愿不这样做.

...经过反思,上面的方法似乎是要走的路.

Mik*_*Vee 14

我无法谈论提问者在这里要求的内容,因为它没有任何意义.

那么让我们假设一个不同的问题:

让我们说,我有一个没有Identity-Field的Heap-Table,但它确实有一个" Visited "Date字段.
堆表记录人员WebPage访问,我将其加载到我的数据仓库中.
在这个数据仓库中,我想使用Surrogate-Key" WebHitID "来引用这些关系.
让我们使用Merge来对表进行初始加载,然后继续调用它以使表保持同步.

我知道如果我将记录插入表中,那么我更喜欢ID(由Identify-Field生成)依据我选择的任何Order-By顺序(让我们说" 访问 "日期) ).
期望Integer-ID与相对于表中其余记录的创建时间相关联的情况并不少见.
我知道这并非总是百分之百的情况,但幽默我一会儿.

Merge可以实现这一点.

使用(感觉像是黑客)TOP将允许在我们的插入中进行排序:

MERGE DW.dbo.WebHit AS Target --This table as an Identity Field called WebHitID.
USING
(
    SELECT TOP 9223372036854775807 --Biggest BigInt (to be safe).
           PWV.PersonID, PWV.WebPageID, PWV.Visited
      FROM ProdDB.dbo.Person_WebPage_Visit AS PWV
     ORDER BY PWV.Visited --Works only with TOP when inside a MERGE statement.
) AS Source
  ON Source.PersonID  = Target.PersonID
 AND Source.WebPageID = Target.WebPageID
 AND Source.Visited   = Target.Visited
WHEN NOT MATCHED BY Target THEN --Not in Target-Table, but in Source-Table.
    INSERT (PersonID, WebPageID, Visited) --This Insert populates our WebHitID.
    VALUES (Source.PersonID, Source.WebPageID, Source.Visited)
WHEN NOT MATCHED BY Source THEN --In Target-Table, but not in Source-Table.
    DELETE --In case our WebHit log in Prod is archived/trimmed to save space.
;
Run Code Online (Sandbox Code Playgroud)


你可以看到我选择使用TOP 9223372036854775807(最大的整数)来拉动所有东西.
如果您有足够的资源进行合并,那么您应该将其分块.
虽然这对我来说是" hacky workaround ",它应该让你到达你需要去的地方.

我在一个小样本集上对此进行了测试并验证了它的工作原理.我没有研究它对更大的复杂数据集的性能影响,所以YMMV有和没有TOP.


MMa*_*tin 7

跟进MikeTeeVee的回答.

使用TOP将允许您在子查询中按顺序排序,但不是TOP 9223372036854775807,我会选择

SELECT TOP 100 PERCENT 
Run Code Online (Sandbox Code Playgroud)

不太可能达到这个数字,但这种方式更有意义,看起来更清洁.

  • 在这种情况下,"SELECT TOP 100 PERCENT"对我不起作用,它会留下**未分类的**顺序.Perhpas它被捕获为特殊情况并被优化器绕过.如果我用`SELECT TOP 9223372036854775807`替换它,则排序立即生效.SQL Server 2008 R2. (6认同)
  • **另请参阅:**MSDN博客文章[TOP 100%ORDER BY认为有害](https://blogs.msdn.microsoft.com/queryoptteam/2006/03/24/top-100-percent-order-by-考虑有害/) (3认同)

HLG*_*GEM -4

为什么要关心 ids 匹配的顺序?这会对您查询数据的方式产生什么影响?相关表应该通过主键和外键连接,而不是按顺序插入记录。表在数据库中本质上并不以特定方式排序。订单应来自 order by 子句。

关于您为什么要这样做的更多解释可能会帮助我们引导您找到合适的解决方案。

  • 虽然您的答案在学术上是正确的,但在某些情况下您无法承担更改架构等的费用。或者请参阅[MikeTeeVee 的答案](http://stackoverflow.com/a/23058548/2392157)。然后您需要一个简单的提示,如何绕过该学术原则并在合并操作中强制执行顺序。您的答案缺少这些详细信息,因此为“-1”。 (5认同)
  • +1 如果您确实关心,那么您尝试捕获的数据中有些内容对您很重要 - 所以请正确执行。听起来数据告诉您它需要一个明确的顺序列。 (3认同)
  • 我尝试插入的数据是按时间顺序排列的,但没有任何显式字段来指示此顺序...但是,按 id 排序时 otherTable 中的顺序按时间顺序是正确的。考虑你的答案让我想知道我的架构是否可以更新。您是正确的,依赖 id 字段可能是一种狡猾的方法。 (3认同)
  • “你为什么要关心 ids 匹配的顺序?” 不是“如何使用合并确保插入以正确的顺序发生?”问题的答案。 (3认同)