SQL DELETE 语句

SQL Server DELETE 命令是一个 DML(数据操作语言)语句,用于从数据库表或视图中删除一个或多个现有行。DELETE 语句对于维护数据库中表的数据完整性和准确性至关重要。

与删除表中所有记录的 TRUNCATE 命令不同,SQL DELETE 语句对行删除有更多的控制。主要优点是 DELETE 允许您使用 WHERE 子句指定条件。因此,您可以根据单个条件或多个条件删除记录。否则,可以删除多条记录或整个数据集。

通常,在一个组织中,一段时间后,我们存储在数据库中的数据量会增长,这些记录可能与当前情况无关或已过时。要删除这些过时的记录或清理日志,您可以使用 SQL Server DELETE 语句。

与从数据库中删除整个表的 DROP 命令不同,DELETE 语句根据条件(如果有)删除行,并保留表结构、约束等。

提示:一旦执行 SQL DELETE 命令,除非使用事务,否则无法逆转该过程并检索数据。

SQL DELETE 语句语法

SQL DELETE 命令的基本语法,以及用于对 SELECT 语句应用条件的 WHERE 子句是:

DELETE FROM [Table_Name] 
WHERE Condition

如果您查看语法,我们没有在 SQL DELETE 语句中提到列列表。因为删除操作是按行执行的,所以我们需要表名。让我为您分解语法。

  • Table_Name:要执行删除操作的表的名称。
  • WHERE Condition:这是一个可选参数,提供删除的过滤器或条件。如果条件为 TRUE,则此语句将从给定表中删除记录。

在 WHERE 子句的帮助下,您可以根据条件删除单个单词或多条记录。但是,如果您完全省略 WHERE 子句,SQL DELETE 语句将删除表中的所有记录。

除了上述简单语法之外,还有一个包含 TOP 子句的复杂语法。

DELETE [TOP(Value) [PERCENT]]
FROM Table_Name
[WHERE condition]

TOP (Value) | PERCENT:这里,TOP 子句是一个可选参数,如果您使用它,SQL DELETE 语句将根据给定的整数或百分比值从表中删除前面的几条记录。

让我向您展示一些您在实际中可能遇到的最常见示例。它包括删除表中的所有记录、单行、多行、单个条件和多个条件等。在本文中,我们将使用下表执行不同类型的 DELETE 操作。

Source Table

要避免的常见错误

在我们深入研究 SQL DELETE 语句示例之前,让我向您展示实际中要避免的最常见错误。

  • 在编写 DELETE 查询时,忘记 WHERE 子句并执行是一个常见且代价高昂的错误。
  • 在清空表时使用 DELETE 命令而不是 TRUNCATE 语句
  • 在删除记录之前忘记备份表。
  • 在对父子表执行 DELETE 操作时理解参照完整性。

提示:您可以使用逻辑运算符来组合 WHERE 子句中的多个条件。

SQL 删除单行

SQL Server DELETE 语句允许您从给定表中删除单行或记录。想象一下有一个 Employee 表,您想删除一个不在组织中工作的员工。在这种情况下,您可以使用 WHERE 条件根据员工 ID 过滤表。然后,删除该特定行。

要执行这些操作,您必须使用比较运算符,如 =、<=、>= 等来检查条件。为了演示这一点,我们将从 employee 表中删除 EmpID = 2。

DELETE FROM [Employee]
WHERE [EmpID] = 2

它将删除 ID 值为 2 的员工记录,这是一条记录。假设没有行满足条件(没有 ID 为 2 的员工),则上述语句不执行任何操作。

根据多个条件删除单条记录

上面的 SQL 示例是一个简单的示例,因为我们在 WHERE 子句中使用单个条件从表中删除单行。但是,在某些情况下,我们必须检查多个条件以确保我们删除了完全匹配的行。

例如,在上表中,我们有三名员工的名字都叫 John,更糟糕的是,其中两条记录的教育和职业甚至都相同。在这种情况下,我们使用 逻辑 AND 操作来匹配名字和姓氏,以删除特定记录。

DELETE FROM [Employee]
WHERE [FirstName] = 'John' AND [LastName] = 'Ruiz'

注意:如果您不小心忘记了 WHERE 子句,那么您最终将删除源中的所有记录。

SQL 删除表中的多行

在某些情况下,需要删除表中的多条记录。例如,删除绩效不佳或旧的部门。另一种情况是删除整个城市或州的数据。假设以下查询删除了所有属于洛杉矶的客户。

DELETE FROM Customers WHERE City = 'Los Angeles'

让我给您一个快速示例来演示多列的删除。以下查询将删除表中教育资格为“部分高中”的所有记录。

DELETE FROM [Employee]
WHERE [Education] = 'Partial High School'

提示:使用 @@ROWCOUNT 显示语句删除的记录总数。

SQL DELETE Statement to Remove a Single row

SQL 根据多个条件删除多行

与上述 SQL DELETE 语句或命令示例类似,我们可以使用多个条件创建更复杂的查询以获得精确的结果集。在此示例中,我们使用 WHERE 子句中的 AND 运算符在开始删除记录之前检查多个条件。第一个条件测试职业是否为“专业人士”,AND 运算符是连接词。下一个条件检查年收入是否小于 90000。如果两个条件都为 TRUE,则该员工记录将从表中删除。

DELETE FROM [Employee]
WHERE [Occupation] = 'Professional' AND [YearlyIncome] < 90000

使用 BETWEEN 运算符删除多行

如果将 SQL DELETE 语句与 BETWEEN 运算符和逻辑 AND 运算符一起使用,则可以删除范围内的行。例如,删除特定日期范围(从 A 到 B 日期)内的客户、订单或员工。

以下示例删除在“2006-01-27 AND ‘2007-01-28’”之间入职(他们的雇佣日期)的员工。

DELETE FROM [Employee]
WHERE [HireDate] BETWEEN '2006-01-27' AND '2007-01-28'

使用 SQL 中的 IN 运算符删除多行

上述示例对于删除一系列记录或与多个或单个条件匹配的行很有用。但是,在某些情况下,我们必须删除特定的一组单个记录。例如,删除不同的员工或学生 ID。

下面的 IN 查询删除了 ID 值为 5、10、12 和 15 的员工。

DELETE FROM [Employee]
WHERE EmpID IN (5, 10, 12, 15)

SQL 删除表中的所有行

SQL Server 允许您删除表中的所有记录或行,而不会干扰表结构。当您想删除所有旧的或不需要的数据时,这非常有用。

如果您需要清空表,可以通过以下三种选项之一实现:首先,简单地省略 WHERE 子句。

DELETE FROM table_name

其次,使用 WHERE 子句,条件始终返回 TRUE(1 = 1)。

DELETE FROM table_name WHERE 1 = 1

第三,使用 *(星号)选择所有行。

DELETE * FROM table_name

尽管我们可以使用这三个选项中的任何一个来实现目标,但始终选择第一个 SQL DELETE 语句选项,它直接删除表中存在的所有记录。所以,让我使用相同的选项来清空上面提到的表。

DELETE FROM Employee

由于上述查询清空了现有表,让我从备份中插入这 15 条记录以执行后续操作。

SQL DELETE Statement to remove multiple and all rows

SQL Server DELETE TOP 子句

SQL Server 允许您将 TOP 子句与 DELETE 语句一起使用,以根据数字或给定百分比删除前面几条记录。例如,如果您想从表中删除前 50 行或 10% 的记录,请使用此 TOP 子句。

在此示例中,我们从表中删除年收入小于或等于 5000 的第一条记录。对于此示例,我们使用带有 TOP 子句和 WHERE 语句的 DELETE 命令。

WHERE 子句将检查年收入小于或等于 5000 的记录,然后 TOP 子句将选择第一条记录。最后,DELETE 命令将删除该记录。

DELETE TOP (1) FROM [Employee]
WHERE [YearlyIncome] <= 50000

如果您的目标是删除前 3 条记录,无论条件如何,您可以省略 WHERE 子句。

DELETE TOP (3) FROM [Employee]

子查询中的 ORDER BY

请记住,DELETE TOP 子句按照记录在表中保存的顺序选择和删除记录。如果您对要删除的记录有特定要求,请在语句中使用 SQL ORDER BY 子句,根据列以 ASC 或 DESC 顺序对它们进行排序。为了演示这一点,您必须使用子查询。

以下查询从表中删除前五名员工记录,按他们的年收入(最低收入)排序。

DELETE FROM [Employee] WHERE [EmpID] IN (
SELECT TOP 5 EmpID FROM Employee
ORDER BY YearlyIncome ASC)

带 CTE

除了上述子查询选项外,您还可以使用公共表表达式 (CTE) 以特定方式获取排序结果。接下来,在 CTE 上执行 SQL DELETE 操作,而不是在表上执行。

以下查询创建一个 CTE,该 CTE 选择年收入大于 5000 的前五名员工,按收入降序排列。接下来,DELETE 语句使用 CTE 删除这些记录。

WITH Test
AS (
SELECT TOP 5 EmpID FROM Employee
WHERE [YearlyIncome] > 50000
ORDER BY YearlyIncome DESC )

DELETE FROM Test
Delete and TOP clause

DELETE 命令中的 SQL 事务

在执行数据操作(例如 DELETE 操作)时,您必须使用 TRANSACTION 概念。它有助于避免错误并将数据回滚到原始状态,这样您就不必从备份中恢复数据。

这意味着您以 BEGIN TRANSACTION、DELETE COMMAND、ROLLBACK(出现问题)开始查询,否则 COMMIT TRANSACTION。如果在 DELETE 命令之后使用 ROLLBACK TRANSACTION,您可以将表数据恢复到起始位置或任何保存点,而无需从备份中恢复数据。

BEGIN TRANSACTION
DELETE FROM Employee WHERE Occupation = 'Professional'
-- SELECT * FROM Employee
ROLLBACK TRANSACTION
-- SELECT * FROM Employee

请尝试取消注释上述查询中的 SELECT 语句,以实时查看 TRANSACTION 的魔力。

带 JOIN 查询的 SQL DELETE 命令

在某些情况下,我们需要根据在另一个表中测试的条件从一个表中删除记录。在这种情况下,我们使用 JOIN 概念来连接两个或更多表并执行删除。第一张图将显示 Department 表中的日期。

让我根据另一个表中的部门名称从 employee 表中删除记录。为此,我们使用 内连接 和 SQL DELETE 语句来连接两个表。以下查询删除所有部门名称为 Sr. Software Developer 的记录。请记住,部门名称来自 Department 表。

DELETE  e 
FROM [Employee] AS e
INNER JOIN Department AS d ON e.[DeptID] = d.id
WHERE d.DepartmentName = 'Sr. Software Developer'

如果您有 AdventureWorksDW 数据库,您可以使用以下查询删除男性客户的销售记录。尝试在 DimGeography 上进行实验,按国家、州、城市和邮政编码删除销售记录。

DELETE fact  
FROM FactInternetSales fact
JOIN DimCustomer cus ON fact.CustomerKey = cus.CustomerKey
WHERE cus.Gender = 'M'

使用另一个表删除行

在实际中,为了维护公共数据,在某些情况下,我们必须将一个表(原始表)中的数据与源表进行比较。如果源表和目标表中有一些重复或公共记录,那么我们必须从这些表中删除它们。在这种情况下,我们可以连接两个表并在一个表上执行 SQL Server DELETE 操作。

以下查询将删除 Employee 表中所有 ID 与 Emp 表相同的匹配记录。

DELETE Employee
FROM Employee
JOIN Emp ON Employee.EmpID = Emp.EmpID

以下查询删除 Employee 表中所有与 Emp 不匹配的记录。

DELETE Employee
FROM Employee
JOIN Emp ON Employee.EmpID != Emp.EmpID

SQL DELETE 命令外键错误修复!

通常,数据库表的设计方式是它们使用主键和外键关系相互连接。在创建父子关系时,参照完整性在执行 SQL Server DELETE 操作中起着主要作用。

如果您观察默认的 Adventure Works 数据库,大多数外键都标记为“无操作参照完整性”。因此,当您尝试从主表中删除记录时,如果子表有依赖记录,则查询将抛出错误。避免孤立记录非常重要。例如,如果您尝试从 Department 表中删除记录,它将抛出错误,因为 Dept ID 在 Employee 表中有引用。

为了处理孤立记录,您可以编写一个 SQL DELETE 语句来删除主表中的记录以及 Employee 表中所有相关的员工。要实现相同目的,您有两个选项。

选项 1:CASCADE DELETE

如果您已经使用 CASCADE DELETE 参照完整性创建了外键,那么这是一种简单直接的技术。以下查询将删除部门名称为“经理”的部门以及所有 ID 值为 6(经理)的员工记录。

DELETE FROM Department 
WHERE DepartmentName = ‘Manager’

选项 2:多个 DELETE 查询

如果您没有使用 CASCADE 创建外键,那么上述查询将抛出错误。为了解决这个问题,您必须运行两个单独的 SQL DELETE 语句查询来删除记录。第一个查询必须删除部门为项目经理的员工行,然后编写第二个查询以从 Department 表中删除项目经理记录。

BEGIN TRANSACTION
DELETE FROM Employee
WHERE DeptID IN (
SELECT id FROM Department WHERE DepartmentName = 'Project Manager');
DELETE FROM Department WHERE id = 5;
COMMIT TRANSACTION;

您还可以用 JOIN 替换 IN 运算符查询,并且可以获得相同的结果。

DELETE FROM Employee 
JOIN Department ON Employee.DeptId = Department.id
WHERE DepartmentName = ' Project Manager';
DELETE FROM Department WHERE id = 5;
SQL DELETE Statement and JOINS with TRANSACTIONS

使用子查询的 SQL DELETE FROM

使用子查询编写 DELETE 语句对于根据内部查询获得的结果集从表中删除记录非常有用。在我们之前的 TOP 子句示例中,我们展示了一个子查询示例,您可以参考该示例以获得基本理解。

在这个从子查询结果集示例中,我们不知道部门 ID。但是我们想删除部门名称为 Module Lead 的员工。在这种情况下,我们使用 子查询 从部门名称为 Manager 的 Department 表中选择记录。接下来,我们使用 DELETE 命令和 WHERE 子句与 IN 运算符来删除子查询编写的多条记录。

DELETE FROM [Employee] WHERE [DeptID] IN
(
SELECT id FROM Department WHERE DepartmentName = 'Manager'
)

删除表中所有部门名称为 Manager 的记录。如果您知道 ID,可以尝试使用以下查询,但这不是正确的方法。

DELETE FROM [Employee] WHERE [DeptID] = 3

以下查询将删除表中所有年收入低于表平均值的员工。内部子查询查找并返回整个表的平均收入。主 DELETE 命令将删除年收入低于平均值的员工。

DELETE FROM Employee
WHERE YearlyIncome <
( SELECT AVG(YearlyIncome) FROM Employee)

SQL Server DELETE 行(如果存在)

WHERE 子句无法检查单个表中的数据。在某些情况下,我们必须根据第二个表的条件删除记录。例如,在从表中删除记录时,始终最好检查记录是否存在。

以下查询使用 EXISTS 运算符检查 Employee 表中的记录与 Department 表中的记录。如果它们存在且其部门名称为 CEO,则 DELETE 语句将删除该记录。

剩余数据 视图

DELETE sd FROM [Employee] as sd
WHERE EXISTS (
SELECT * FROM Department
WHERE sd.DeptID = Department.id
AND DepartmentName = 'CEO'
)

删除重复记录

假设客户表中有一些重复记录,我们的任务是删除这些记录。在 SQL Server 中,我们可以使用子查询或 CTE 查找重复项,并使用 DELETE 语句删除这些记录。

一般来说,最后插入的记录可能是正确或需要的记录。因此,以下查询将保留最高的 ID 值(假设是最新值)并删除重复项。如果需要,您可以将 MAX 替换为 MIN 函数

DELETE FROM customers 
WHERE CustomerID NOT IN (
SELECT MAX(CustomerID) FROM customers
GROUP BY FirstName, LastName, DOB
)

另一个选项是使用 CTE 和 ROW_NUMBER() 排名函数。在以下查询中,ROW_NUMBER() 函数 为分区组中的每一行分配一个唯一的编号。在这里,它将为每个客户分配编号。接下来,我们使用 DELETE 语句删除行号大于 1 的记录。

WITH CTE AS (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName, DOB ORDER BY CustomerID) AS rank
FROM customer)
DELETE FROM CTE WHERE rank > 1

SQL Server DELETE 和 IS NULL 语句示例

表中的 NULL 值表示缺失数据。在某些情况下,我们必须摆脱这些 NULL 值。在这种情况下,我们使用 DELETE 语句以及 IS NULL 运算符。

如您所知,AdventureWorksDW DimProduct 表中有许多产品的 Product Description 为空或 NULL。因此,让我编写一个查询来删除所有 Description 为 NULL 的产品。

DELETE FROM DimProduct

WHERE ProductDescription IS NULL

在 SQL DELETE 语句中使用 OUTPUT 子句

OUTPUT 子句保存并显示 DELETE 命令删除的记录总数。例如,以下查询删除销售额小于 1000 的员工。但是,OUTPUT 子句将显示被删除的总记录作为结果集。在这里,如果需要少量列,可以将 * 替换为所需的列名。

DELETE Employee 
OUTPUT DELETED.*
WHERE Sales < 1000;

上述查询是使用 OUTPUT 子句显示已删除结果集的简单版本。但是,如果您使用 表变量,您可以存储 OUTPUT 子句返回的结果集并执行进一步的操作。以下查询将创建一个表变量并使用 OUTPUT 子句保存 DELETE 语句删除的行。接下来,SELECT 语句将从变量中显示这些记录。

DECLARE @Variable TABLE (  
[EmpID] [int] NOT NULL,
[FirstName] [nvarchar](255) NULL,
[LastName] [nvarchar](255) NULL,
[Education] [nvarchar](255) NULL,
[Occupation] [nvarchar](255) NULL,
[YearlyIncome] [float] NULL,
[Sales] [float] NULL,
DepartmentName VARCHAR(50) NULL);

DELETE Employee
OUTPUT DELETED.EmpID, DELETED.FirstName, DELETED.LastName,
DELETED.Education,DELETED.Occupation,DELETED.YearlyIncome,
DELETED.Sales, d.DepartmentName
INTO @Variable
FROM Employee
JOIN Department as d
ON Emp.DeptID = d.id
WHERE d.DepartmentName = 'Software Developer';

SELECT * FROM @Variable

使用 LIKE 运算符的 DELETE 命令

如果在 WHERE 子句中使用 SQL LIKE 运算符,我们可以对记录执行通配符搜索,并且 DELETE 命令将删除匹配的记录。例如,您可以使用 DELETE 和 LIKE 组合来删除属于城市名称以 C、N 等开头的客户。

以下查询将删除教育中包含“High”关键字或教育以“Degree”结尾的员工。我建议您尝试更多通配符以获得更好的知识。

DELETE FROM [Employee]

WHERE Education LIKE '%High%' OR Education LIKE '%Degree'

SQL 删除存储过程

让我们看看如何在 存储过程 中使用此语句。在这里,我们删除职业等于文员或年收入小于或等于 60000 的记录。

IF OBJECT_ID ( 'sp_DeleteEmpRecords', 'P' ) IS NOT NULL   
DROP PROCEDURE sp_DeleteEmpRecords;
GO

CREATE PROCEDURE sp_DeleteEmpRecords
AS
BEGIN
SET NOCOUNT ON;

DELETE FROM [Employee]
WHERE Occupation = 'Clerical' OR
YearlyIncome <= 60000
END
GO
Messages
-------
Command(s) completed successfully.

让我使用 EXEC 命令来执行存储过程。

EXEC dbo.sp_DeleteEmpRecords
GO
Messages
-------
Command(s) completed successfully.

现在,让我们看看存储过程的执行是否清除了我们表中的行。

-- Select all records from a Table after executing the SP
SELECT * FROM [ProductSale]

使用 Management Studio 的 SQL Server Delete 语句

如果您可以访问 Management StudioSQL Server,则有多个选项可以从数据库表中删除记录。

选项 A:使用编辑前 200 行

请右键单击表,然后从菜单中选择“编辑前 200 行”选项。接下来,使用 Ctrl 或 Command 键仔细选择所需的行。然后,右键单击它们以打开上下文菜单。选择“执行 SQL 命令”以进一步验证它们,或选择“删除”选项以永久从表中删除这些行。

提示:在 DELETE 命令之前使用 SELECT 语句,以检查您要从表中删除的记录是否是结果集中显示的记录。

选项 B:使用脚本表

除了上述两个选项之外,您还可以使用 IntelliSense 编写 DELETE 语句。它非常高级,您可以更好地控制查询。为此,右键单击表 -> 选择“将表脚本化为” -> “删除到” -> “新查询编辑器窗口”。它将为所选表生成语句,代码如下所示。

USE [Sample]
GO
DELETE FROM [dbo].[Employee]
WHERE <Search Conditions,,>
GO

首先,让我将表备份到原始位置。接下来,让我们添加下面所示的搜索条件。

DELETE FROM [dbo].[Employee] WHERE EmpID = 1

SQL DELETE 语句最佳实践

以下是编写有效 SQL DELETE 语句的一些最佳实践。

  • 用户权限: DELETE 操作非常敏感,因此您必须限制未经授权的人员删除表。
  • 数据备份:在实施 DELETE 操作之前,务必进行备份,以避免数据丢失。如果您正在处理大型数据集,数据丢失将是巨大且不可逆的。
  • WHERE 子句: 在编写 DELETE 命令时,始终使用 WHERE 子句。如果您确定要删除整个数据集,则只可省略 WHERE 子句。
  • 索引列: 确保在 WHERE 子句中使用索引列,以数倍提高查询性能。
  • SELECT: 在实施 SQL DELETE 命令之前,使用 SELECT 语句查看数据。或使用 SELECT COUNT(*) 查看受影响的总行数。
  • 事务: 始终将完整的 DELETE 语句包装在 BEGIN 和 END TRANSACTION 中是一个好习惯,以确保数据完整性。如果在执行过程中出现问题,您可以 ROLLBACK 到原始状态。
  • 分批处理: 在处理大型数据集时,分小批(TOP 子句)执行删除操作,以提高查询性能并避免阻塞。
  • 删除所有行: 使用 TRUNCATE 语句清空整个表是一个好习惯。因为它更快,并且不维护每条记录删除的事务日志。
  • OUTPUT 子句: 使用 OUTPUT 子句显示 DELETE 语句删除的行。
  • 外键错误: 当存在父子关系时,从表中删除记录将抛出错误。除非您使用 CASCADE DELETE 规则创建了外键。否则,首先从子表中删除记录,然后从父表中删除。
  • 禁用触发器和约束:在使用大型数据集时,禁用外键约束。此外,相关的触发器也将提高性能。但是,您应该知道这些触发器存在的原因及其重要性。要禁用触发器:ALTER TABLE Employee DISABLE TRIGGER ALL。DELETE 操作完成后,编写上述 ALTER 语句并将 DISABLE 关键字替换为 ENABLE。

SQL DELETE 与 TRUNCATE 与 DROP

Microsoft SQL Server 提供三个命令:DELETE、TRUNCATE 和 DROP。由于它们的相似性,人们常常对它们的操作感到困惑,这里我们展示它们的区别。

  • DELETE: 根据用户给定的条件,删除表中的单条或多条记录。
  • TRUNCATE: 一次性删除表中的所有记录或行,并重置标识列。
  • DROP: 从数据库中删除整个表。

下表将说明 SQL Server 中 DELETE、TRUNCATE 和 DROP 命令之间最常见的区别。

删除TRUNCATEDROP
DELETE 是数据操作语言 (DML) 语句。TRUNCATE 是数据定义语言 (DDL) 语句。DROP 是 DDL 语句。
它根据条件删除一行或多行。删除所有记录并保留表结构。删除表、结构和约束。
使用 DELETE 命令删除单行或多行。使用 TRUNCATE 删除表中的所有记录并保留表结构。使用 DROP 命令删除表或数据库。
它允许 WHERE 子句过滤要删除的记录。它不支持 WHERE 子句。不支持 WHERE 子句。
它不重置标识列值。它重置标识列值。不适用。
DELETE FROM orders WHERE OrderDate < '2020-01-01'TRUNCATE TABLE ordersDROP TABLE orders
它记录每次行删除,因此事务日志很高。它只记录数据页,因此事务空间较少。它记录整个表的删除。因此,它维护完整的日志。
性能比其他两个慢。比 DELETE 快三者中最快。
如果存在 CASCADE DELETE 参照完整性,则可以使用 SQL 外键引用删除记录。您不能截断具有外键引用的表。当其他表引用该表时,您无法删除该表。因此,首先删除依赖表或关系,然后应用操作。
它将触发表上的 DELETE 触发器。它不会触发表上的任何触发器。它不会触发表上的触发器。
它保持触发器和约束不变。它不会删除触发器和约束。它删除表上的约束和触发器