断言简介
断言是一种数据质量测试查询,用于查找违反查询中指定的一个或多个条件的行。如果查询返回任何行,则断言会失败。Dataform 每次更新 SQL 工作流时都会运行断言,如果任何断言都失败,系统会向您发出提醒。
Dataform 会自动在 BigQuery 中创建包含已编译断言查询结果的视图。如在工作流设置文件中配置的那样,Dataform 会在断言架构中创建这些视图,您可以在其中检查断言结果。
例如,对于默认的 dataform_assertions
架构,Dataform 会以以下格式在 BigQuery 中创建视图:dataform_assertions.assertion_name
。
您可以为所有 Dataform 表类型(表、增量表、视图和具体化视图)创建断言。
您可以通过以下方式创建断言:
-
您可以将内置断言添加到表的
config
块中,并指定断言的条件。 -
对于高级用例或非由 Dataform 创建的数据集,您可以在单独的 SQLX 文件中手动编写自定义断言。
准备工作
所需的角色
如需获得创建断言所需的权限,请让您的管理员为您授予工作区的 Dataform Editor (roles/dataform.editor
) IAM 角色。
如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
创建内置断言
您可以将内置 Dataform 断言添加到表格的 config
块。Dataform 会在表创建后运行这些断言。Dataform 创建表格后,您可以在工作区的 Workflow execution logs(工作流执行日志)标签页中查看断言是否通过了测试。
您可以在表的 config
块中创建以下断言:
nonNull
此条件断言,在所有表行中,指定的列均不为 null。此条件适用于绝不会为 null 的列。
以下代码示例展示了表的
config
块中的nonNull
断言:
config {
type: "table",
assertions: {
nonNull: ["user_id", "customer_id", "email"]
}
}
SELECT ...
rowConditions
此条件断言所有表行都遵循您定义的自定义逻辑。每条行条件都是一个自定义 SQL 表达式,系统会针对每条行条件对每行表格进行评估。如果任何表行导致
false
,断言将失败。以下代码示例展示了增量表的
config
块中的自定义rowConditions
断言:
config {
type: "incremental",
assertions: {
rowConditions: [
'signup_date is null or signup_date > "2022-08-01"',
'email like "%@%.%"'
]
}
}
SELECT ...
uniqueKey
此断言用于断言指定列中的所有表行具有不同的值。
以下代码示例展示了视图的
config
块中的uniqueKey
断言:
config {
type: "view",
assertions: {
uniqueKey: ["user_id"]
}
}
SELECT ...
uniqueKeys
此条件断言,在指定的列中,没有表行具有相同的值。如果表中有多行具有所有指定列的相同值,则断言会失败。
以下代码示例展示了表的
config
块中的uniqueKeys
断言:
config {
type: "table",
assertions: {
uniqueKeys: [["user_id"], ["signup_date", "customer_id"]]
}
}
SELECT ...
向 config
代码块添加断言
如需向表的配置块添加断言,请按以下步骤操作:
- 在开发工作区中的 Files 窗格中,选择表定义 SQLX 文件。
- 在表格文件的
config
块中,输入assertions: {}
。 - 在
assertions: {}
内,添加断言。 - 可选:点击格式。
以下代码示例展示了在 config
块中添加的条件:
config {
type: "table",
assertions: {
uniqueKey: ["user_id"],
nonNull: ["user_id", "customer_id"],
rowConditions: [
'signup_date is null or signup_date > "2019-01-01"',
'email like "%@%.%"'
]
}
}
SELECT ...
使用 SQLX 创建手动断言
手动断言是指您在专用 SQLX 文件中编写的 SQL 查询。手动断言 SQL 查询必须返回零行。如果查询在执行时返回行,则断言会失败。
如需在新 SQLX 文件中添加手动断言,请按以下步骤操作:
- 在文件窗格中,点击
definitions/
旁边的更多菜单。
- 点击创建文件。
在添加文件路径字段中,输入文件名,后跟
.sqlx
。例如definitions/custom_assertion.sqlx
。文件名只能包含数字、字母、连字符和下划线。
点击创建文件。
在文件窗格中,点击新文件。
在该文件中,输入以下内容:
config { type: "assertion" }
在
config
代码块下,编写您的 SQL 查询或多个查询。可选:点击格式。
以下代码示例展示了 SQLX 文件中的手动断言,该断言断言 sometable
中的字段 A、B 和 c
永远不会为 NULL
:
config { type: "assertion" }
SELECT
*
FROM
${ref("sometable")}
WHERE
a IS NULL
OR b IS NULL
OR c IS NULL
将断言设置为依赖项
当工作流操作 B 依赖于包含断言的工作流操作 A 时,操作 A 的断言失败不会阻止 Dataform 执行操作 B。如需仅在操作 A 的断言通过时执行操作 B,您需要将操作 A 的断言设置为操作 B 的依赖项。
您可以通过以下方式将断言设置为所选操作的依赖项:
- 将所选断言设为依赖项
您可以手动将所选断言设置为依赖项,方法是将它们添加到修改后的操作的
config
块中的dependencies: [ "" ]
。例如,如果操作 B 依赖于操作 A,并且您希望操作 B 仅依赖于操作 A 的所选断言,则可以将这些所选断言添加到操作 B 的
config
块中。您可以手动将所选断言设置为除数据源声明之外的所有操作类型的依赖项。
- 将所选依赖项操作的断言设置为依赖项
您可以设置
includeDependentAssertions
参数,以自动将所选依赖项工作流操作的所有直接断言设置为所修改操作的依赖项。Dataform 会在每次编译操作期间将这些断言添加为依赖项,以确保在依赖项操作的断言发生变化时,依赖项保持最新状态。例如,如果操作 C 依赖于操作 A 和 B,但您只希望操作 C 依赖于操作 A 的断言,则可以修改操作 C 并设置
includeDependentAssertions
参数,以自动将操作 A 的所有断言设置为操作 C 的依赖项。您可以为以下类型的操作设置
includeDependentAssertions
参数:table
view
operations
- 将所有依赖项操作的断言设置为依赖项
您可以设置
dependOnDependencyAssertions
参数,以自动将所修改操作的所有依赖项操作中的所有直接断言设置为所修改操作的其他依赖项。Dataform 会在每次编译操作期间将这些断言添加为依赖项,以确保在依赖项操作的断言发生变化时,依赖项保持最新状态。例如,如果操作 C 依赖于操作 A 和 B,您可以修改操作 C 并设置
dependOnDependencyAssertions
参数,以自动将操作 A 和 B 的所有断言设置为操作 C 的依赖项。您可以为以下类型的操作设置
dependOnDependencyAssertions
参数:table
view
operations
如果您在单个文件中设置 dependOnDependencyAssertions
参数和 includeDependentAssertions
参数,则 includeDependentAssertions
参数的优先级更高。例如,如果您将 dependOnDependencyAssertions
设置为 true
,但同时也将所选依赖项操作的 includeDependentAssertions
设置为 false
,Dataform 将不会向依赖项添加该操作的断言。
以下代码示例展示了在同一表定义文件中设置的 dependOnDependencyAssertions
和 includeDependentAssertions
参数:
// filename is tableName.sqlx
config {
type: "table",
dependOnDependencyAssertions: true,
dependencies: [ "actionA", {name: "actionB", includeDependentAssertions: false} ]
}
SELECT * FROM ${ref("actionC")}
在上述代码示例中,Dataform 会在编译期间将 actionA
和 actionC
的所有直接断言添加到 tableName
的依赖项。
将所选断言设为依赖项
如需仅在所选断言通过时执行工作流操作,您可以将所选断言添加到修改后的操作的 config
块中的 dependencies: [ "" ]
。
如需将所选断言设置为所选工作流操作的依赖项,请按以下步骤操作:
- 在开发工作区中的 Files 窗格中,展开
definitions/
。 - 选择工作流操作 SQLX 文件。
- 在操作文件的
config
块中,输入dependencies: [ "" ]
。 在
dependencies: [ "" ]
中,输入您要设置为依赖项的操作断言的名称或手动断言的文件名,采用以下格式之一:nonNull
config { type: "ACTION_TYPE", dependencies: [ "ACTION_DATASET_NAME_ACTION_NAME_assertions_nonNull"] }
替换以下内容:
- ACTION_TYPE:工作流操作的类型:
table
、view
或operations
。 - ACTION_DATASET_NAME:定义操作的数据集的名称。默认数据集在工作流设置文件中定义。
- ACTION_NAME:用于定义断言的操作的名称。
rowConditions
config { type: "ACTION_TYPE", dependencies: [ "ACTION_DATASET_NAME_ACTION_NAME_assertions_rowConditions"] }
替换以下内容:
- ACTION_TYPE:工作流操作的类型:
table
、view
或operations
。 - DATASET_NAME:定义操作的数据集的名称。默认数据集在工作流设置文件中定义。
- ACTION_NAME:定义断言的操作的名称。
uniqueKey
config { type: "ACTION_TYPE", dependencies: [ "ACTION_DATASET_NAME_ACTION_NAME_assertions_uniqueKey_INDEX"] }
替换以下内容:
- ACTION_TYPE:工作流操作的类型:
table
、view
或operations
。 - DATASET_NAME:定义表的数据集的名称。默认数据集在工作流设置文件中定义。
- ACTION_NAME:定义断言的表的名称。
- INDEX:您要添加为依赖项的
uniqueKey
断言中定义的键数组的索引。例如0
或1
。如果断言中仅定义了一个键数组,则索引为0
。
uniqueKeys
config { type: "ACTION_TYPE", dependencies: [ "ACTION_DATASET_NAME_ACTION_NAME_assertions_uniqueKeys_INDEX"] }
替换以下内容:
- ACTION_TYPE:工作流操作的类型:
table
、view
或operations
。 - DATASET_NAME:定义表的数据集的名称。默认数据集在工作流设置文件中定义。
- ACTION_NAME:定义断言的表的名称。
- INDEX:您要添加为依赖项的
uniqueKeys
断言中定义的键数组的索引,例如0
或1
。如果断言中仅定义了一个键数组,则索引为0
。
手动断言
config { type: "ACTION_TYPE", dependencies: [ "MANUAL_ASSERTION_NAME"] }
替换以下内容:
- ACTION_TYPE:工作流操作的类型:
table
、view
或operations
。 - MANUAL_ASSERTION_NAME 手动断言的名称。
- ACTION_TYPE:工作流操作的类型:
如需将其他断言添加为修改的表格的依赖项,请重复第 4 步。
可选:点击格式。
以下代码示例展示了添加到 dataform
数据集中定义的表 A 的断言:
config {
type: "table",
assertions: {
uniqueKey: ["user_id"],
nonNull: ["user_id", "customer_id"],
}
}
以下代码示例展示了将表 A 断言添加为表 B 的依赖项:
config {
type: "table",
dependencies: [ "dataform_A_assertions_uniqueKey_0", "dataform_A_assertions_nonNull"]
}
以下代码示例展示了在 manualAssertion.sqlx
文件中定义的手动断言,该断言已添加为视图的依赖项:
config {
type: "view",
dependencies: [ "manualAssertion"]
}
以下代码示例展示了 manual_assertion
文件以及作为依赖项添加到表的 sometable
表的断言:
config {
type: "table",
dependencies: [ "manual_assertion", "dataform_sometable_assertions_nonNull" , "dataform_sometable_assertions_rowConditions"]
}
SELECT * FROM ${ref("referenced_table")} LEFT JOIN ...
将所选操作的断言设置为依赖项
如需仅在所选依赖项操作的所有直接断言都通过时执行工作流操作,请在修改后的操作中将 includeDependentAssertions
参数设置为 true
。在编译期间,Dataform 会自动向依赖项添加所选依赖项操作的直接断言。默认值为 false
。
如需将所选依赖项操作的所有断言设置为依赖项,请按以下步骤操作:
- 在开发工作区中的 Files 窗格中,展开
definitions/
。 - 选择工作流操作 SQLX 文件。
在该文件中,使用以下任一方法将
includeDependentAssertions
参数设置为true
:在
config
块中config { type: "ACTION_TYPE", dependencies: [{name: "dEPENDENCY_ACTION_NAME", includeDependentAssertions: true}] }
替换以下内容:
- ACTION_TYPE:工作流操作的类型:
table
、view
或operations
。 - DEPENDENCY_ACTION_NAME:您要将哪些断言设置为所修改操作的依赖项的依赖项操作的名称。
在
SELECT
语句中config { type: "ACTION_TYPE" } SELECT * FROM ${ref({name: "DEPENDENCY_ACTION_NAME", includeDependentAssertions: true})}
替换以下内容:
- ACTION_TYPE:工作流操作的类型:
table
、view
或operations
。 - DEPENDENCY_ACTION_NAME:您要将哪些断言设置为所修改操作的依赖项的依赖项操作的名称。
- ACTION_TYPE:工作流操作的类型:
可选:点击格式。
以下代码示例展示了依赖于 viewA
、tableB
和 tableB
的所有断言的 tableC
:
// filename is tableC.sqlx
config {
type: "table",
dependencies: ["viewA", {name: "tableB", includeDependentAssertions: true}]
}
SELECT * FROM ...
在上面的代码示例中,Dataform 会在编译期间自动将 tableB
的所有直接断言添加为 tableC
的依赖项。
将所有依赖项操作的断言设置为依赖项
如需仅在所有依赖项操作的所有直接断言都通过时执行工作流操作,请在修改后的操作中将 dependOnDependencyAssertions
参数设置为 true
。Dataform 会在编译期间自动将依赖项操作的直接断言添加为依赖项。默认值为 false
。
如果您在单个文件中设置 dependOnDependencyAssertions
参数和 includeDependentAssertions
参数,则 includeDependentAssertions
参数会优先于为其设置的依赖项操作。
如需将所选依赖项操作的所有断言设置为依赖项,请按以下步骤操作:
- 在开发工作区中的 Files 窗格中,展开
definitions/
。 - 选择工作流操作 SQLX 文件。
在该文件中,将
dependOnDependencyAssertions
参数设置为true
,格式如下:config { type: "ACTION_TYPE", dependOnDependencyAssertions: true, dependencies: [ "dependency1", "dependency2" ] }
替换 ACTION_TYPE:工作流操作的类型。支持的值包括
table
、view
和operations
。可选:点击格式。
以下代码示例展示了依赖于 sometableA
、sometabletableB
、sometableC
和 sometableD
的 sometableE
,以及依赖项表的所有直接断言:
// filename is sometableE.sqlx
config {
type: "table",
dependOnDependencyAssertions: true,
dependencies: [ "sometableA", "sometableB" ]
}
SELECT * FROM ${ref("sometableC")}
SELECT * FROM ${ref("sometableD")}
在上面的代码示例中,Dataform 会在编译期间自动将 sometableA
、sometableB
、sometableC
和 sometableD
的所有直接断言添加为 sometableE
的依赖项。
后续步骤
- 如需详细了解断言类型,请参阅 Dataform API。
- 如需了解如何使用 JavaScript 定义断言,请参阅使用 JavaScript 创建 Dataform 工作流。
- 如需了解如何手动执行工作流,请参阅触发执行。