结合 Bigquery Delete 和 Insert 语句

Posted

技术标签:

【中文标题】结合 Bigquery Delete 和 Insert 语句【英文标题】:Combining Bigquery Delete and Insert Statements 【发布时间】:2020-01-23 19:02:29 【问题描述】:

Bigquery 中有没有办法将 DELETEINSERT 语句合并为一个

DELETE `my_project.my_dataset.demo` 
WHERE date= CURRENT_DATE()

INSERT INTO
 `my_project.my_dataset.demo` 
SELECT * FROM `my_project.my_dataset.my_source` 
WHERE date= CURRENT_DATE()

有什么语句可以将以上两种DML合二为一?

【问题讨论】:

【参考方案1】:

MERGE:

https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement

MERGE 语句是一种 DML 语句,它可以将 INSERT、UPDATE 和 DELETE 操作组合成一条语句并以原子方式执行这些操作。

在以下示例中,NewArrivals 表中的所有产品都替换为子查询中的值。 INSERT 子句没有为目标表或源子查询指定列名。

MERGE dataset.NewArrivals
USING (SELECT * FROM UNNEST([('microwave', 10, 'warehouse #1'),
                             ('dryer', 30, 'warehouse #1'),
                             ('oven', 20, 'warehouse #2')]))
ON FALSE
WHEN NOT MATCHED THEN
  INSERT ROW
WHEN NOT MATCHED BY SOURCE THEN
  DELETE

【讨论】:

不错,但是这个解决方案仍然不像删除插入操作,通过匹配键,您首先删除目标中与暂存表匹配的所有行,然后将暂存的所有行插入到目标。例如,如果要替换与相同日期匹配的目标表行。【参考方案2】:

我稍微修改了 Felipe 的回答来处理这个用例。唯一需要更改的是在 WHEN NOT MATCHED 语句中添加一个额外的子句:

MERGE `my_project.my_dataset.demo`
USING (SELECT * from `my_project.my_dataset.my_source` WHERE date=CURRENT_DATE())

ON 1=2  /* exactly the same as ON FALSE, but slightly clearer */
WHEN NOT MATCHED BY SOURCE AND date=CURRENT_DATE() THEN
  DELETE
WHEN NOT MATCHED BY TARGET THEN
  INSERT ROW

了解正在发生的事情的关键是我们在条件 1=2 上进行匹配——也就是说,我们将永远匹配。但是我们可以在 NOT MATCHED 子句中添加额外的条件。

WHEN NOT MATCHED BY SOURCE 是现有表中的每条记录。 WHEN NOT MATCHED BY SOURCE AND (whatever) 是现有表中与“whatever”子句匹配的每条记录 WHEN NOT MATCHED BY TARGET 是传入数据中的每条记录

【讨论】:

以上是关于结合 Bigquery Delete 和 Insert 语句的主要内容,如果未能解决你的问题,请参考以下文章

来自 Apps 脚本的 DELETE 的 BigQuery 错误? [复制]

结合 BigQuery 和 Pub/Sub Apache Beam

优化繁重的 BigQuery DELETE 查询

在 BigQuery 中结合聚合和分析功能以减小表大小

如何在 Bigquery 中结合 Cross Join 和 String Agg

将 BigQuery SQL 与内置 Python 函数结合使用