Source: https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/dml/insert/ Documentation version: v5.3.2 # INSERT `INSERT`语句用于往图或临时图中插入点和边。 Note 对非默认 Schema 或其中的对象执行操作时,用户既要通过隐式访问规则或显式`USAGE`授权获得该 Schema 的访问权,也要具备目标操作所需的权限。Schema 访问校验和目标操作所需的权限校验相互独立,满足其中一项不能替代另一项。Schema 访问控制不适用于临时图、内置 Procedure 和内置 Function。更多信息,请参见 [Schema 访问控制](https://dev-docs.yueshu.com.cn/v5.3.2/server-admin/authorization/schema-access-control/)。 ## 前提条件 - 已创建图或临时图。更多信息,请参见 [CREATE GRAPH](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/ddl/graph/create/) 和 [CREATE TEMPORARY GRAPH](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/ddl/graph-projection/create/)。 - 若要往图中插入点和边,须具备在当前 Schema 执行`INSERT ANY GRAPH`操作的权限,或具备在当前图中执行`INSERT`操作的权限。更多信息,请参见[角色与权限](https://dev-docs.yueshu.com.cn/v5.3.2/server-admin/authorization/)。 - 若要往临时图中插入点和边,必须是具备角色`ADMIN`的用户或临时图的所有者。 ## 语法 语法图源码 insert_statement insert_path_pattern insert_element_pattern_filler insert_edge_pattern ```` insert_statement ::= ( 'INSERT' | 'INSERT' 'OR' 'REPLACE' | 'INSERT' 'OR' 'IGNORE' | 'INSERT' 'OR' 'UPDATE' ) insert_path_pattern ( ',' insert_path_pattern )* insert_path_pattern ::= '(' insert_element_pattern_filler ')' ( insert_edge_pattern '(' insert_element_pattern_filler ')' )* insert_element_pattern_filler ::= (element_variable_declaration? ( ( ('IS' | ':') label_name ( '&' label_name )* ) | ( ( 'TYPED' | '@' ) element_type_name ) ) '{' property_name ':' value_expression ( ',' property_name ':' value_expression )* '}') | element_variable_declaration insert_edge_pattern ::= '<-[' ( insert_element_pattern_filler )? ']-' | '-[' ( insert_element_pattern_filler )? ']->' | '~[' ( insert_element_pattern_filler )? ']~' ```` ## 参数 ### `INSERT | INSERT OR REPLACE | INSERT OR IGNORE | INSERT OR UPDATE` []() 插入点和边时,可以选择以下模式处理已存在的数据: | 写入模式 | 行为 | `INSERT` | 数据不存在时插入;已存在时,语句执行失败并报告错误。 | `INSERT OR REPLACE` | 数据不存在时插入;已存在时,用本次提交的数据替换原有点或边。 | `INSERT OR IGNORE` | 数据不存在时插入;已存在时,忽略本次写入,保留原有数据,不报错。 | `INSERT OR UPDATE` | 数据不存在时插入;已存在时,用本次提交的属性值更新原有点或边。 数据是否已存在,按以下键冲突规则判断: - 对于相同点类型的点,待插入点的主键与已有点的主键相同。 - 对于相同边类型的边: - 若定义过多边键,待插入边的多边键、起始点和目标点与已有边的多边键、起始点和目标点均相同。 - 若未定义多边键,待插入边的起始点和目标点与已有边的起始点和目标点相同。 ### `element_variable_declaration` 声明图元素点或边的变量,以便引用和操作这些图元素。该变量为一个标识符。更多信息,请参见[标识符命名规则](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/overview/keywords-identifiers/)。 ### `label_name` 图元素点或边的标签名称。该名称为一个标识符。更多信息,请参见[标识符命名规则](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/overview/keywords-identifiers/)。 ### `property_name` 属性的名称。该名称为一个标识符。更多信息,请参见[标识符命名规则](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/overview/keywords-identifiers/)。 ### `value_expression` 属性的值。更多信息,请参见[值表达式](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/fe/#_6)。 ### `element_type_name` 点类型或边类型的名称。该名称为一个标识符。更多信息,请参见[标识符命名规则](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/overview/keywords-identifiers/)。 ## 示例 以下示例基于[示例数据集](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/overview/example-dataset/)中的创建的图`movie`和图类型`movie_type`,展示如何使用`INSERT`语句。 在执行以下示例语句前,假设您已执行`SESSION SET GRAPH movie`语句将图`movie`设置为当前工作图;否则,需要在语句的开头指定图名称,如`USE movie`。更多信息,请参见 [USE](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/dql/clauses/use-graph/)。 ### 指定点类型插入点 ```` ''' INSERT (@Director{id:11, name:"Alice", birthDate:date("1990-01-01")}), (TYPED Actor{id:22, name:"Bob", birthDate:date("1990-01-02")}) ''' ```` 上述语句插入了一个点类型为`Director`的点和一个点类型为`Actor`的点。符号`@`和关键字`TYPED`都可用于指定点类型。 ### 通过`INSERT OR REPLACE`插入有冲突的点 ```` INSERT OR REPLACE (@Director{id:11, name:"Alice2"}) ```` 上述语句写入一个点类型为`Director`的点。如果图中不存在主键`id`为`11`的`Director`点,则插入;如果已存在,则用本次提交的数据替换已有点。 执行以下语句验证插入结果: ```` MATCH (n@Director{id:11}) RETURN n ```` 返回: ```` +------------------------------------------------------------------------+ | n | +------------------------------------------------------------------------+ | (288606709776121860@Director:Person{birthDate:null,id:11,name:Alice2}) | +------------------------------------------------------------------------+ ```` ### 通过`INSERT OR IGNORE`插入点并保留已有数据 本例接着上一个`INSERT OR REPLACE`示例执行。此时,图中已存在`id`为`11`的`Director`点,其`name`为`Alice2`、`birthDate`为`NULL`。假设图中尚不存在`id`为`12`的`Director`点。 执行以下语句,分别提交一个与已有点主键相同的点和一个尚不存在的点: ```` ''' INSERT OR IGNORE (@Director{id:11, name:"Alice3", birthDate:date("1990-06-30")}), (@Director{id:12, name:"Carol", birthDate:date("1991-01-01")}) ''' ```` - `id`为`11`的点已存在:跳过该点的本次写入,`name`仍为`Alice2`,`birthDate`仍为`NULL`。 - `id`为`12`的点不存在:正常插入,`name`为`Carol`,`birthDate`为`1991-01-01`。 执行以下语句验证结果: ```` ''' MATCH (n@Director) WHERE n.id IN [11, 12] RETURN n.id AS id, n.name AS name, n.birthDate AS birthDate ORDER BY id ''' ```` 返回: | id | name | birthDate | 11 | Alice2 | `NULL` | 12 | Carol | 1991-01-01 ### 通过`INSERT OR UPDATE`插入有冲突的点 ```` INSERT OR UPDATE (@Director{id:11, name:"Alice4", birthDate:date("1990-12-31")}) ```` 上述语句写入一个点类型为`Director`的点。如果图中不存在主键`id`为`11`的`Director`点,则插入;如果已存在,则更新已有点的属性。 执行以下语句验证插入结果: ```` MATCH (n@Director{id:11}) RETURN n ```` 返回: ```` +------------------------------------------------------------------------------+ | n | +------------------------------------------------------------------------------+ | (288606709776121860@Director:Person{birthDate:1990-12-31,id:11,name:Alice4}) | +------------------------------------------------------------------------------+ ```` ### 指定标签插入点 ```` ''' INSERT (:Movie{id:10000,name:"movie"}), (IS Genre{id:11000,name:"genre"}) ''' ```` 上述语句插入了一个标签为`Movie`的点和一个标签为`Genre`的点。符号`:`和关键字`IS`都可用于指定标签。 ### 插入具有 NULL 值的点 ```` INSERT (@Movie{id:10002,name:NULL}) ```` 上述语句插入了一个点类型为`Movie`的点,并且属性`name`的值为`NULL`。 ### 基于已存在的点插入边 ```` ''' MATCH (n@Movie{id:10000}), (m@User{id:1}) INSERT (n)<-[:Watch{rate:5}]-(m) ''' ```` 上述语句匹配已存在的点`n`和`m`,并插入一条从点`m`到点`n`的边,边的标签为`Watch`,并且边的属性`rate`的值为`5`。 ### 同时插入新的点和边 ```` ''' INSERT (@Actor{id:200000,name:"actor", birthDate:date("1990-01-01")}) -[@Act]-> (@Movie{id:10003,name:"movie1"}) ''' ```` 上述语句插入一个点类型为`Actor`的点和一个点类型为`Movie`的点,然后插入一条从点`Actor`到点`Movie`的边,边的类型为`Act`。 ### 基于已存在的点插入点和边 ```` ''' MATCH (n@Movie{id:10000}) INSERT (n)<-[@Watch{rate:5}]-(@User{id:11002}) ''' ```` 上述语句匹配已存在点`n`,并插入一个新点,点类型为`User`,以及一条从新点到`n`的边,边的类型为`Watch`,并且边的属性`rate`的值为`5`。 ### 基于已存在的点插入多个点和边 ```` ''' MATCH (n@User{id:1}) INSERT (n)-[@Watch{rate:5}]->(m@Movie{id:10004,name:"movie2"}), (m)-[@WithGenre]->(@Genre{id:11003,name:"genre3"}) ''' ```` 上述语句匹配已存在的点`n`,插入一个新点,点类型为`Movie`,以及一条从`n`到新点的边,边的类型为`Watch`,并且边的属性`rate`的值为`5`。然后再插入一个新点,点类型为`Genre`,以及一条从点`m`到新点的边,边的类型为`WithGenre`。 ### 使用表变量批量插入点和边 ```` ''' TABLE t { actor_id, movie_id, movie_name } = ( 2, 20001, 'Movie1' ), ( 3, 20002, 'Movie2' ), ( 4, 20003, 'Movie3' ) USE movie FOR re IN t MATCH (a@Actor) WHERE a.id = re.actor_id INSERT (a)-[@Act]->(@Movie {id: re.movie_id, name: re.movie_name}) ''' ```` 上述语句定义了表变量`t`,并遍历表变量将数据插入到图`movie`中。该语句基于表变量的字段`actor_id`匹配点类型为`Actor`的点,并基于字段`movie_id`和`movie_name`的值插入点类型为`Movie`的点,并在这些点之间插入边。 关于使用表变量进行批量操作的更多信息,请参见[定义表变量](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/variable-definition/table-variable/)。 ### 跨图插入点和边 ```` ''' // 创建新图 CREATE GRAPH IF NOT EXISTS another_movie TYPED movie_type ''' ''' USE movie MATCH (a@Actor)-[@Act]->(m@Movie) RETURN a AS actor, m AS movie NEXT USE another_movie INSERT OR REPLACE (@Actor{id:actor.id, name:actor.name, birthDate:actor.birthDate})-[@Act]-> (@Movie{id:movie.id, name:movie.name}) ''' ```` 上述语句创建了一个新图`another_movie`,从已存在的图`movie`中匹配点和边,并将匹配到的点和边插入到新图`another_movie`中。