Create a graph from a SQL view

Learn how to create a graph using SQL views . This document provides step-by-step instructions and code examples for defining views and using them to define node and edge tables. Explore examples with sample code that demonstrate use cases for creating graphs with views. To learn more about using views to create a property graph, including benefits and considerations, see Overview of graphs created from SQL views .

Before you begin

To create a graph, you must:

  1. Ensure your Spanner Graph environment is set up .

  2. Familiarize yourself with how Spanner Graph schemas work .

Create a graph using views

To create a graph using views:

  1. Define views for your graph. Make sure your views follow one of the required view patterns . For more information, see Create a view .

  2. Use your views in the NODE TABLES and EDGE TABLES clauses of the CREATE PROPERTY GRAPH statement to create a graph.

  3. Include the KEY clause in the CREATE PROPERTY GRAPH statement. The KEY clause specifies the columns from the source view that uniquely identify each graph element.

Example: Create a graph using views

This example creates the following views over Customer and Account tables: AsiaCustomer , AsiaBankAccount , and AsiaAccountsOwnership . Then, the example uses these views to create the following in a graph:

  • Create the Customer node table using the AsiaCustomer view.

  • Create the Account node table using the AsiaBankAccount view.

  • Create the Owns edge table using the AsiaAccountsOwnership view. This edge connects Customer nodes with Account nodes.

Step 1: Create the tables

First, create the data tables. The following code creates the Customer and Account tables.

  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 
 ); 
 

Step 2: Create the views

Next, create views to transform or filter data from the tables. These views filter the tables to include only customers and accounts in Asia. Views used to create graph elements must ensure that rows in the view are unique .

  -- 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" 
 ; 
 

Step 3: Create the property graph

Now, create the AsiaFinGraph using the views you created. The CREATE PROPERTY GRAPH statement includes the KEY clause for each graph element definition to specify columns that uniquely identify the graph elements.

  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 
 ) 
  
 ); 
 

Use cases examples

SQL views offer benefits over using tables for property graph elements. The following examples demonstrate some use cases for defining graph elements with views instead of tables.

Example: Enforce fine-grained graph data access control

To enforce row-level security on your graph data, define your node or edge tables using definer's rights views . The view exposes a permitted subset of the underlying data to the graph

For example, to restrict graph access to only employees in an engineering cost center, you can create an EngineerEmployeeView view and grant SELECT permissions on the view to an engineering_data_reader role using the GRANT clause.

When you define a graph node table using this view, users running graph queries with the engineering_data_reader role can see only the rows filtered by the view, which include engineering employees.

  -- 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 
 ) 
  
 ); 
 

Example: Model derived graph elements

You can use views to define graph elements that require data transformations. A key benefit is that the view defines the transformation, so you don't need to maintain a separate table for the derived data.

For example, you can UNNEST data from an ARRAY column (or an array field within a JSON column) to model multiple edge relationships from a single row.

In the following supply chain schema example, a Parts table stores a list of sub-components in a dependent_parts array. A view can use the UNNEST operator to transform each element of that array into distinct rows. This view can then serve as an edge table, letting you model a PartDependsOnPart edge to represent dependency relationships between parts.

  -- 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 
 ) 
  
 ); 
 

Example: Schemaless data transition

Schemaless data management lets you create a flexible graph definition without predefined node and edge types. While schemaless data management provides flexibility, you might need to transition to a more formal structure as your data becomes more defined. A more formal structure exposes the graph's node and edge relationships, labels, and properties in the schema, which reduces the need for manual data exploration to understand the graph schema.

You can use views to formalize the node and edge types without migrating your underlying data. For example, you can transition from a typical schemaless model that uses canonical GraphNode and GraphEdge tables. To do this, you create views that extract the data from your schemaless tables:

  1. Define a view for each node and edge type you want to formalize (for example, Person or WorksFor ). In the view, filter the data by its label (for example, WHERE n_label = "person" ) and cast the properties from the JSON column to specific data types (for example, STRING(prop.name) AS name ).

  2. Define a new property graph where NODE TABLES and EDGE TABLES reference the typed views you just created.

A schemaless graph provides better performance than a formalized graph for some queries (for example, a quantified path pattern with multiple edge types). If formalized metadata is important for your use case, then you can use views to transition from a schemaless graph to a typed schema. You can also choose to use a schemaless graph for some use cases and a typed schema graph for other use cases. For more information, see Choose a schema design based on graph queries .

The following example demonstrates the workflow for transitioning from a schemaless to a formalized graph in four steps:

  1. Define the canonical GraphNode and GraphEdge tables for the schemaless model.

  2. Create an initial, flexible graph on those schemaless tables.

  3. Define typed views ( Person , Company , WorksFor ) that extract and formalize the data from the schemaless tables.

  4. Create the final, strongly-typed graph that uses these views as its node and edge tables.

  -- 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 
 ) 
  
 ); 
 

What's next

Design a Mobile Site
View Site in Mobile | Classic
Share by: