瞭解如何使用 SQL 檢視表建立圖表。本文件提供逐步操作說明和程式碼範例,說明如何定義檢視表,並使用檢視表定義節點和邊緣資料表。查看範例和程式碼範例,瞭解如何使用檢視畫面建立圖表。如要進一步瞭解如何使用檢視表建立屬性圖,包括優點和注意事項,請參閱「透過 SQL 檢視表建立的圖表總覽」。
事前準備
如要建立圖表,請務必:
確認 Spanner Graph 環境已設定。
使用檢視表建立圖表
如要使用檢視畫面建立圖表,請按照下列步驟操作:
定義圖表的檢視畫面。根據預設,檢視畫面必須遵循其中一種支援的檢視模式,確保元素不重複。如果檢視表使用的查詢不符合這些模式,您可以在步驟 4 停用鍵唯一性驗證。詳情請參閱「建立檢視表」。
在
CREATE PROPERTY GRAPH陳述式的NODE TABLES和EDGE TABLES子句中使用檢視表,建立圖表。在
CREATE PROPERTY GRAPH陳述式中加入KEY子句。KEY子句會指定來源檢視表中的資料欄,用於識別各個圖表元素。選用:如果檢視表使用不符合支援唯一性模式的任意 SQL 查詢,請在
CREATE PROPERTY GRAPH陳述式中加入OPTIONS (validate_element_key_uniqueness = false)子句。請確保KEY子句資料欄會為每個節點或邊緣資料列產生不重複的值:CREATE PROPERTY GRAPH MyGraph NODE TABLES ( CustomerViewTrusted KEY(id) ) OPTIONS (validate_element_key_uniqueness = false);詳情請參閱「停用金鑰驗證 (任何 SQL 查詢)」。
選用:如果檢視表呼叫遠端函式或有其他不穩定資料欄,請在
CREATE PROPERTY GRAPH陳述式中加入OPTIONS (allow_view_with_volatile_column = true)子句:CREATE PROPERTY GRAPH MyGraph NODE TABLES ( AccountRemoteUdfView KEY(account_id) ) OPTIONS (allow_view_with_volatile_column = true);詳情請參閱「在檢視表使用遠端函式時啟用 volatile 資料欄」。
範例:使用檢視畫面建立圖表
這個範例會在 Customer 和 Account 資料表上建立下列檢視表:AsiaCustomer、AsiaBankAccount 和 AsiaAccountsOwnership。接著,範例會使用這些檢視畫面,在圖表中建立下列項目:
使用
AsiaCustomer檢視表建立Customer節點資料表。使用
AsiaBankAccount檢視表建立Account節點資料表。使用
AsiaAccountsOwnership檢視表建立Owns邊緣資料表。這個 邊緣會連結Customer節點和Account節點。
步驟 1:建立資料表
首先,建立資料表。下列程式碼會建立 Customer 和 Account 資料表。
CREATE TABLE Customer (
customer_id INT64 NOT NULL,
name STRING(MAX),
address_continent STRING(MAX),
address_country STRING(MAX),
) PRIMARY KEY(customer_id);
CREATE TABLE Account (
account_id INT64 NOT NULL,
customer_id INT64 NOT NULL,
account_type STRING(MAX),
balance INT64,
create_time TIMESTAMP,
address_continent STRING(MAX),
address_country STRING(MAX),
CONSTRAINT FK_CustomerId FOREIGN KEY (customer_id)
REFERENCES Customer (customer_id)
) PRIMARY KEY(account_id);
步驟 2:建立檢視表
接著,建立檢視表來轉換或篩選資料表中的資料。這些檢視表會篩選資料表,只納入亞洲的客戶和帳戶。除非 validate_element_key_uniqueness 設為 false,否則用於建立圖表元素的檢視表必須遵循支援的模式,確保檢視表中的資料列不重複。
-- View for 'Customer' nodes, filtered for Asia
CREATE VIEW AsiaCustomer
SQL SECURITY INVOKER AS
SELECT customer.customer_id, customer.name
FROM Customer customer
WHERE LOWER(customer.address_continent) = "asia";
-- View for 'Account' nodes, filtered for Asia.
CREATE VIEW AsiaBankAccount
SQL SECURITY INVOKER AS
SELECT account.account_id, account.balance, account.account_type, account.create_time
FROM Account account
WHERE LOWER(account.address_continent) = "asia";
-- View for 'Owns' edges, connecting customers to accounts in Asia.
CREATE VIEW AsiaAccountsOwnership
SQL SECURITY INVOKER AS
SELECT account.customer_id, account.account_id
FROM Account account
WHERE LOWER(account.address_continent) = "asia";
步驟 3:建立屬性圖譜
現在,請使用您建立的檢視表建立 AsiaFinGraph。CREATE PROPERTY GRAPH 陳述式包含每個圖表元素定義的 KEY 子句,用於指定可唯一識別圖表元素的資料欄。
CREATE PROPERTY GRAPH AsiaFinGraph
NODE TABLES (
AsiaCustomer AS Customer KEY(customer_id),
AsiaBankAccount AS Account KEY(account_id)
)
EDGE TABLES (
AsiaAccountsOwnership AS Owns
KEY(customer_id, account_id)
SOURCE KEY (customer_id) REFERENCES Customer (customer_id)
DESTINATION KEY (account_id) REFERENCES Account (account_id)
);
應用實例
與使用資料表做為屬性圖元素相比,SQL 檢視表有許多優點。以下範例示範了使用檢視表 (而非資料表) 定義圖表元素的用途。
範例:強制執行精細的圖表資料存取控管
如要對圖表資料強制執行資料列層級安全性,請使用定義者權限檢視表定義節點或邊緣資料表。檢視表會向圖表
舉例來說,如要限制圖表存取權,僅限工程成本中心員工存取,您可以建立 EngineerEmployeeView 檢視表,並使用 GRANT 子句,將檢視表的 SELECT 權限授予 engineering_data_reader 角色。
使用這個檢視表定義圖表節點資料表時,具備 engineering_data_reader 角色的使用者執行圖表查詢,只能看到檢視表篩選出的資料列,包括工程員工。
-- The table containing all employee data.
CREATE TABLE Employee (
id INT64 NOT NULL,
cost_center STRING(MAX),
job_title STRING(MAX),
office STRING(MAX)
) PRIMARY KEY (id);
-- The definer's rights view that filters for engineering employees.
CREATE VIEW EngineerEmployeeView SQL SECURITY DEFINER AS
SELECT e.id, e.cost_center, e.job_title, e.office
FROM Employee e
WHERE LOWER(e.cost_center) = "engineering";
-- The role that is granted to read the view.
CREATE ROLE engineering_data_reader;
GRANT SELECT ON VIEW EngineerEmployeeView TO ROLE engineering_data_reader;
-- The graph that uses definer's rights view.
CREATE PROPERTY GRAPH EngineeringGraph
NODE TABLES (
EngineerEmployeeView KEY(id)
);
範例:模型衍生圖表元素
您可以使用檢視表定義需要轉換資料的圖表元素。主要優點是檢視表會定義轉換,因此您不需要為衍生資料維護個別資料表。
取消巢狀陣列,建立邊緣模型
例如,您可以從 ARRAY 資料欄 (或 JSON 資料欄中的陣列欄位) UNNEST 資料,從單一資料列建立多個邊緣關係的模型。
在下列供應鏈結構定義範例中,Parts 資料表會將子元件清單儲存在 dependent_parts 陣列中。檢視表可以使用 UNNEST 運算子,將該陣列的每個元素轉換為不同的資料列。這個檢視表可做為邊緣資料表,讓您建立 PartDependsOnPart 邊緣模型,代表零件之間的依附關係。
-- Parts table with an ARRAY of dependent parts.
CREATE TABLE Parts (
part_id INT64 NOT NULL,
dependent_parts ARRAY<INT64>
) PRIMARY KEY (part_id);
-- A view that unnests the dependent_parts array.
-- GROUP BY ensures uniqueness for the graph element KEY.
CREATE VIEW PartDependsOnPart SQL SECURITY INVOKER AS
SELECT p.part_id, dependent_part_id
FROM Parts AS p,
UNNEST(p.dependent_parts) AS dependent_part_id
GROUP BY p.part_id, dependent_part_id;
-- Graph modeling the part dependency relationship.
CREATE PROPERTY GRAPH SupplyChainGraph
NODE TABLES (
Parts
)
EDGE TABLES (
PartDependsOnPart KEY (part_id, dependent_part_id)
SOURCE KEY (part_id) REFERENCES Parts(part_id)
DESTINATION KEY (dependent_part_id) REFERENCES Parts(part_id)
);
使用遠端函式運算屬性
您也可以在檢視表中使用遠端函式,方法是在 CREATE
PROPERTY GRAPH 陳述式的 OPTIONS 子句中設定 allow_view_with_volatile_column = true,為圖表元素計算衍生資源。詳情請參閱「在檢視表使用遠端函式時啟用 volatile 資料欄」。
-- Define a remote function.
CREATE FUNCTION rudf_identity_func(x INT64)
RETURNS INT64 NOT DETERMINISTIC LANGUAGE REMOTE
OPTIONS (
endpoint = 'https://us-central1-project-id.cloudfunctions.net/my-func'
);
-- Base table for accounts.
CREATE TABLE Account (
account_id INT64 NOT NULL,
balance INT64
) PRIMARY KEY (account_id);
-- View that computes a property using the remote function.
CREATE VIEW AccountRemoteUdfView SQL SECURITY INVOKER AS
SELECT
t.account_id,
t.balance,
rudf_identity_func(t.account_id) AS view_computed_prop
FROM Account AS t;
-- Graph using the view requires allow_view_with_volatile_column = true.
CREATE PROPERTY GRAPH AccountViewRemoteUdfGraph
NODE TABLES (
AccountRemoteUdfView KEY (account_id)
PROPERTIES (account_id, balance, view_computed_prop)
)
OPTIONS (allow_view_with_volatile_column = true);
範例:無結構定義資料轉換
無結構定義的資料管理可讓您建立彈性的圖表定義,不必預先定義節點和邊緣類型。雖然無結構定義的資料管理方式可提供彈性,但隨著資料定義更加明確,您可能需要轉換為更正式的結構。更正式的結構會在結構定義中公開圖表的節點和邊緣關係、標籤和屬性,減少手動探索資料以瞭解圖表結構定義的需求。
您可以使用檢視表,將節點和邊緣類型正規化,而不必遷移基礎資料。舉例來說,您可以從使用標準 GraphNode 和 GraphEdge 資料表的典型無結構定義模型轉換。為此,您需要建立檢視表,從無結構定義的資料表中擷取資料:
為要正規化的每個節點和邊緣類型 (例如
Person或WorksFor) 定義檢視表。在檢視表中,依標籤 (例如WHERE n_label = "person") 篩選資料,並將 JSON 欄中的屬性轉換為特定資料類型 (例如STRING(prop.name) AS name)。定義新的屬性圖,其中
NODE TABLES和EDGE TABLES參照您剛建立的類型檢視表。
對於某些查詢 (例如具有多個邊緣類型的量化路徑模式),無結構定義圖表的效能優於正規化圖表。如果正式中繼資料對您的用途很重要,可以使用檢視表,從無結構定義圖表轉換為有類型的結構定義。您也可以選擇在某些用途使用無結構定義圖,在其他用途使用有類型結構定義圖。詳情請參閱「根據圖表查詢選擇結構定義設計」。
以下範例說明從無結構定義圖表轉換為正式圖表的工作流程,共分為四個步驟:
定義無結構定義模型的標準
GraphNode和GraphEdge資料表。在這些無結構定義的資料表上,建立初始的彈性圖表。
定義類型檢視表 (
Person、Company、WorksFor),從無結構定義的資料表中擷取資料並正規化。建立最終的強型別圖,並將這些檢視表做為節點和邊緣資料表。
-- 1. Create the canonical tables for a schemaless model.
CREATE TABLE GraphNode (
id INT64 NOT NULL,
label STRING(MAX) NOT NULL,
properties JSON
) PRIMARY KEY (id);
CREATE TABLE GraphEdge (
id INT64 NOT NULL,
dest_id INT64 NOT NULL,
edge_id INT64 NOT NULL,
label STRING(MAX) NOT NULL,
properties JSON
) PRIMARY KEY (id, dest_id, edge_id),
INTERLEAVE IN PARENT GraphNode;
-- 2. Define a schemaless graph.
CREATE PROPERTY GRAPH FinGraph
NODE TABLES (
GraphNode
DYNAMIC LABEL (label)
DYNAMIC PROPERTIES (properties)
)
EDGE TABLES (
GraphEdge
SOURCE KEY (id) REFERENCES GraphNode(id)
DESTINATION KEY (dest_id) REFERENCES GraphNode(id)
DYNAMIC LABEL (label)
DYNAMIC PROPERTIES (properties)
);
-- 3. Define typed views that extract and formalize the data.
-- Convert JSON fields to primitive types (for example, INT64, STRING) to
-- ensure type safety.
CREATE VIEW Person SQL SECURITY INVOKER AS
SELECT n.id, STRING(n.properties.name) AS name, INT64(n.properties.age) AS age
FROM GraphNode n WHERE n.label = "person";
CREATE VIEW Company SQL SECURITY INVOKER AS
SELECT n.id, STRING(n.properties.name) AS company_name, BOOL(n.properties.is_public) AS is_public
FROM GraphNode n WHERE n.label = "company";
CREATE VIEW WorksFor SQL SECURITY INVOKER AS
SELECT e.id AS person_id, e.dest_id AS company_id, e.edge_id AS edge_id, STRING(e.properties.since) AS since
FROM GraphEdge e
WHERE e.label = "worksfor";
-- 4. Create the final, formalized graph from the typed views.
CREATE PROPERTY GRAPH typed_formalized_graph
NODE TABLES (
Person KEY(id)
PROPERTIES (name, age),
Company KEY(id)
PROPERTIES (company_name, is_public)
)
EDGE TABLES(
WorksFor KEY(person_id, company_id, edge_id)
SOURCE KEY (person_id) REFERENCES Person(id)
DESTINATION KEY (company_id) REFERENCES Company(id)
PROPERTIES (since)
);
後續步驟
進一步瞭解元素鍵不重複性規定。