首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果继续不以T(或任何给定的主要SQL方言)提供UPSERT语句,会得到什么好处?

如果继续不以T(或任何给定的主要SQL方言)提供UPSERT语句,会得到什么好处?
EN

Software Engineering用户
提问于 2020-12-07 22:21:42
回答 1查看 172关注 0票数 -1

这个问题是问一个普遍适用的工程原则。它使用the作为一个具体的例子,但问题是主要SQL方言背后的工程原则。委员会还本着与先前提出的问题同样的精神提出:

以一种不缓存结果的方式实现LINQ有什么优势?

T已经存在了一段时间,SQL Server也是如此,它与之密切相关。例如,关于堆栈溢出的大量to / Server问题与2005年版本有关。现在是15年后。

截至2020年12月,仍然没有简单的原生UPSERT语句。相反,许多人所做的只是简单地检查是否存在,然后插入或更新。但是,除非您还指定了锁定,否则会出现并发问题。在这一点上,您必须认真考虑不同锁定机制的范围,您的代码会变得有点冗长。

Upsert是一种不断需要的操作;然而,在the发布、更新和扩展多年之后,仍然不包含它的决定必须是有意识和深思熟虑的。在them / Server中添加UPSERT关键字和本机操作的时间已经很长了,所以微软看到了一些让他们谨慎行事的东西--一些工程原则必须考虑到任何主要的SQL方言。

那么,从工程的角度来看,在大规模的SQL方言中没有UPSERT关键字/操作有什么优势呢?在等式中加入这一因素会带来什么缺点?它可以是一个优势,语言保持相对苗条,只是增加新的功能,有一个明显的,持久的优势。但是,既然上浮是一种普遍需要和明确定义的操作,那么故意忽略它还有什么好处呢?

这与我想象的大致一致。它应该能够使用本质上相同的内部自动锁定机制,使两个UPDATE或两个INSERT语句相互隔离。SQL实现已经必须防止UPDATE语句并发地影响同一行(或者INSERT语句试图同时插入相同的自动主键值),因此我们应该能够在这里使用完全相同或几乎相同的锁定机制:

案例1:

代码语言:javascript
运行
复制
UPSERT [TableX] (ColumnA, ColumnB, ... )
VALUES          (@valueA, @valueB, ... );

↓

IF NOT EXISTS(
    SELECT
        1
    FROM
        TableX WITH (
            <roughly the union of internal, automatic locks used with UPDATE and INSERT
            statements>
        )
    WHERE
        (ColumnA = @valueA OR ISNULL(ColumnA, @valueA) IS NULL) AND
        (ColumnB = @valueB OR ISNULL(ColumnB, @valueB) IS NULL) AND
        ...
)
    INSERT TableX (ColumnA, ColumnB, ... )
    VALUES        (@valueA, @valueB, ... );

案例2:

代码语言:javascript
运行
复制
UPSERT [TableX] (ColumnA, ColumnB, ... )
VALUES          (@valueA, @valueB, ... )
WHERE           <SetOfConditions>;

↓

IF EXISTS(
    SELECT
        1
    FROM
        TableX WITH (
            <roughly the union of internal, automatic locks used with UPDATE and INSERT
            statements>
        )
    WHERE
        <SetOfConditions>
)
    UPDATE TableX
    SET
        ColumnA = @valueA,
        ColumnB = @valueB,
        ...
    WHERE
        <SetOfConditions>
ELSE
    INSERT TableX (ColumnA, ColumnB, ..., <AnythingElseFrom_SetOfConditions> )
    VALUES        (@valueA, @valueB, ..., <AnythingElseFrom_SetOfConditions> );

在我看来,这似乎是自然而合乎逻辑的,使用了大致相同的内部锁定机制,用于实现UPDATEINSERT语句。锁的内容可能要稍微多一点,因为这是两个背靠背的操作,但应该是80%-90%,这只是UPDATEs和INSERTs已经存在的问题的翻版。它主要应该是UPDATE_-和INSERT__-锁的结合。

唯一稍微混乱的部分是显式的WHERE子句。一方面,您基本上必须确定地从它派生值,从而隐式地将它们插入到VALUESSELECT子句中。这样,在插入的情况下,结果行将与WHERE子句匹配。正因为如此,WHERE条件(如ColumnZ > 0 )不会在没有随机性和额外复杂性的情况下工作,但是像ColumnZ = 0ColumnZ IS NULL这样的条件会起作用。

另一方面,不应允许WHERE子句中的条件与VALUESSELECT子句相矛盾。再一次,这与插入有关。如果必须插入新行,如果子句相互矛盾,那么新行应该匹配哪个子句?由于这一问题,矛盾需要使声明/操作无效。

因此,解决上述两个问题需要两件事:对于要解决的第一个问题,WHERE条件必须是确定性的(除非允许随机性和额外的复杂性)。对于第二个问题,不应允许WHERE条件与VALUESSELECT子句中的任何内容相矛盾。

对我来说,只要WHERE条款受到足够的限制,以解决上述两个问题,这似乎是完全合理的,非常实用和普遍适用,并有一个坚实的寿命在前面。不管是to还是其他任何东西,为什么一个主要的、资金充足的、全面的SQL实现会继续无限期地放弃这个特性?从工程的角度来看,什么具体的问题使这成为一个严重的问题?

EN

回答 1

Software Engineering用户

发布于 2020-12-08 23:35:38

那么,从工程的角度来看,在大规模的SQL方言中没有UPSERT关键字/操作有什么优势呢?

TSQL有一个upsert关键字MERGE。它可以具有您希望UPSERT具有的确切含义,但需要更明确地说明。另一方面,这种明示是以INSERTUPDATE从句的形式出现的。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/419770

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档