SQL 服务器合并删除与过滤器

Posted

技术标签:

【中文标题】SQL 服务器合并删除与过滤器【英文标题】:SQL server merge Delete with filter 【发布时间】:2014-10-01 13:35:53 【问题描述】:

我正在使用合并进行插入或删除,但我不确定它应该是什么样子。我有一个映射表,将分类法映射到支持的语言。该表如下所示:

TaxonomyLanguageID(PK) | TaxonomyID(FK) | LanguageID(FK)

我想要做的是将临时表与上表合并,其中临时表将包含分类法支持的语言列表。例如:

TaxonomyID|LanguageID

456,        2

456,        3

456,        9

我尝试过的看起来像这样(选择用于测试,稍后这将是一个临时表):

MERGE dbo.TaxonomyLanguages as t
using (SELECT 5395  as TaxonomyID, 2 as LanguageID) as s
ON (s.TaxonomyID=T.TaxonomyID AND s.LanguageID=t.LanguageID)
WHEN NOT MATCHED BY TARGET THEN
    INSERT(TaxonomyID,LanguageID) VALUES(S.TaxonomyID,s.LanguageID)
WHEN NOT MATCHED BY SOURCE AND T.TaxonomyID=s.TaxonomyID
    THEN DELETE;

我想要做的是如果不匹配则插入,如果不匹配则删除,但只删除目标中与源中找到的分类 ID 匹配的那些行。

但我得到一个“只有目标列在'当源不匹配'子句中允许”错误。

关于如何解决这个问题(或应该如何完成)的任何想法?

我正在寻找的示例。如果我有来源喜欢

TaxonomyID|LanguageID

4000,      2

4000,      3

还有一个像这样的目标:

TaxonomyLanguageID|TaxonomyID|LanguageID

1,                  3000       2

2,                  4000       1

3,                  4000       2

最终结果是:

TaxonomyLanguageID|TaxonomyID|LanguageID

1,                 3000       2

3,                 4000       2

4,                 4000       3

【问题讨论】:

【参考方案1】:

你必须把它分成两遍,因为关键字段的数量不同。

Select 456 as TaxonomyID, 2 as LanguageID
  into TaxonomyLanguages

INSERT INTO [dbo].[TaxonomyLanguages]
           ([TaxonomyID]
           ,[LanguageID])
     VALUES
           (456, 3)
           ,(456, 9)
GO

select *
from [TaxonomyLanguages]


MERGE dbo.TaxonomyLanguages as t
using (SELECT 5395  as TaxonomyID, 2 as LanguageID) as s
ON (s.TaxonomyID=T.TaxonomyID AND s.LanguageID=t.LanguageID)
WHEN NOT MATCHED BY TARGET THEN
    INSERT(TaxonomyID,LanguageID) VALUES(S.TaxonomyID,s.LanguageID);


MERGE dbo.TaxonomyLanguages as t
using (SELECT 5395  as TaxonomyID, 2 as LanguageID) as s
ON (s.TaxonomyID=T.TaxonomyID)
WHEN NOT MATCHED BY SOURCE 
    THEN DELETE;

select *
from [TaxonomyLanguages]

根据评论,更改第二次合并:

MERGE dbo.TaxonomyLanguages as t
using (SELECT 456  as TaxonomyID, 3 as LanguageID) as s
ON (s.TaxonomyID=T.TaxonomyID)
WHEN  MATCHED 
  and (s.LanguageID <> T.LanguageID)
    THEN DELETE;

【讨论】:

我的问题可能很糟糕,但这只会删除所有其他行。我只想删除与源中的 TaxonomyID 匹配的行,但不匹配 languageID。我会用一个例子来更新我的问题 好的。然后使用 MATCHED 和过滤器。 合并 dbo.TaxonomyLanguages as t using (SELECT 456 as TaxonomyID, 3 as LanguageID) as s ON (s.TaxonomyID=T.TaxonomyID) WHEN MATCHED 和 (s.LanguageID T.LanguageID)然后删除;【参考方案2】:
MERGE SupplierProducts with (HOLDLOCK) AS TARGET
USING (SELECT P.Id, P.ListPrice, P.SalesPrice FROM Products P) AS SOURCE ON (TARGET.Id = SOURCE.Id)

WHEN MATCHED AND TARGET.Id = SOURCE.Id THEN
    UPDATE SET TARGET.ListPrice = SOURCE.ListPrice,
               TARGET.Price = SOURCE.SalesPrice,
               TARGET.UpdatedAt = GETDATE()

WHEN NOT MATCHED BY TARGET THEN
    INSERT (ProductId, ListPrice, Price)
    VALUES (SOURCE.Id, SOURCE.ListPrice, SOURCE.SalesPrice)
    
WHEN NOT MATCHED BY SOURCE
    THEN DELETE
    OUTPUT
        left($action, 1) AS [Event],
        SOURCE.Id,
        DELETED.ListPrice AS OldListPrice,
        DELETED.Price AS OldPrice,
        INSERTED.ListPrice AS ListPrice,
        INSERTED.Price AS Price ,
        INSERTED.UpdatedAt;

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于SQL 服务器合并删除与过滤器的主要内容,如果未能解决你的问题,请参考以下文章

sql 如何过滤重复记录

SQL 从反透视表中删除过滤器

Kotlin函数式编程 ② ( 过滤函数 | predicate 谓词函数 | filter 过滤函数 | 合并函数 | zip 函数 | folder 函数 | 函数式编程意义 )

Kotlin函数式编程 ② ( 过滤函数 | predicate 谓词函数 | filter 过滤函数 | 合并函数 | zip 函数 | folder 函数 | 函数式编程意义 )

复制经过过滤的数据子集:合并复制还是事务复制?

Shell文本处理 - 分割合并与过滤