”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 如何在 Bigquery 参数化查询中传递结构数组

如何在 Bigquery 参数化查询中传递结构数组

发布于2024-11-08
浏览:158

How to pass an Array of Structs in Bigquery

在Google的Bigquery中,SQL查询可以参数化。如果您不熟悉这个概念,它基本上意味着您可以将 SQL 查询编写为参数化模板,如下所示:

INSERT INTO mydataset.mytable(columnA, columnB)
    VALUES (@valueA, @valueB)

并分别传递值。这有很多好处:

  • 查询比通过字符串连接构建的查询更具可读性
  • 代码更加健壮和工业化
  • 这是针对 SQL 注入攻击的强大保护(强制 XKCD)

乍一看,从 Python 脚本传递查询参数似乎很简单。例如:

from google.cloud.bigquery import (
    Client,
    ScalarQueryParameter,
    ArrayQueryParameter,
    StructQueryParameter,
    QueryJobConfig,
)

client=Client()

client.query("
INSERT INTO mydataset.mytable(columnA, columnB)
    VALUES (@valueA, @valueB)
", job_config=QueryJobConfig(
    query_parameters=[
        ScalarQueryParameter("valueA","STRING","A"), 
        ScalarQueryParameter("valueB","STRING","B")
])

上面的示例在 A 列和 B 列中插入简单(“标量”)值。但您也可以传递更复杂的参数:

  • 数组(ArrayQueryParameter)
  • 结构(StructQueryParameter)

当您想要插入结构数组时,就会出现问题:有很多陷阱,几乎没有文档,网络上有关该主题的资源也很少。本文的目标就是填补这一空白。

如何使用参数化查询在 bigquery 中持久保存结构数组

让我们定义要存储在目标表中的以下对象

from dataclasses import dataclass

@dataclass
class Country:
    name: str
    capital_city: str

@dataclass
class Continent:
    name: str
    countries: list[Country]

通过调用此参数化查询

query = UPDATE continents SET countries=@countries WHERE name="Oceania"

遵循浅薄文档的第一次尝试是

client.query(query, 
    job_config=QueryJobConfig(query_parameters=[
        ArrayQueryParameter("countries", "RECORD", [
             {name="New Zealand", capital_city="Wellington"},
             {name="Fiji", capital_city="Suva"} ...]
]))

这会惨败

AttributeError:'dict'对象没有属性'to_api_repr'

问题 1:ArrayQueryParameter 的值必须是 StructQueryParameter 的实例

事实证明,构造函数的第三个参数 - value - 必须是 StructQueryParameter 实例的集合,而不是直接想要的值。那么让我们来构建它们:

client.query(query, 
job_config=QueryJobConfig(query_parameters=[
    ArrayQueryParameter("countries", "RECORD", [
    StructQueryParameter("countries",
        ScalarQueryParameter("name", "STRING", ct.name), 
        ScalarQueryParameter("capital_city", "STRING", ct.capital_city)
    )
    for ct in countries])
]))

这次有效...直到你尝试设置一个空数组

client.query(query, 
    job_config=QueryJobConfig(
    query_parameters=[
        ArrayQueryParameter("countries", "RECORD", [])
]))

ValueError:缺少空数组的详细结构项类型信息,请提供 StructQueryParameterType 实例。

陷阱 n°2:提供完整的结构类型作为第二个参数

错误消息非常清楚:“RECORD”不足以让 Bigquery 知道如何处理空数组。它需要完整详细的结构。就这样吧

client.query(query, job_config=QueryJobConfig(query_parameters=[
    ArrayQueryParameter("countries",
        StructQueryParameterType(
            ScalarQueryParameterType("STRING","name"),
            ScalarQueryParameterType("STRING","capital_city")
        ), [])
]))

(注意 ...ParameterType 构造函数的参数顺序与 ...Parameter 构造函数相反。这只是路上的另一个陷阱...)

现在它也适用于空数组,耶!

最后一个需要注意的问题:StructQueryParameterType 的每个子字段都必须有一个名称,即使第二个参数(名称)在构造函数中是可选的。它实际上对于子字段是强制性的,否则你会得到一种新的错误

空结构字段名称

我想这就是我们完成查询参数中记录数组的使用所需要知道的一切,我希望这会有所帮助!


感谢您的阅读!我是 Matthieu,Stack Labs 的数据工程师。
如果您想了解 Stack Labs 数据平台或加入热情的数据工程团队,请联系我们。


Denys Nevozhai 在 Unsplash 上的照片

版本声明 本文转载于:https://dev.to/stack-labs/how-to-pass-an-array-of-structs-in-bigquerys-parameterized-queries-39nm?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 课程计划:年级学生 Python 基础知识(初级)
    课程计划:年级学生 Python 基础知识(初级)
    客观的: 在本课程结束时,学生将对 Python 编程有基本的了解,包括变量、基本数据类型、循环和函数。他们将使用 Python 创建简单的程序,运用逻辑思维和解决问题的技能。 持续时间:6 节课 第 1 课:Python 简介和设置 目标:让学生熟...
    编程 发布于2024-11-08
  • 如何在 Java 中正确复制二维数组以保留修改?
    如何在 Java 中正确复制二维数组以保留修改?
    通过复制保留二维数组修改在 Java 中,创建对象副本时,了解引用分配行为至关重要。在给定的场景中,定义了两个名为 current 和 old 的二维数组,以及复制内容的方法。old() 方法将 current 数组分配给 old 。然而,这只是将引用传输到内存中的同一数组。当对 current 进...
    编程 发布于2024-11-08
  • 如何在不依赖扩展名的情况下确定文件类型?
    如何在不依赖扩展名的情况下确定文件类型?
    如何在不依赖扩展名的情况下检测文件类型除了检查文件的扩展名之外,确定文件是 mp3 还是图像格式是很有价值的编程中的任务。这是一个不依赖扩展的全面解决方案:PHP >= 5.3:$mimetype = finfo_fopen(fopen($filename, 'r'), FILEINFO_MIME_...
    编程 发布于2024-11-08
  • 使用 JavaScript 创建令人着迷的粒子动画
    使用 JavaScript 创建令人着迷的粒子动画
    这就是我们要创建的,将鼠标移到粒子上即可查看效果。 在本文中,我将引导您完成使用 JavaScript 和 HTML5 画布创建迷人粒子动画的过程。该项目不仅增强了网页的美观性,而且还是深入研究一些有趣的编码概念的绝佳机会。让我们开始吧! 项目概况 动画的特点是粒子围绕中心点以圆形图...
    编程 发布于2024-11-08
  • 使用 JavaScript 释放大型语言模型的力量:实际应用程序
    使用 JavaScript 释放大型语言模型的力量:实际应用程序
    In recent years, Large Language Models (LLMs) have revolutionized how we interact with technology, enabling machines to understand and generate human-...
    编程 发布于2024-11-08
  • Bootstrap 和 Tailwind 集成:Pro 和 Contro | Bootstrap 和 Tailwind:优点和缺点
    Bootstrap 和 Tailwind 集成:Pro 和 Contro | Bootstrap 和 Tailwind:优点和缺点
    简介 |介绍 意大利语: 本文有意大利语和英语版本。向下滚动查看英文版本。 英语: 本文有意大利语和英语版本。向下滚动查看英文版本。 意大利语版 Bootstrap 和 Tailwind 集成简介 近年来,Bootstrap和Tailwind CSS已经成为前端开发最流行的两个框架。 Boot...
    编程 发布于2024-11-08
  • 我们如何使用 Gin 框架增强 Go 应用程序中的错误处理?
    我们如何使用 Gin 框架增强 Go 应用程序中的错误处理?
    更好的错误处理问题在Go应用程序中,我们如何通过定义自定义错误类型(例如appError和实现自定义处理程序来捕获错误并将其写入响应中?AnswerGin Error处理Gin 鼓励使用中间件来处理错误响应,并将错误逻辑与正常流程逻辑分开。在Gin中实现集中错误处理:使用中间件:router.Use...
    编程 发布于2024-11-08
  • DOM API 终极指南
    DOM API 终极指南
    // Selecting Elements: document is not the real DOM element. document.documentElement; // Select the entire page document.head; // Select the head doc...
    编程 发布于2024-11-08
  • Node.js 傻瓜指南 - MongoDB 和 Fastify
    Node.js 傻瓜指南 - MongoDB 和 Fastify
    O que é Node.js? Node.js, uma plataforma construída sobre o motor de JavaScript V8 do Google Chrome, revolucionou o desenvolvimento backend n...
    编程 发布于2024-11-08
  • 如何使用 Joda Time 将日期字符串解析为 DateTime 对象并避免“无效格式”错误?
    如何使用 Joda Time 将日期字符串解析为 DateTime 对象并避免“无效格式”错误?
    使用 Joda Time 将日期字符串解析为 DateTime 对象处理日期和时间数据时,通常需要转换日期作为字符串存储到结构化对象中以供进一步处理。 Joda Time 库提供了一套全面的工具,用于处理 Java 中的日期和时间操作。一个常见任务是将日期字符串转换为 DateTime 对象。但是,...
    编程 发布于2024-11-08
  • 如何解决 PHP 中的“每个引号前都有斜杠”问题?
    如何解决 PHP 中的“每个引号前都有斜杠”问题?
    理解“引号前的斜杠”问题在某些情况下,PHP网页可能会遇到提交表单数据导致添加一个每个双引号前都有反斜杠。此问题是由称为“魔术引号”的服务器配置功能引起的。启用魔术引号后,PHP 在向数据库或表单提交发送或从数据库或表单提交中接收某些字符时,会自动转义某些字符,包括双引号。虽然这可以通过转义恶意引号...
    编程 发布于2024-11-08
  • ## 如何在 C++ 中将多维数组转换为库函数的指针?
    ## 如何在 C++ 中将多维数组转换为库函数的指针?
    在 C 中将多维数组转换为指针 在 C 中,多维数组与指针不直接兼容。当尝试使用采用 double** 的库函数时,使用简单的强制转换转换 double4 数组可能会导致错误。要解决此问题,必须使数组适应函数的接口。不要将整个数组转换为 double**,而是创建指向每行开头的临时“索引”数组:do...
    编程 发布于2024-11-08
  • 如何在 PHP 中异步执行 cURL 请求?
    如何在 PHP 中异步执行 cURL 请求?
    PHP中的异步Curl请求在PHP中异步执行curl post请求可以提高性能并防止潜在的延迟。以下是如何使用不同的方法实现此目的:使用异步 cURL 函数使用curl_multi_*时,您可以同时执行多个 cURL 请求。下面是一个示例代码:$curl = curl_init($request);...
    编程 发布于2024-11-08
  • 如何将 Boehm 垃圾收集器与 C++ 标准库类(如“std::vector”和“std::string”)集成?
    如何将 Boehm 垃圾收集器与 C++ 标准库类(如“std::vector”和“std::string”)集成?
    将 Boehm 垃圾收集器与 C 标准库结合使用开发多线程 C 应用程序时,Boehm 保守的垃圾收集器对于简化内存非常有用管理。这就提出了如何将 Boehm GC 与 C 标准库的类(如 std::map 和 std::vector)集成的问题。一种方法涉及重新定义全局运算符 ::new 以使用 ...
    编程 发布于2024-11-08
  • 如何在 PHP 中通过 SSH 安全连接到远程 MySQL 服务器?
    如何在 PHP 中通过 SSH 安全连接到远程 MySQL 服务器?
    在 PHP 中通过 SSH 安全连接到远程 MySQL 服务器要为 PHP 数据库连接建立安全隧道,以下 SSH 隧道解决方案提供了一种强大的方法。SSH 隧道设置创建一个通往 MySQL 数据库服务器的 SSH 隧道。为此,请使用如下命令:ssh -fNg -L 3307:10.3.1.55:33...
    编程 发布于2024-11-08

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3