从C#调用BigQuery存储过程时遭遇目标表配置冲突错误
我来帮你梳理下这个问题的核心原因,以及对应的解决办法:
问题根源
当你调用CALL语句执行存储过程时,BigQuery会把这个操作视为脚本执行,而脚本(包含多个SQL语句的序列)本身不支持通过客户端设置DestinationTable——这就是你第一个错误configuration.query.destinationTable cannot be set for scripts的原因。
而当你注释掉这个配置后,客户端执行查询时默认期望有一个目标表来接收结果,但存储过程返回的查询结果并没有绑定到任何表,所以又抛出了Query doesn't have a destination table异常。
两种可行的解决思路
思路1:让存储过程自行处理结果写入
修改你的PROC2,直接在存储过程内部将查询结果写入目标表,这样客户端就不需要设置DestinationTable了。
比如把PROC2的逻辑从单纯的查询改为:
CREATE OR REPLACE TABLE `powerful-decker-249310.Tables.StationsTmp` AS SELECT * FROM tempTab;
或者如果需要追加数据,可以用:
INSERT INTO `powerful-decker-249310.Tables.StationsTmp` SELECT * FROM tempTab;
这样调用PROC3时,客户端只需要执行CALL语句即可,不需要额外配置目标表,存储过程会自动把结果写入到指定的StationsTmp表中。
思路2:客户端获取结果后手动写入目标表
保留存储过程的现有逻辑,客户端不设置DestinationTable,而是先获取查询结果,再手动将数据插入到目标表中。
调整后的C#代码示例:
var resultsOptions = new GetQueryResultsOptions { Timeout = new TimeSpan(0, Timeout, 0) }; var queryOptions = new QueryOptions{ UseLegacySql = false }; // 注释掉DestinationTable的配置,避免脚本执行报错 // queryOptions.DestinationTable = bqClient.GetTable("powerful-decker-249310","Tables", "StationsTmp").Reference; // 执行存储过程调用,获取结果集 var results = bqClient.ExecuteQuery(query, parameters: null, queryOptions: queryOptions, resultsOptions: resultsOptions); // 将结果写入目标表 var destinationTable = bqClient.GetTable("powerful-decker-249310","Tables", "StationsTmp"); var rows = results.ToList(); if (rows.Any()) { bqClient.InsertRows(destinationTable, rows); }
补充说明
BigQuery对脚本和单条查询的处理逻辑不同:单条SELECT语句可以指定目标表,但脚本(包括CALL、多条SQL组合)不支持这种方式,因为脚本可能包含多个返回结果的语句,无法用单一的目标表来接收。所以要么在存储过程内部处理结果的持久化,要么客户端自行处理结果集的写入。
内容的提问来源于stack exchange,提问作者Gowtham M




