本文档介绍了使用 Spanner Graph 时可能会遇到的错误。还提供了错误示例和建议的修复方法。
如果您在查看本问题排查指南后仍需要进一步支持,请参阅获取支持。
架构错误
架构结果基于设置和查询 Spanner Graph 中使用的数据集。
元素键必须保证唯一性
错误消息
Neither the primary keys nor any unique index defined on the property graph
element source table `Person` provides the uniqueness guarantee for graph
element `Person` belonging to the graph `FinGraph`. You want to redefine the
element key columns (`name`) based on the source table's primary keys, or
create a unique index on the element's key columns.
错误示例
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person KEY (name)
);
建议的修复方法
对元素键列创建唯一索引,并根据源表主键重新定义元素键列。
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person KEY (id)
);
或者,对元素键列创建唯一索引。
CREATE UNIQUE INDEX PersonNameIndex ON Person(name);
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person KEY (name)
);
元素定义的名称必须是唯一的
错误消息
Account is defined more than once; use a unique name.
错误示例
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Account,
Person
)
EDGE TABLES (
Account
SOURCE KEY(owner_id) REFERENCES Person
DESTINATION KEY(account_id) REFERENCES Account
);
建议的修复方法
为边缘定义使用唯一名称。
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Account,
Person
)
EDGE TABLES (
Account AS Owns
SOURCE KEY(owner_id) REFERENCES Person
DESTINATION KEY(account_id) REFERENCES Account
);
标签定义对于属性必须保持一致
错误消息
The label Entity is defined with different property declarations. There is one
instance of this label defined with properties of [id]. Another instance is
defined with properties of [name].
错误示例
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person LABEL Entity PROPERTIES (name),
Account LABEL Entity PROPERTIES (id)
);
建议的修复方法
您必须在同一标签下使用同一属性名称集。
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person LABEL Entity PROPERTIES (id, name),
Account LABEL Entity PROPERTIES (id, name)
);
属性声明对于属性类型必须保持一致
错误消息
The property declaration of name has type conflicts. There is an existing
declaration of type INT64. There is a conflicting one of type STRING.
错误示例
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person PROPERTIES (name),
Account PROPERTIES (id AS name)
);
建议的修复方法
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person PROPERTIES (name),
Account PROPERTIES (CAST(id AS STRING) AS name)
);
属性定义不得为子查询
错误消息
Property value expression of count cannot contain a subquery.
错误示例
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person PROPERTIES ((SELECT COUNT(*) FROM Person) AS count)
);
建议的修复方法
不适用。禁止使用此条件。
属性定义在同一元素定义中必须保持一致
错误消息
Property location has more than one definition in the element table Person
错误示例
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person
LABEL Person PROPERTIES (country AS location)
LABEL Entity PROPERTIES (city AS location)
);
建议的修复方法
使用相同的属性定义。
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person
LABEL Person PROPERTIES (country AS location)
LABEL Entity PROPERTIES (country AS location)
);
或者,分配不同的属性名称。
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Person
LABEL Person PROPERTIES (country AS location)
LABEL Entity PROPERTIES (city AS city)
);
查询错误
查询结果基于设置和查询 Spanner Graph 中使用的数据集。
图表元素无法作为查询结果返回
错误消息
Returning expressions of type GRAPH_ELEMENT is not allowed
错误示例
GRAPH FinGraph
MATCH (n:Account)
RETURN n;
建议的修复方法
GRAPH FinGraph
MATCH (n:Account)
RETURN TO_JSON(n) AS n;
属性规范无法与 WHERE 子句搭配使用
错误消息
WHERE clause cannot be used together with property specification
错误示例
GRAPH FinGraph
MATCH (n:Account {id: 1} WHERE n.is_blocked)
RETURN n.id;
建议的修复方法
您可以尝试以下建议的修复方法之一。
GRAPH FinGraph
MATCH (n:Account {id: 1})
WHERE n.is_blocked
RETURN n.id;
GRAPH FinGraph
MATCH (n:Account WHERE n.id = 1 AND n.is_blocked )
RETURN n.id;
GRAPH FinGraph
MATCH (n:Account {id: 1, is_blocked: TRUE})
RETURN n.id;
不允许引用之前语句中定义的变量
错误消息
Name 'account_id', defined in the previous statement, can only be referenced in
the outermost WHERE clause of MATCH
说明
不允许在 MATCH 模式中引用之前语句中定义的变量。在图表查询中,之前语句定义的名称只能在 MATCH 的最外层 WHERE 子句中使用。
错误示例
GRAPH FinGraph
LET account_id = 1
MATCH (n:Account {id: account_id})
RETURN n.id;
建议的修复方法
GRAPH FinGraph
LET account_id = 1
MATCH (n:Account)
WHERE n.id = account_id
RETURN n.id;
不允许重新定义相关图表变量
错误消息
The name account is already defined; redefining graph element variables in a
subquery is not allowed. To refer to the same graph element, use a different
name and add an explicit filter that checks for equality.
说明
在图表查询中,无法在内部图表子查询中重新定义图表元素名称。此场景可能被解读为引用与外部范围相同的图表元素,或是被解读为绑定到新的图表元素,这会遮盖外部范围名称。禁止重新定义。
错误示例
GRAPH FinGraph
MATCH (account:Account)
RETURN account.id AS account_id, VALUE {
MATCH (account:Account)-[transfer:Transfers]->(:Account)
RETURN SUM(transfer.amount) AS total_transfer
} AS total_transfer;
建议的修复方法
GRAPH FinGraph
MATCH (account:Account)
RETURN account.id AS account_id, VALUE {
MATCH (a:Account)-[transfer:Transfers]->(:Account)
WHERE a = account
RETURN SUM(transfer.amount) AS total_transfer
} AS total_transfer;
查询语义问题
查询结果基于设置和查询 Spanner Graph 中使用的数据集。
不同的 WHERE 和 FILTER 生成不同的输出
说明
FILTER 是一个语句;WHERE 是一个子句,作为 MATCH、OPTIONAL
MATCH 语句的一部分。
在第一个示例中,WHERE 子句会向 OPTIONAL MATCH 语句中描述的模式添加额外限制。这不是匹配完成后的过滤条件。
在第二个示例中,FILTER 语句是匹配完成后的过滤条件。
示例问题
以下示例具有不同的输出,因为 WHERE 和 FILTER 不同。
示例 1
GRAPH FinGraph
MATCH (n:Account {id: 7})
OPTIONAL MATCH (m:Account)
WHERE FALSE
RETURN n.id AS n_id, m.id AS m_id;
| n_id | m_id |
|---|---|
| 7 | null |
示例 2
GRAPH FinGraph
MATCH (n:Account {id: 7})
OPTIONAL MATCH (m:Account)
FILTER FALSE
RETURN n.id AS n_id, m.id AS m_id;
空结果。
在语句间传播不同的变量导致不同的输出
说明
在 Graph Query Language 中,多次声明的变量在所有出现位置都引用同一图表元素。
在示例 1 中,没有任何 Account 节点的 id 同时为 7 和 16。因此,系统会返回空结果。
在示例 2 中,系统不会从之前的语句返回名称 n(只会返回 id)。因此,第二个 MATCH 会查找 id 为 16 的 Account 节点。
示例问题
以下示例具有不同的输出,因为不同的变量在语句间传播。
示例 1
GRAPH FinGraph
MATCH (n:Account {id: 7})
RETURN n
NEXT
MATCH (n:Account {id: 16})
RETURN n.id AS n_id;
空结果。
示例 2
GRAPH FinGraph
MATCH (n:Account {id: 7})
RETURN n.id AS id
NEXT
MATCH (n:Account {id: 16})
RETURN n.id AS n_id;
| n_id |
|---|
| 16 |
如果后续语句不是 LIMIT,系统会忽略 ORDER BY
说明
在 Graph Query Language 中,除非满足以下条件之一,否则系统会忽略 ORDER BY 语句:
ORDER BY是最后一个语句。ORDER BY之后紧跟着LIMIT。
在示例 1 中,LIMIT 并非紧跟在 ORDER BY 之后;最后的 LIMIT 是单独的。这意味着引擎会忽略 ORDER BY。
在示例 2 中,ORDER BY 适用,因为 LIMIT 紧跟在 ORDER BY 之后。
示例问题
以下示例具有不同的输出,因为在示例 1 中,当在没有 LIMIT 的情况下使用 ORDER BY 语句时,系统会忽略该语句。
示例 1
GRAPH FinGraph
MATCH (n:Account)
ORDER BY n.id DESC
RETURN n.id
LIMIT 3;
| n_id |
|---|
| 7 |
示例 2
GRAPH FinGraph
MATCH (n:Account)
ORDER BY n.id DESC
LIMIT 3
RETURN n.id;
| n_id |
|---|
| 20 |
不同的边缘模式会产生不同的输出
说明
在错误示例中使用的数据集中,ANY 方向的边缘模式会与图表中的每个 Transfers 边缘匹配两次。
在示例 1 中,从 Account(id=x) 到 Account(id=y) 的 Transfers 边缘可以匹配两次,如下所示:
- n=
Account(id=x),m=Account(id=y) - n=
Account(id=y),m=Account(id=x)
在示例 2 中,只有一个匹配项,其中 n=Account(id=x),m=Account(id=y)。
因此,示例 1 中的查询会返回 10,而示例 2 中的查询会返回 5。
示例问题
以下示例具有不同的输出,因为它们使用不同的边缘模式。
示例 1
GRAPH FinGraph
MATCH (n:Account)-[:Transfers]-(m:Account)
RETURN COUNT(*) AS num_transfer_edges;
| num_transfer_edges |
|---|
| 10 |
示例 2
GRAPH FinGraph
MATCH (n:Account)-[:Transfers]->(m:Account)
RETURN COUNT(*) AS num_transfer_edges;
| num_transfer_edges |
|---|
| 5 |
变更错误
变更结果基于设置和查询 Spanner Graph 中使用的数据集。
缺少来源节点会违反外键限制条件
错误消息
Parent row for row [...] in table AccountTransferAccount is missing. Row cannot
be written.
说明
AccountTransferAccount 边缘表是 INTERLEAVED INTO PARENT Account node 表。如需创建 Transfer 边缘,其父级 Account 节点必须已存在。
错误示例
INSERT INTO AccountTransferAccount (id, to_id, create_time, amount)
VALUES (100, 1, PENDING_COMMIT_TIMESTAMP(), 200);
建议的修复方法
先创建前导 Account 节点,然后创建 Transfer 边缘。
缺少目标节点会违反外键限制条件
错误消息
Foreign key constraint FK_TransferTo is violated on table
AccountTransferAccount. Cannot find referenced values in Account(id)
说明
AccountTransferAccount 表通过名为 FK_TransferTo 的 ForeignKey 引用 Accounttable。如需创建 Transfer 边缘,引用的尾随节点 Account 节点必须已存在。
错误示例
INSERT INTO AccountTransferAccount (id, to_id, create_time, amount)
VALUES (1, 100, PENDING_COMMIT_TIMESTAMP(), 200);
建议的修复方法
先创建尾随 Account 节点,然后创建 Transfer 边缘。
孤立的传出边缘违反了父子关系
错误消息
Integrity constraint violation during DELETE/REPLACE. Found child row [...] in
table AccountTransferAccount
说明
AccountTransferAccount 边缘表是 INTERLEAVED INTO PARENT Account 节点表,而要删除的 Account 节点仍与传出边缘相连。
错误示例
DELETE FROM Account WHERE id = 1;
建议的修复方法
先删除所有传出 Transfer 边缘,然后删除 Account 节点。或者,为 INTERLEAVE 定义 ON DELETE CASCADE,让 Spanner 自动删除这些边缘。
孤立的传入边缘违反了父子关系
错误消息
Foreign key constraint violation when deleting or updating referenced row(s):
referencing row(s) found in table AccountTransferAccount
说明
AccountTransferAccount 边缘表通过 ForeignKey 引用 Account 节点表,而要删除的 Account 节点仍与传入边缘相连。
错误示例
DELETE FROM Account WHERE id = 1;
建议的修复方法
先删除所有传入 Transfer 边缘,然后删除 Account 节点。或者,为 ForeignKey 定义 ON DELETE CASCADE,让 Spanner 自动删除这些边缘。