这个问题是问一个普遍适用的工程原则。它使用the作为一个具体的例子,但问题是主要SQL方言背后的工程原则。委员会还本着与先前提出的问题同样的精神提出:
T已经存在了一段时间,SQL Server也是如此,它与之密切相关。例如,关于堆栈溢出的大量to / Server问题与2005年版本有关。现在是15年后。
截至2020年12月,仍然没有简单的原生UPSERT语句。相反,许多人所做的只是简单地检查是否存在,然后插入或更新。但是,除非您还指定了锁定,否则会出现并发问题。在这一点上,您必须认真考虑不同锁定机制的范围,您的代码会变得有点冗长。
Upsert是一种不断需要的操作;然而,在the发布、更新和扩展多年之后,仍然不包含它的决定必须是有意识和深思熟虑的。在them / Server中添加UPSERT关键字和本机操作的时间已经很长了,所以微软看到了一些让他们谨慎行事的东西--一些工程原则必须考虑到任何主要的SQL方言。
那么,从工程的角度来看,在大规模的SQL方言中没有UPSERT关键字/操作有什么优势呢?在等式中加入这一因素会带来什么缺点?它可以是一个优势,语言保持相对苗条,只是增加新的功能,有一个明显的,持久的优势。但是,既然上浮是一种普遍需要和明确定义的操作,那么故意忽略它还有什么好处呢?
这与我想象的大致一致。它应该能够使用本质上相同的内部自动锁定机制,使两个UPDATE或两个INSERT语句相互隔离。SQL实现已经必须防止UPDATE语句并发地影响同一行(或者INSERT语句试图同时插入相同的自动主键值),因此我们应该能够在这里使用完全相同或几乎相同的锁定机制:
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, ... );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> );在我看来,这似乎是自然而合乎逻辑的,使用了大致相同的内部锁定机制,用于实现UPDATE和INSERT语句。锁的内容可能要稍微多一点,因为这是两个背靠背的操作,但应该是80%-90%,这只是UPDATEs和INSERTs已经存在的问题的翻版。它主要应该是UPDATE_-和INSERT__-锁的结合。
唯一稍微混乱的部分是显式的WHERE子句。一方面,您基本上必须确定地从它派生值,从而隐式地将它们插入到VALUES或SELECT子句中。这样,在插入的情况下,结果行将与WHERE子句匹配。正因为如此,WHERE条件(如ColumnZ > 0 )不会在没有随机性和额外复杂性的情况下工作,但是像ColumnZ = 0或ColumnZ IS NULL这样的条件会起作用。
另一方面,不应允许WHERE子句中的条件与VALUES或SELECT子句相矛盾。再一次,这与插入有关。如果必须插入新行,如果子句相互矛盾,那么新行应该匹配哪个子句?由于这一问题,矛盾需要使声明/操作无效。
因此,解决上述两个问题需要两件事:对于要解决的第一个问题,WHERE条件必须是确定性的(除非允许随机性和额外的复杂性)。对于第二个问题,不应允许WHERE条件与VALUES或SELECT子句中的任何内容相矛盾。
对我来说,只要WHERE条款受到足够的限制,以解决上述两个问题,这似乎是完全合理的,非常实用和普遍适用,并有一个坚实的寿命在前面。不管是to还是其他任何东西,为什么一个主要的、资金充足的、全面的SQL实现会继续无限期地放弃这个特性?从工程的角度来看,什么具体的问题使这成为一个严重的问题?
发布于 2020-12-08 23:35:38
那么,从工程的角度来看,在大规模的SQL方言中没有
UPSERT关键字/操作有什么优势呢?
TSQL有一个upsert关键字MERGE。它可以具有您希望UPSERT具有的确切含义,但需要更明确地说明。另一方面,这种明示是以INSERT和UPDATE从句的形式出现的。
https://softwareengineering.stackexchange.com/questions/419770
复制相似问题