您当然可以对部分列执行 UPSERT(只要这些“忽略”列是 NULLABLE,这是默认值),请参阅下面使用临时表的示例来演示该想法:
CREATE TEMP TABLE c AS
SELECT 1 id, "old name" name, NULL col1, NULL col2, NULL col3, NULL col4;
SELECT * FROM c; -- output before
MERGE c
USING UNNEST([struct<id INT64, name STRING>
(1, 'updated name 1'),
(3, 'new name to insert')]) d
ON c.id = d.id
WHEN NOT MATCHED THEN
INSERT (id, name) VALUES (d.id, d.name)
WHEN MATCHED THEN
UPDATE SET c.name = d.name;
SELECT * FROM c; -- output after
合并前的输出
+----+----------+------+------+------+------+
| id | name | col1 | col2 | col3 | col4 |
+----+----------+------+------+------+------+
| 1 | old name | NULL | NULL | NULL | NULL |
+----+----------+------+------+------+------+
合并后的输出
+----+--------------------+------+------+------+------+
| id | name | col1 | col2 | col3 | col4 |
+----+--------------------+------+------+------+------+
| 3 | new name to insert | NULL | NULL | NULL | NULL |
| 1 | updated name 1 | NULL | NULL | NULL | NULL |
+----+--------------------+------+------+------+------+
警告
您的查询受长度限制。所以不要在一个查询中 UPSERT 太多行。
最大未解析的标准 SQL 查询长度 - 1 MB
我还建议您使用query parameter 来传递您的数据,而不是将它们放入查询中。
可扩展性
如果每日更新量超过 200MB,则可能将数据分解成太多 MERGE 使其更接近达到 DML 每日限制。
每个表每天的最大组合 INSERT、UPDATE、DELETE 和 MERGE 语句数 - 1,000
您应该考虑其他方式来执行 UPSERT。其中一种方法是将 csv/json/parquet 文件上传到 GCS 并将 load 上传到 BigQuery 表,然后从表中执行类似的 MERGE 语句。