【问题标题】:Sequelize: Bulk update or insert into MSSQL DBSequelize:批量更新或插入 MSSQL DB
【发布时间】:2018-05-22 22:16:26
【问题描述】:

在过去的 24 小时里,我一直在网上搜索解决方案,但还没有找到。我正在尝试将单个模型的批量更新插入(更新或插入)到 mssql 数据库中。带有 updateOnDuplicate:true 的 bulkCreate 不适用于 mssql。还有其他解决方案吗?这是数据集在 1-50k 行之间的任何地方。任何帮助将不胜感激!

【问题讨论】:

    标签: javascript sql sql-server node.js sequelize.js


    【解决方案1】:

    使用 OpenJson 将数据转换为表格并与源表格合并,如下所示:

    const upsertedData = [
      {
        id: "123",
        value: "Value 2"
      },
      {
        id: "124",
        value: "Value 1"
      }
    ]
    
    const upsert = async (data) => {
      await sequelize.query(
        `BEGIN
          DECLARE @json NVARCHAR(MAX);
          SET @json = :dataToBeUpserted
          MERGE INTO dbo.tableToBeUpserted AS Target
          USING (SELECT * from OpenJson(@json) WITH (
              id nvarchar(32),
              value nvarchar(32),
          )) AS Source
          ON (Target.id = Source.id)
          WHEN MATCHED THEN
          UPDATE SET 
              Target.value = Source.value
          WHEN NOT MATCHED THEN           
              INSERT (id, value)
              VALUES (Source.id, Source.value);
        END`,
        {
          replacements: {
            dataToBeUpserted: JSON.stringify(data)
          },
        }
      )
    }
    
    await upsert(upsertedData)
    

    【讨论】:

      【解决方案2】:

      对于 SQL 2016+,您只需使用 NVarchar(max) 参数将批量数据作为 JSON 传递,然后解析并加载到服务器上。您的查询将如下所示:

      Insert into TargetTable(Number,Date,Customer,Quantity,[Order])
      SELECT Number,Date,Customer,Quantity,[Order]
      FROM OPENJSON ( @json )  
      WITH (   
                    Number   varchar(200)   '$.Order.Number',  
                    Date     datetime       '$.Order.Date',  
                    Customer varchar(200)   '$.AccountNumber',  
                    Quantity int            '$.Item.Quantity',  
                    [Order]  nvarchar(MAX)  AS JSON  
       );
      

      您可以将@json 参数与 NVarchar(max)(字符串)值绑定,例如:

      [  
        {  
          "Order": {  
            "Number":"SO43659",  
            "Date":"2011-05-31T00:00:00"  
          },  
          "AccountNumber":"AW29825",  
          "Item": {  
            "Price":2024.9940,  
            "Quantity":1  
          }  
        },  
        {  
          "Order": {  
            "Number":"SO43661",  
            "Date":"2011-06-01T00:00:00"  
          },  
          "AccountNumber":"AW73565",  
          "Item": {  
            "Price":2024.9940,  
            "Quantity":3  
          }  
        }
      ]
      

      更新看起来像:

       with q as
       (
          select t.Number, t.Quantity oldQuantity, j.Quantity newQuantity 
          from OPENJSON ( @json )  
          WITH (   
                        Number   varchar(200)   '$.Order.Number',  
                        Date     datetime       '$.Order.Date',  
                        Customer varchar(200)   '$.AccountNumber',  
                        Quantity int            '$.Item.Quantity',  
                        [Order]  nvarchar(MAX)  AS JSON  
                ) j
          join TargetTable t
            on j.Number = t.Number
       )
       update q set oldQuantity = newQuantity
      

      见:https://docs.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql

      如果您无法绑定参数,那么在紧要关头,您可以将 JSON 文档作为文字字符串包含在您的 TSQL 批处理中。

      【讨论】:

      • 我很欣赏您的回复,这实际上是一种有趣的方式。通常我使用 TVP 和 MERGE 存储过程,类似于此处 cmets 中概述的内容:michaeljswart.com/2011/09/…。但问题不在于如何在 SQL 中执行此操作,而是如何使用 Sequelize 来执行此操作。我知道如何在 SQL 中做到这一点,但 Sequelize 应该有这个能力。
      • 对。传递 JSON 在性能上应该与 TVP 相似,但不需要客户端驱动程序提供任何特殊的 API 支持。
      • 上面的例子是一个INSERT。对于 OPENJSON 创建的 UPDATE 连接表与您的目标表,然后更新。见上文。
      猜你喜欢
      • 2019-10-08
      • 1970-01-01
      • 2015-03-31
      • 2016-05-02
      • 2011-09-11
      • 2012-03-19
      • 1970-01-01
      • 2011-11-13
      • 2015-10-20
      相关资源
      最近更新 更多