【问题标题】:Proper way to make hundreds database update?进行数百个数据库更新的正确方法?
【发布时间】:2019-05-13 13:27:32
【问题描述】:

我有一个功能,每分钟查询一次 Google BigQuery,我想使用 BigQuery 结果更新另一个关系数据库中的行。

我试图做这样的事情:

BEGIN TRANSACTION
    UPDATE MyTable SET MyField = BigQueryResult_Row1_MyField WHERE a_id = BigQueryResult_Row1_a_id
    UPDATE MyTable SET MyField = BigQueryResult_Row2_MyField WHERE a_id = BigQueryResult_Row2_a_id
    UPDATE MyTable SET MyField = BigQueryResult_Row3_MyField WHERE a_id = BigQueryResult_Row3_a_id
    .
    .
    .
    UPDATE MyTable SET MyField = BigQueryResult_RowN_MyField WHERE a_id = BigQueryResult_RowN_a_id
COMMIT TRANSACTION

这是每个 bigquery 行的 UPDATE 语句。我不能将单个 UPDATE 语句与 SELECT 语句结合使用,因为数据来自 BigQuery,而不是来自另一个数据库表。

尝试执行此事务,我得到超时错误,所以我想问:这是一次进行数百次更新的正确方法吗?在某些情况下,一次甚至可能有上千次更新。我怎样才能以更好的方式做到这一点?

【问题讨论】:

  • 为什么不将数据插入临时表,使用select 更新,然后删除临时表?
  • 什么样的超时错误?

标签: sql tsql transactions sql-update


【解决方案1】:

雷纳特的回答很好。但是更通俗的写法使用values()

UPDATE t 
        SET MyField = v.MyField       
    FROM MyTable t JOIN
         (VALUES ('BigQueryResult_Row1_MyField', 'BigQueryResult_Row1_a_id'),
                 ('BigQueryResult_Row2_MyField', 'BigQueryResult_Row2_a_id'),
                 ('BigQueryResult_Row3_MyField', 'BigQueryResult_Row3_a_id'),
                 ('BigQueryResult_RowN_MyField', 'BigQueryResult_RowN_a_id')
         ) v(MyField, a_id)
        ON v.a_id = t.a_id;

一般来说,当您打算使用UNION ALL 时使用UNION 是个坏主意——因为UNION 会产生删除重复项的开销。在这种情况下,表构造函数无论如何都是一个更简单的解决方案。

【讨论】:

  • 谢谢,我不知道 UNION 开销。无论如何,用 VALUES 定义临时表是否有任何限制,或者我可以添加一千个值?
  • @AlessioInnocenzi 。 . .不,最终您将达到查询长度的限制。这些可以由中间层强加。如果您有超过几百行,您可能会考虑将它们存储在一个表中并批量插入它们。或者,如果数据从数据库中的表开始,则只需使用子查询而不是显式值。
【解决方案2】:

这样的查询是否可以在没有超时的情况下工作(按照@JohnHC 的建议使用临时表)?

BEGIN TRANSACTION

;WITH UpdateTempTable AS (
    SELECT 'BigQueryResult_Row1_MyField' As MyField, 'BigQueryResult_Row1_a_id' AS a_id
    UNION SELECT 'BigQueryResult_Row2_MyField', 'BigQueryResult_Row2_a_id'
    UNION SELECT 'BigQueryResult_Row3_MyField', 'BigQueryResult_Row3_a_id'
    UNION SELECT 'BigQueryResult_RowN_MyField', 'BigQueryResult_RowN_a_id'
  ) UPDATE MyTable 
        SET MyTable.MyField = UpdateTempTable.MyField       
    FROM MyTable 
        JOIN UpdateTempTable ON UpdateTempTable.a_id = MyTable.a_id;

COMMIT TRANSACTION

【讨论】:

  • 它就像一个魅力,非常感谢你的回答,感谢@JohnHC的建议
  • 这是一个很好的答案,但@Gordon Linoff anwer 在这种情况下更合适,因为我必须添加数百或数千个值,而开销是一个重要的变量。出于这个原因,我将更改已接受的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-11
  • 1970-01-01
  • 2019-03-02
  • 2018-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多