GaussDB-DELETE
功能描述
DELETE从指定的表里删除满足WHERE子句的行。如果WHERE子句不存在,将删除表中所有行,结果只保留表结构。
注意事项
-
表的所有者、被授予表DELETE权限的用户或被授予DELETE ANY TABLE权限的用户有权删除表中数据,当三权分立开关关闭时,系统管理员默认拥有此权限。同时在进行DELETE操作时,用户也必须拥有USING子句所引用的表以及condition上读取的表的SELECT权限。
-
对于行存复制表,仅支持以下场景的DELETE操作:
- 有主键约束的场景。
- 执行计划能下推的场景。
-
对于子查询是STREAM计划的DELETE语句,不支持删除的行数据同时进行UPDATE更新操作。
语法格式
| ``` [ WITH [ RECURSIVE ] with_query [, ...] ] DELETE [/*+ plan_hint */] [FROM] [ ONLY ] {table_name [ * ] 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 row_count ] [ RETURNING { * | { output_expr [ [ AS ] output_name ] } [, ...] } ];
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
其中with_query的详细格式为:
with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ] ( {select | values | insert | update | delete} )
#### 参数说明
- **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://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0270.html#ZH-CN_TOPIC_0000001865586156)。每条语句中只有第一个/*+ plan_hint */注释块会作为hint生效,里面可以写多条hint。
- **ONLY**
如果指定ONLY则只有该表被删除;如果没有声明,则该表和它的所有子表将都被删除。
- **table_name**
目标表的名称(可以有模式修饰)。
取值范围:已存在的表名。

支持使用DATABASE LINK方式对远端表进行操作,使用方式请参见[DATABASE LINK](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0711.html#ZH-CN_TOPIC_0000001865745520)。
- **subquery**
删除目标对象可以是子查询,在对子查询中的数据进行删除时,会将子查询当成一个临时视图,支持在子查询后面加CHECK OPTION选项。
```
[ 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 } ]} [, ...] ]
[ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
[ into_option ];
```
其中指定子查询源from_item为:
```
{[ ONLY ] {table_name | view_name} [ * ] [ [ 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 [, ...] ) ]}
```
如果子查询中只有一张表,则对该表做删除;如果子查询中有多张表或有嵌套关系,则通过判断是否有保留键表确定是否可删除。关于保留键表和WITH CHECK OPTION请参见[CREATE VIEW](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0577.html#ZH-CN_TOPIC_0000001911665581)。
- **view_name**
目标视图的名称。

对视图和子查询的删除,有如下约束:
- 只有直接引用基表用户列的列可进行DELETE。
- 子查询或视图必须至少包含一个可更新列,关于可更新列请参见[CREATE VIEW](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0577.html#ZH-CN_TOPIC_0000001911665581)。
- 不支持在顶层包含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://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0577.html#ZH-CN_TOPIC_0000001911665581)。
- 不支持对系统视图进行删除。
- 不支持多表删除功能。
- **alias**
目标表的别名。
取值范围:字符串,符合[标识符命名规范](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0321.html#ZH-CN_TOPIC_0000001865746364__zh-cn_topic_0000001704458709_section14873217506)。
- **using_list**
using子句。
- **condition**
一个返回Boolean值的表达式,用于判断哪些行需要被删除。建议不要使用int等数值类型作为condition,因为int等数值类型可以隐式转换为bool值(非0值隐式转换为true,0转换为false),可能导致非预期的结果。
- **WHERE CURRENT OF cursor_name**
当cursor指向表的某一行时,可以使用此语法删除cursor当前指向的行。使用限制及约束请参考[UPDATE](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0698.html#ZH-CN_TOPIC_0000001865745764)章节对此语法介绍。
- **ORDER BY**
关键字详见[SELECT](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0675.html#ZH-CN_TOPIC_0000001911665281)章节介绍。
- **LIMIT**
关键字详见[SELECT](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0675.html#ZH-CN_TOPIC_0000001911665281)章节介绍。
- **output_expr**
DELETE命令删除行之后计算输出结果的表达式,该表达式可以使用表的任意字段,可以使用*返回被删除行的所有字段。
- **output_name**
一个字段的输出名称。
取值范围:字符串,符合[标识符命名规范](https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/devg-dist/gaussdb-12-0321.html#ZH-CN_TOPIC_0000001865746364__zh-cn_topic_0000001704458709_section14873217506)。
#### 示例
- **删除部分数据**
```
--建表。
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);
NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'x1' as the distribution column by default.
HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
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 5 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 cascades to view del_subqry.vv_wco
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);
NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'x1' as the distribution column by default.
HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
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;
DELETE 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语法。
更多详情请参考GaussDB 文档中心:<https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/productdesc/qlh_03_0001.html>