高级T-SQL:如何在更新多列时更新多行?

时间:2018-03-23 05:59:04

标签: sql-server

我正在寻找那个表演'甜蜜点'尝试更新多行的多列时...

背景

我在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%更新/%插入相比)

0 个答案:

没有答案