我正在寻找那个表演'甜蜜点'尝试更新多行的多列时...
背景
我在MDM /抽象/分层分类/功能SQL Server环境中工作。这个问题涉及一个后期数据驱动的计算过程,我需要保存结果。我将JSON传递给SQL函数,该函数将自动为插入/更新创建SQL(如果值匹配,则跳过更新)。
tblDestination看起来像
create table tblDestination as
(
sysPrimaryKey bigint identity(1,1)
, sysHeaderId bigint -- udt_ForeignKey
, sysLevel1Id bigint -- udt_ForeignKey (classification level 1)
, strText nvarchar(100) -- from here down: the values that need to be updated
, dtmDate datetime2(7)
, numNumeric flat
, flgFlag bit
, intInteger bigint
, sysRefKey bigint-- ForeignKey
, primary key non clustered (sysPrimaryKey)
)
/ *请注意,此表上的聚簇索引存在,包含的内容多于上面列出的列,并且物理建模正确。如果要测试* /
,可以使用所需的任何clustered / IX / UI索引@JSON看起来像......(ARBITRARY#范围在2到100之间)
declare @JSON nvarchar(max)='{"ARBITRARY NAME 1":"3/1/2017","ARBITRARY NAME 2": "Value", "ARBITRARY NAME 3": 45.3}'
函数游标通过传入的@JSON并构建插入或更新语句。
Cursor local static forward_only read_only
for
select [key] as JSON_Key, [value] from openjson(@json)
while @@fetch
-- get the id for ARBITRARY ID plus a classification id
select @level1Id = level1Id, @level2id = level2Id
from tblLevel1 where ProgrammingName = @JSON_Key
-- get a ProgrammingName field for the previously retrieved level2Id
Select @ProgrammingName = /*INTEGER/FLAG/NUMERIC/TEXT/DATE/REFKEY
from tblLevel2 where level2id = @level2id
-- clear variables
set @numeric = null, @integer = null, @text = null etc..
-- check to see if insert or update is required
Select @DestinationID from tblDestination where HeaderId = @header and Level1 = @Level1
if @DestinationId is null
begin
If @ProgrammingName = 'Numeric' begin @Numeric = @JSON_Value end
else if @ProgrammingName = 'Integer' begin @Integer = @JSON_value end
etc..
-- dynamically build the updates here..
/*
'update tblDestination
Set numeric = ' +@numeric
+', flag = '+@flag
+', date = '+@date
.. etc
+'where HeaderId = '+@header + ' and level1Id = '+@Level1Id
end
IE:
Update tblDestination
Set numNumeric = NULL
, flgFlag = NULL
, dtmDate = '3/1/2017'
Where sysPrimaryKey = 33676224
*/
最后 ...到这篇文章:这里有没有人有多列多行更新的经验?
类似的东西:
Set TableNumeric
= CASE WHEN Level3Id = 33676224 then null
when leve3id = 33676225 then 3.2
when level3id = 33676226 then null
end
, tableDate = case when level3id = 33676224 then '3/1/2017'
when 33676225 then null
when 33676226 then null
end
where headerId = 23897
and IDs in (33676224, 33676225, 33676226)
我知道插入语句(插入的列数与记录数)的速度不同,并且已拨入该部分。
我很想知道是否有人发现了这个“甜蜜点”。用于更新。 甜蜜点意味着:
我应该制作新的更新块之前有多少个案例?
更新tbl set(Column = Case(当Id = ##然后ColumnValue时)^ n END)^ n'减少实际更新数量的正确方法是什么?
将事务中的更新包装为更快选项(以及每个COMMIT的数量)?
更新声明的易读性无关紧要。实际上没有人会看到代码。
我已将单个更新语句链隔离为所讨论查询成本的约70%以上(与所有插入和20 / 80,50 / 50,80 / 20%更新/%插入相比)