
# DELETE
#### 功能描述
DELETE从指定的表里删除满足WHERE子句的行。如果WHERE子句不存在，将删除表中所有行，结果只保留表结构。
#### 注意事项
- 表的所有者、被授予表DELETE权限的用户或被授予DELETE ANY TABLE权限的用户有权删除表中数据，当三权分立开关关闭时，系统管理员默认拥有此权限。同时也必须有USING子句引用的表以及condition上读取表的SELECT权限。
- 对于多表删除语法，暂时不支持对视图和含有RULE的表进行多表删除。
- 对于子查询是STREAM计划的DELETE语句，不支持删除的行数据同时进行UPDATE更新操作。
 
#### 语法格式
单表删除：
```
[ WITH [ RECURSIVE ] with_query [, ...] ]
DELETE [/*+ plan_hint */] [FROM] [ ONLY ] {table_name [ * ] [ [ [partition_clause]  [ [ AS ] alias ] ] | [ [ [ AS ] alias ] [partitions_clause] ] ] | subquery [ [ AS ] alias ] | view_name [ [ AS ] alias ]}
    [ USING using_list ]
    [ WHERE condition | WHERE CURRENT OF cursor_name ]
    [ ORDER BY { expression  [ ASC | DESC | USING operator ] } ]
    [ LIMIT { count } ]
    [ RETURNING { * | { output_expr [ [ AS ] output_name ] } [, ...] } ];
```
多表删除：
```
[ WITH [ RECURSIVE ] with_query [, ...] ]
DELETE [/*+ plan_hint */] [FROM] 
    {[ ONLY ] table_name [ * ] [ [ [partition_clause]  [ [ AS ] alias ] ] | [ [ [ AS ] alias ] [partitions_clause] ] ]} [, ...]
    [ USING using_list ]
    [ WHERE condition ];
```
或：
```
[ WITH [ RECURSIVE ] with_query [, ...] ]
DELETE [/*+ plan_hint */]
    {[ ONLY ] table_name [ * ] [ [ [partition_clause]  [ [ AS ] alias ] ] | [ [ [ AS ] alias ] [partitions_clause] ] ]} [, ...]
    [ FROM using_list ]
    [ WHERE condition ];
```
- with_query的详细格式为：
  ```
  with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ]
  ( {select | values | insert | update | delete} )
  ```
  

- subquery的详细格式为：
  ```
  [ WITH [ RECURSIVE ] with_query [, ...] ]
  SELECT [/*+ plan_hint */] [ ALL ]
  { * | {expression [ [ AS ] output_name ]} [, ...] }
  [ into_option ]
  [ FROM from_item [, ...] ]
  [ WHERE condition ]
  [ [ START WITH condition ] CONNECT BY [NOCYCLE] condition [ ORDER SIBLINGS BY expression ] ]
  [ ORDER BY {expression [ [ ASC | DESC | USING operator ] | nlssort_expression_clause ] [ NULLS { FIRST | LAST } ]} [, ...] ]
  [ OFFSET start [ ROW | ROWS ] ]
  [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
  [ into_option ];
  ```
  

- 指定子查询源from_item为：
  ```
  {[ ONLY ] {table_name | view_name} [ * ] [ partition_clause ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
  |( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
  |with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
  |from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]}
  ```
  
- partition_clause 的详细格式为：
  ```
  PARTITION { ( partition_name ) | FOR ( partition_value [, ...] ) } |
  SUBPARTITION { ( subpartition_name ) | FOR ( subpartition_value [, ...] ) }
  ```
  
#### 参数说明
- **WITH \[ RECURSIVE \] with_query \[, ...\]**
  用于声明一个或多个可以在主查询中通过名称引用的子查询，相当于临时表。
  如果声明了RECURSIVE，那么允许SELECT子查询通过名称引用它自己。
  - with_query_name指定子查询生成的结果集名称，在查询中可使用该名称访问子查询的结果集。 column_name指定子查询结果集中显示的列名。
    
  
  - 每个子查询可以是SELECT、VALUES、INSERT、UPDATE或DELETE语句。
  
  - 用户可以使用MATERIALIZED或NOT MATERIALIZED对CTE进行修饰。
    - 如果声明为MATERIALIZED，则WITH查询将被物化，生成一个子查询结果集的复制，在引用处直接查询该复制，因此WITH子查询无法和主干SELECT语句进行联合优化（如谓词下推、等价类传递等），对于此类场景可以使用NOT MATERIALIZED进行修饰，如果WITH查询语义上可以作为子查询内联执行，则可以进行上述优化。
    
    - 如果用户没有显示声明物化属性则遵守此规则：如果CTE只在所属主干语句中被引用一次，且语义上支持内联执行，则会被改写为子查询内联执行，否则以CTE Scan的方式物化执行。
     
   
- **plan_hint**
  以/\*+ \*/的形式在DELETE关键字后，用于对DELETE对应的语句块生成的计划进行hint调优，详细用法请参见章节[使用Plan Hint进行调优](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0293.html#ZH-CN_TOPIC_0000002527828150)。每条语句中只有第一个/\*+ plan_hint \*/注释块会作为hint生效，里面可以写多条hint。
  
- **ONLY**
  如果指定ONLY则只有该表被删除，如果没有声明，则该表和它的所有子表将都被删除。
  
- **table_name**
  目标表的名称（可以有模式修饰）。
  取值范围：已存在的表名。
  ![](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  支持使用DATABASE LINK方式对远端表进行操作，使用方式详情请见[DATABASE LINK](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0711.html#ZH-CN_TOPIC_0000002527988336)。
  
- **subquery**
  删除目标对象可以是子查询，在对子查询中的数据进行删除时，会将子查询当成一个临时视图，支持在子查询后面加CHECK OPTION选项。
  如果子查询中只有一张表，则对该表做删除；如果子查询中有多张表或有嵌套关系，则通过判断是否有保留键表确定是否可以进行删除操作。关于保留键表和WITH CHECK OPTION请参见[CREATE VIEW](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0584.html#ZH-CN_TOPIC_0000002527828318)。
  
- **view_name**
  目标视图的名称。
  ![](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  对视图和子查询的删除，有如下约束：
  - 只有直接引用基表用户列的列可进行DELETE操作。
  
  - 子查询或视图必须至少包含一个可更新列，关于可更新列请参见[CREATE VIEW](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0584.html#ZH-CN_TOPIC_0000002527828318)。
  
  - 不支持在顶层包含DISTINCT、GROUP BY、HAVING、LIMIT、OFFSET子句的视图和子查询。
  
  - 不支持在顶层包含集合运算（UNION、INTERSECT、EXCEPT、MINUS）的视图和子查询。
  
  - 不支持目标列表中包含聚集函数、窗口函数、返回集合函数（array_agg、json_agg、generate_series等）的视图和子查询。
  
  - 不支持仅带有BEFORE/AFTER触发器，没有INSTEAD OF触发器或INSTEAD规则的视图。
  
  - 视图和子查询中支持的表类型包括普通表、临时表、全局临时表、分区表、二级分区表、ustore表、astore表。
  
  - 连接视图或子查询只能对视图或子查询中的保留键表做删除操作，如果只存在一张保留键表，则删除该表数据，如果存在多张保留键表，仅删除from后的第一张保留键表的数据。
  
  - 如果连接视图或子查询中指定了CHECK OPTION选项，且基表重复，重复的基表在视图或子查询中保留键表属性不一致，则无法从连接视图或子查询中删除行。关于保留键表请参见[CREATE VIEW](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0584.html#ZH-CN_TOPIC_0000002527828318)。
  
  - 不支持对系统视图进行DELETE操作。
  
  - 不支持多表删除功能。
    
- **partition_clause**
  指定分区删除操作。
  PARTITION { ( partition_name ) \| FOR ( partition_value \[, ...\] ) } \|
  SUBPARTITION { ( subpartition_name ) \| FOR ( subpartition_value \[, ...\] ) }
  关键字详见[SELECT](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0681.html#ZH-CN_TOPIC_0000002559108089)章节介绍。
  示例详见[CREATE TABLE SUBPARTITION](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0577.html#ZH-CN_TOPIC_0000002558948133)。
  
- **partitions_clause**
  指定多个分区删除操作。
  PARTITION { ( { partition_name \| subpartition_name } \[, ...\] ) }
  此语法仅在参数sql_compatibility='B'时生效。
  关键字详见[SELECT](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0681.html#ZH-CN_TOPIC_0000002559108089)章节介绍。
  示例详见[CREATE TABLE SUBPARTITION](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0577.html#ZH-CN_TOPIC_0000002558948133)。
  
- **alias**
  目标表的别名。
  取值范围：字符串，符合[标识符命名规范](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0330.html#ZH-CN_TOPIC_0000002558947985__zh-cn_topic_0000002527058134_section1257443811315)。
  
- **using_list**
  using子句。
  ![](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
  当参数sql_compatibility='B'或删除多张目标表时，using_list指定关联表的集合时可以同时出现目标表，并且可以定义表的别名并在目标表中使用。其他情况下则目标表不可重复出现在using_list中。
  
- **condition**
  一个返回Boolean值的表达式，用于判断哪些行需要被删除。不建议使用int等数值类型作为condition，因为int等数值类型可以隐式转换为bool值（非0值隐式转换为true，0转换为false），可能导致非预期的结果。
  
- **WHERE CURRENT OF cursor_name**
  当cursor指向表的某一行时，可以使用此语法删除cursor当前指向的行。使用限制及约束请参考[UPDATE](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0698.html#ZH-CN_TOPIC_0000002527988332)章节对此语法介绍。
  
- **ORDER BY**
  关键字详见[SELECT](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0681.html#ZH-CN_TOPIC_0000002559108089)章节介绍。
  
- **LIMIT**
  关键字详见[SELECT](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0681.html#ZH-CN_TOPIC_0000002559108089)章节介绍。
  
- **output_expr**
  DELETE命令删除行之后计算输出结果的表达式，该表达式可以使用表的任意字段，可以使用\*返回被删除行的所有字段。
  
- **output_name**
  一个字段的输出名称。
  取值范围：字符串，符合[标识符命名规范](https://support.huaweicloud.com/centralized-devg-v8-gaussdb/gaussdb-42-0330.html#ZH-CN_TOPIC_0000002558947985__zh-cn_topic_0000002527058134_section1257443811315)。
  
 
#### 示例
- **删除部分数据**
  ```
  --建表。
  gaussdb=# CREATE TABLE test_t1(col1 INT,col2 INT);
  gaussdb=# INSERT INTO test_t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (4, 6);
  --删除表中部分记录。
  gaussdb=# DELETE FROM test_t1 WHERE col1 = 4;
  --查询。
  gaussdb=# SELECT * FROM test_t1;
   col1 | col2 
  ------+------
      1 |    1
      2 |    2
      3 |    3
  (3 rows)
  ```
  
- **删除所有数据**
  ```
  --删除所有的数据。
  gaussdb=# DELETE FROM test_t1;
  --查询。
  gaussdb=# SELECT * FROM test_t1;
   col1 | col2 
  ------+------
  (0 rows)
  --删除表。
  gaussdb=# DROP TABLE test_t1;
  ```
  
- **WITH \[ RECURSIVE \] with_query \[, ...\]**
  ```
  --学生表。
  gaussdb=# CREATE TABLE student(id INT,name varchar(50));
  --成绩表。
  gaussdb=# CREATE TABLE grade(id INT,score CHAR);
  gaussdb=# INSERT INTO student VALUES (1, 'tom'), (2, 'jerry'), (3, 'david');
  gaussdb=# INSERT INTO grade VALUES (1, 'A'), (2, 'B'), (3, 'b');
  --在学生表中删除id=2的数据同时删除该学生在成绩表中的数据。
  gaussdb=# WITH del_stu AS(DELETE FROM student WHERE id = 2 RETURNING id)
      DELETE FROM grade WHERE id = (SELECT id FROM del_stu);
  --查询数据。
  gaussdb=# SELECT * FROM student;
   id | name  
  ----+-------
    1 | tom
    3 | david
  (2 rows)
  gaussdb=# SELECT * FROM grade;
   id | score 
  ----+-------
    1 | A
    3 | b
  (2 rows)
  --删除表。
  gaussdb=# DROP TABLE grade;
  gaussdb=# DROP TABLE student;
  ```
  

- **删除视图或子查询**
  示例1：删除子查询
  ```
  --创建SCHEMA。
  gaussdb=# CREATE SCHEMA del_subqry;
  CREATE SCHEMA。
  gaussdb=# SET CURRENT_SCHEMA = 'del_subqry';
  SET
  --创建表并插入数据。
  gaussdb=# CREATE TABLE t1 (x1 int, y1 int);
  CREATE TABLE
  gaussdb=# CREATE TABLE t2 (x2 int PRIMARY KEY, y2 int);
  NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "t2_pkey" for table "t2"
  CREATE TABLE
  gaussdb=# CREATE TABLE tdata (x INT PRIMARY KEY, y INT);
  NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "tdata_pkey" for table "tdata"
  CREATE TABLE
  gaussdb=# CREATE TABLE tinfo (z INT PRIMARY KEY, comm VARCHAR2(20));
  NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "tinfo_pkey" for table "tinfo"
  CREATE TABLE
  gaussdb=# INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (5, 5);
  INSERT 0 4
  gaussdb=# INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3), (5, 5);
  INSERT 0 4
  gaussdb=# INSERT INTO tdata VALUES (1, 1), (2, 2), (3, 3);
  INSERT 0 3
  gaussdb=# INSERT INTO tinfo VALUES (1,'one'), (2, 'two'), (3, 'three'), (5, 'wrong three');
  INSERT 0 4
  --通过子查询删除t1中的数据。
  gaussdb=# DELETE FROM (SELECT * FROM t1) where y1 = 3;
  DELETE 1
  --子查询带READ ONLY，无法删除数据。
  gaussdb=# DELETE FROM (SELECT * FROM t1 WITH READ ONLY) WHERE y1 = 1;
  ERROR:  cannot perform a DML operation on a read-only subquery.
  --对多表连接的子查询删除。
  gaussdb=# SELECT * FROM t1, t2 WHERE x1 = x2;
   x1 | y1 | x2 | y2
  ----+----+----+----
    1 |  1 |  1 |  1
    2 |  2 |  2 |  2
    5 |  5 |  5 |  5
  (3 rows)
  gaussdb=# DELETE FROM (SELECT * FROM t1, t2 WHERE x1 = x2) WHERE y2 = 5;
  DELETE 1
  gaussdb=# SELECT * FROM t1, t2 WHERE x1 = x2;
   x1 | y1 | x2 | y2
  ----+----+----+----
    1 |  1 |  1 |  1
    2 |  2 |  2 |  2
  (2 rows)
  --子查询带CHECK OPTION，tdata表重复，其中 td1不是保留键表，td2是保留键表。
  gaussdb=# DELETE FROM (SELECT td1.x x1, td1.y y1, td2.x x2, td2.y y2 FROM tdata td1, tdata td2, tinfo WHERE td2.y=tinfo.z AND td1.x=td2.y WITH CHECK OPTION) WHERE y1 = 2;
  ERROR:  cannot delete from view without exactly one key-preserved table
  --不带CHECK OPTION，创建同样结构的子查询，删除成功。
  gaussdb=# DELETE FROM (SELECT td1.x x1, td1.y y1, td2.x x2, td2.y y2 FROM tdata td1, tdata td2, tinfo WHERE td2.y=tinfo.z AND td1.x=td2.y) WHERE y1 = 2;
  DELETE 1
  --删除SCHEMA。
  gaussdb=# RESET CURRENT_SCHEMA;
  RESET
  gaussdb=# DROP SCHEMA del_subqry CASCADE;
  NOTICE:  drop cascades to 4 other objects
  DETAIL:  drop cascades to table del_subqry.t1
  drop cascades to table del_subqry.t2
  drop cascades to table del_subqry.tdata
  drop cascades to table del_subqry.tinfo
  DROP SCHEMA
  ```
  
  示例2： 删除视图
  ```
  --创建SCHEMA。
  gaussdb=# CREATE SCHEMA del_view;
  CREATE SCHEMA
  gaussdb=# SET CURRENT_SCHEMA = 'del_view';
  SET
  --创建表并插入数据。
  gaussdb=# CREATE TABLE t1 (x1 int, y1 int);
  CREATE TABLE
  gaussdb=# CREATE TABLE t2 (x2 int PRIMARY KEY, y2 int);
  NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "t2_pkey" for table "t2"
  CREATE TABLE
  gaussdb=# CREATE TABLE tdata (x INT PRIMARY KEY, y INT);
  NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "tdata_pkey" for table "tdata"
  CREATE TABLE
  gaussdb=# CREATE TABLE tinfo (z INT PRIMARY KEY, comm VARCHAR2(20));
  NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "tinfo_pkey" for table "tinfo"
  CREATE TABLE
  gaussdb=# INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (5, 5);
  INSERT 0 4
  gaussdb=# INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3), (5, 5);
  INSERT 0 4
  gaussdb=# INSERT INTO tdata VALUES (1, 1), (2, 2), (3, 3);
  INSERT 0 3
  gaussdb=# INSERT INTO tinfo VALUES (1,'one'), (2, 'two'), (3, 'three'), (5, 'wrong three');
  INSERT 0 4
  --创建单表视图。
  gaussdb=# CREATE VIEW v_del1 AS SELECT * FROM t1;
  CREATE VIEW
  gaussdb=# CREATE VIEW v_del_read AS SELECT * FROM t1 WITH READ ONLY;
  CREATE VIEW
  --通过视图删除t1中的数据。
  gaussdb=# DELETE FROM v_del1 where y1 = 3;
  DELETE 1
  --视图带READ ONLY，无法删除数据。
  gaussdb=# DELETE FROM v_del_read WHERE y1 = 1;
  ERROR:  cannot perform a DML operation on a read-only subquery.
  --创建多表连接视图。
  gaussdb=# CREATE VIEW vvt1t2 AS SELECT * FROM t1, t2 WHERE x1 = x2;
  CREATE VIEW
  gaussdb=# CREATE VIEW vv_dup AS SELECT td1.x x1, td1.y y1, td2.x x2, td2.y y2 FROM tdata td1, tdata td2, tinfo WHERE td2.y=tinfo.z AND td1.x=td2.y;
  CREATE VIEW
  gaussdb=# CREATE VIEW vv_dup_wco AS SELECT td1.x x1, td1.y y1, td2.x x2, td2.y y2 FROM tdata td1, tdata td2, tinfo WHERE td2.y=tinfo.z AND td1.x=td2.y WITH CHECK OPTION;
  CREATE VIEW
  --对多表连接的视图做删除操作。
  gaussdb=# SELECT * FROM vvt1t2;
   x1 | y1 | x2 | y2
  ----+----+----+----
    1 |  1 |  1 |  1
    2 |  2 |  2 |  2
    5 |  5 |  5 |  5
  (3 rows)
  gaussdb=# DELETE FROM vvt1t2 WHERE y2 = 5;
  DELETE 1
  gaussdb=# SELECT * FROM vvt1t2;
   x1 | y1 | x2 | y2
  ----+----+----+----
    1 |  1 |  1 |  1
    2 |  2 |  2 |  2
   (2 rows)
  --视图带CHECK OPTION，tdata表重复，其中 td1不是保留键表，td2是保留键表。
  gaussdb=# DELETE FROM vv_dup_wco WHERE y1 = 2;
  ERROR:  cannot delete from view without exactly one key-preserved table
  --不带CHECK OPTION，创建同样结构的视图，删除成功。
  gaussdb=# DELETE FROM vv_dup WHERE y1 = 2;
  DELTE 1
  --删除SCHEMA。
  gaussdb=# RESET CURRENT_SCHEMA;
  RESET
  gaussdb=# DROP SCHEMA del_view CASCADE;
  NOTICE:  drop cascades to 9 other objects
  DETAIL:  drop cascades to table del_view.t1
  drop cascades to table del_view.t2
  drop cascades to table del_view.tdata
  drop cascades to table del_view.tinfo
  drop cascades to view del_view.v_del1
  drop cascades to view del_view.v_del_read
  drop cascades to view del_view.vvt1t2
  drop cascades to view del_view.vv_dup
  drop cascades to view del_view.vv_dup_wco
  DROP SCHEMA
  ```
  
 
#### 优化建议
- DELETE 如果要删除表中的所有记录，建议使用TRUNCATE语法。
  
 
