sql-server - `merge` 语句会保证所有插入行的 `default current_timestamp` 列的值相同吗?
问题描述
我相信即使在事务中,一堆插入到带有default current_timestamp
列的表中,可能会根据行创建时间具有不同的值,但我不确定该语句的原子性如何:merge
这是我的测试脚本:
代码
if type_id(N'ValuableRow') is not null drop type ValuableRow create type ValuableRow as table ( JustAValue nvarchar(max) ) drop table if exists TestTable create table TestTable( JustAValue nvarchar(max) , Birth datetime2 default current_timestamp ) go --// delete TestTable insert TestTable(JustAValue) values ('1234'), ('5678') declare @rows ValuableRow, @alsoRows ValuableRow insert @rows(JustAValue) values ('abcd'), ('1234'), ('5678'), ('wxyz') merge TestTable y using @rows x on (y.JustAValue=x.JustAValue) when not matched then insert (JustAValue) values (JustAValue) output inserted.JustAValue into @alsoRows ; select * from @alsoRows select * from TestTable
结果显示:
显然,如果操作需要更长的执行时间是不够的,我想知道merge
仍然会使所有插入的行具有相同的创建时间吗?
解决方案
无论MERGE
.
这与 的原子性无关MERGE
。
CURRENT_TIMESTAMP
结束调用GETDATE()
函数。GETDATE()
是一个运行时常量。保证计划中的每个单独引用在整个语句持续时间内具有相同的值(尽管如果计划有多个引用GETDATE()
这些将是两个不同的运行时常量,并且可以在不同的时间进行评估)。
这里的执行计划只有一个对该函数的引用。它计算一次并给出表达式标签Expr1010
StmtText
|--Table Insert(OBJECT:(@alsoRows), SET:([JustAValue] = [tempdb].[dbo].[TestTable].[JustAValue] as [y].[JustAValue]))
|--Table Merge(OBJECT:([tempdb].[dbo].[TestTable] AS [y]), SET:([tempdb].[dbo].[TestTable].[JustAValue] as [y].[JustAValue] = @rows.[JustAValue] as [x].[JustAValue],[tempdb].[dbo].[TestTable].[Birth] as [y].[Birth] = [Expr1010]) ACTION:([Action1009]))
|--Compute Scalar(DEFINE:([Expr1010]=CONVERT_IMPLICIT(datetime2(7),getdate(),0)))
|--Table Spool
|--Filter(WHERE:([Action1009] IS NOT NULL))
|--Compute Scalar(DEFINE:([Action1009]=ForceOrder(CASE WHEN [TrgPrb1007] IS NOT NULL THEN NULL ELSE (4) END)))
|--Nested Loops(Left Outer Join, OUTER REFERENCES:([x].[JustAValue]))
|--Table Scan(OBJECT:(@rows AS [x]))
|--Compute Scalar(DEFINE:([TrgPrb1007]=(1)))
|--Filter(WHERE:([tempdb].[dbo].[TestTable].[JustAValue] as [y].[JustAValue]=@rows.[JustAValue] as [x].[JustAValue]))
|--Table Scan(OBJECT:([tempdb].[dbo].[TestTable] AS [y]))
RAND()
也是一个运行时常量,并且在实践中更容易看到这种行为,因为它不依赖于设计一个长时间运行的语句。
DECLARE @T TABLE(X FLOAT DEFAULT RAND());
MERGE INTO @T
USING sys.objects o ON o.object_id = X
WHEN NOT MATCHED THEN INSERT DEFAULT VALUES;
SELECT *
FROM @T; /*All rows will have the same value*/
推荐阅读
- ios - 无法获取 navigationItem.rightBarButtonItem 的 UIView/Frame - iOS
- sqlite - SQL - julianday 函数的正确日期格式是什么?
- c++ - 编译器确定参数是给定还是省略
- groovy - Nifi Groovy 脚本将 Json 转换为 CSV
- docusignapi - Docusign:发送模板信封,得到“选项卡元素中指定的 DocumentId 不引用此信封中的文档”
- grid - tk_messageBox 在网格视图中显示错误,但在包中正常
- javascript - 如何使用 Chai.js 检查数组中的任何元素是否包含大于 0 的值?
- neural-network - 如何在语音识别中生成时间戳?
- javascript - 如何将 React 组件推送到数组?
- c++ - 生成整数长度的枚举数组