cte公用表表达式

In this article, the latest in our series on Common table expressions, we’ll review CTE SQL Deletes including analyzing the operation before the delete, actually removing the data as well as organizing and ordering the deletes with CTEs.

在本文中,这是我们有关Common表表达式的最新系列文章,我们将回顾CTE SQL删除,包括分析删除之前的操作,实际删除数据以及使用CTE组织和排序删除。

Due to the possible complexity with delete transactions, SQL CTEs (common table expressions) may offer us a tool to help increase our thoroughness. Reversing an insert results in a delete, while reversing an update results in a counter-update, but reversing a delete statement requires that we have a copy of the records prior to removing them. We want to take extra care when running delete transactions, especially in environments where we cannot be offline to restore data. We’ll look at running delete transactions with SQL CTEs alongside considerations about where they can be useful in organization, performance and minimizing errors.

由于删除事务可能会很复杂,因此SQL CTE(公用表表达式)可能会为我们提供一种工具,以帮助提高完整性。 反向插入会导致删除,而反向更新会导致反向更新,但是反向删除语句要求我们在删除记录之前先拥有记录的副本。 在运行删除事务时,我们要格外小心,尤其是在无法离线还原数据的环境中。 我们将着眼于使用SQL CTE运行删除事务,并考虑在何处对组织,性能和最大程度地减少错误有用。

删除之前 (Before the delete)

Before running any delete transaction, unless we have a specific process flow to follow, we should always save a copy of the data and, if unused, remove that copy of the data at a later time. One reason for this is that we may have a very large database, remove 150 records in that database, but without a copy of the data, be forced to restore a copy of the same database to get 150 records. Even with using a tool like common table expressions to minimize errors, we still want to develop for experiencing errors. I’ve seen restores for databases over a terabyte occur because fewer than 10,000 records were needed following a bad delete transaction.

在运行任何删除事务之前,除非要遵循特定的处理流程,否则我们应始终保存数据副本,如果未使用,请稍后再删除该数据副本。 这样做的一个原因是我们可能有一个非常大的数据库,删除该数据库中的150条记录,但是没有数据副本,被迫还原同一数据库的副本以获取150条记录。 即使使用通用表表达式之类的工具来最大程度地减少错误,我们仍然希望针对遇到的错误进行开发。 我已经看到对数TB的数据库进行还原的原因是,一次不良的删除事务后需要的记录少于10,000条。

In our below code for our pre-delete step, we first save a copy of the data we’ll be removing to a new table that has an extension that we’ll be dropping (in this specific example, _DropTable). Because we’ll be deleting the winter months of December, January and February, I’ve also added _Winter in the name. Next, we see the code and an image of our job step that goes through and removes tables with this extension after a week. This only shows an example of considering reversal steps with deletes, because reversing a delete is more complex than reversing an insert or update on the data retrieval side.

在下面的预删除步骤代码中,我们首先将要删除的数据副本保存到一个新表中,该表具有我们将要删除的扩展名(在此特定示例中, _DropTable )。 因为我们将删除冬季的十二月,一月和二月,所以我还在名称中添加了_Winter 。 接下来,我们将看到代码和工作步骤的图像,这些图像和过程将在一周后删除具有此扩展名的表。 这仅显示了考虑使用删除操作的反向步骤的示例,因为在数据检索方面,反向删除操作比反向插入或更新操作更为复杂。

SELECT *
INTO tbAlmondData_Winter_DropTable
FROM tbAlmondData
WHERE MONTH(AlmondDate) IN (12,1,2)SELECT [name],[create_date]
FROM sys.tables
ORDER BY [create_date] DESC

We see in the sys.tables our new table name.

我们在sys.tables中看到我们的新表名。

DECLARE @dropstring NVARCHAR(4000) = ''SELECT@dropstring += N'DROP TABLE ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME([name]) + '  '
FROM sys.tables
WHERE [create_date] > DATEADD(DD,-7,GETDATE())AND [name] LIKE '%_DropTable'EXEC sp_executesql @dropstring

Our job step removes all tables with the extension _DropTable after a week of their creation.

创建一周后,我们的工作步骤将删除所有扩展名为_DropTable的表。

One important point here is that the extension _DropTable may be a legitimate extension in some environments, so for these environments, we would use other extensions like _ToBeDropped, _ToBeRemoved, etc.

这里重要的一点是,扩展名_DropTable在某些环境中可能是合法的扩展,因此对于这些环境,我们将使用_ToBeDropped_ToBeRemoved等其他扩展名。

使用SQL CTE删除数据 (Removing data with SQL CTEs)

Once we have our data backed up, we can proceed to remove our data. We will wrap our delete with a begin and commit transaction to restrict access while the delete is performing and name our transaction. Following the format we’ve used with naming common table expressions, we’ll keep the name relative to what we’re doing – removing the winter months. In addition to querying the set of data before we run a delete, we can see how a fat finger mistake can be avoid here, like an accidental run of a delete statement without a where clause – the CTE in SQL Server inherently requires that we write the wrapped query first since the delete transaction is based off wrapped query.

一旦我们备份了数据,就可以继续删除数据。 我们将使用开始和提交事务包装我们的删除操作,以在执行删除操作时限制访问并命名我们的事务。 遵循用于命名公用表表达式的格式,我们将相对于我们正在执行的操作保留名称-删除冬季。 除了在运行删除操作之前查询数据集之外,我们还可以看到在这里如何避免出现手指错误,例如意外运行不带where子句的delete语句– SQL Server中的CTE本质上要求我们编写因为删除事务基于包装查询,所以包装查询优先。

BEGIN TRAN DeleteWinter;WITH RemoveWinter AS(SELECT *FROM tbAlmondDataWHERE MONTH(AlmondDate) IN (12,1,2)
)
DELETE
FROM RemoveWinterCOMMIT TRAN DeleteWinter

If we run the wrapped query following the delete, we’ll see no records return since the 92 winter months were removed.

如果在删除后运行包装查询,则自从删除了92个冬季月份以来,我们将看不到任何记录返回。

Because deletes can be costly to restore, I suggest re-using the select query we used in the back-up select, as this in intuitive when the script is reviewed (if applicable). Also, with deletes I prefer to get as much information about what I’m removing to reduce the likelihood of an accidental removal.

由于删除操作的恢复成本可能很高,因此我建议重新使用我们在备份选择中使用的选择查询,因为这在检查脚本时(如果适用)很直观。 另外,对于删除,我更希望获得与要删除的内容有关的尽可能多的信息,以减少意外删除的可能性。

If we discovered that we need to return our data back to our table, we could quickly reverse our removal using inverse logic:

如果发现需要将数据返回到表中,则可以使用逆逻辑快速撤消移除操作:

INSERT INTO tbAlmondData
SELECT *
FROM tbAlmondData_Winter_DropTable

Since we saved all the data we removed in full within this backup table, we can do a full insert to restore the data.

由于我们已将删除的所有数据全部保存在此备份表中,因此我们可以进行完全插入来恢复数据。

使用SQL CTE进行有序和有组织的删除 (Ordered and organized deletes with SQL CTEs)

Since common table expressions can assist us with organization of data, especially organizing data in groups within larger groups, we can apply this feature with removing duplicate values and removing values within smaller groups of data. For our starting example, we’ll re-insert the data we removed and we’ll do it twice – inserting duplicate winter records in our tbAlmondData.

由于公用表表达式可以帮助我们组织数据,特别是在较大的组内按组组织数据,因此我们可以应用此功能,删除重复的值并删除较小的数据组内的值。 对于我们的第一个示例,我们将重新插入删除的数据,然后进行两次-在tbAlmondData中插入重复的冬季记录。

---- Run this transaction twice
INSERT INTO tbAlmondData
SELECT *
FROM tbAlmondData_Winter_DropTableSELECT *
FROM tbAlmondData
ORDER BY AlmondDate ASC

Duplicate winter month data.

冬季月份数据重复。

When we run a count of dates and group by the date, we see that our winter months have two records in them. For this example, we’ll assert that our AlmondDate is a primary key (though we are allowing duplicates for an example removal) in that only one unique record should exist in the table.

当我们对日期进行计数并按日期进行分组时,我们看到冬季有两个记录。 对于此示例,我们将断言AlmondDate是主键(尽管我们允许重复删除示例),因为表中应仅存在一个唯一记录。

SELECT AlmondDate, COUNT(AlmondDate) CountDates
FROM tbAlmondData
GROUP BY AlmondDate

The AlmondDate records with their count totals.

AlmondDate记录其总数。

Next, we’ll order our data using a select query inside a common table expression that we won’t finish yet to see what our output will look like. Since we want to removed the ordered data that show a duplicate id (in this case, 2), we’ll create a query with the ROW_NUMBER function that divides and orders our data by the AlmondDate column. Because we’re dividing this column into partitions based on the value, we will see an Id of two if there is another identical record in the table. This is key because it applies to multiple columns, if the duplicate record has multiple values duplicated.

接下来,我们将在公共表表达式内使用选择查询对数据进行排序,但我们尚未完成该表,以查看输出结果。 由于我们要删除显示重复ID(在本例中为2)的有序数据,因此我们将使用ROW_NUMBER函数创建一个查询,该函数按AlmondDate列对数据进行划分和排序。 因为我们将基于该值将该列划分为多个分区,所以如果表中还有另一个相同的记录,我们将看到一个ID为2。 这是关键,因为如果重复记录具有多个重复的值,则它适用于多个列。

;WITH RemoveDupes AS(SELECTROW_NUMBER() OVER (PARTITION BY AlmondDate ORDER BY AlmondDate) Id , * FROM tbAlmondData
)
---Unfinished: use the inner select statement

We see a value of 2 for records that appear again.

对于再次出现的记录,我们看到值为2。

Since we don’t want to remove original records as that would remove values with only one record (records with only an ID of 1), we will remove the rows that have a ID value of 2.

由于我们不想删除原始记录,因为那样会删除仅包含一条记录(ID为1的记录)的值,因此我们将删除ID值为2的行。

;WITH RemoveDupes AS(SELECTROW_NUMBER() OVER (PARTITION BY AlmondDate ORDER BY AlmondDate) Id , * FROM tbAlmondData
)
DELETE FROM RemoveDupes WHERE Id = 2

When we run the transaction, we see that 92 records were removed and if we run the select statement again from inside the wrapped query, we see only values of 1 for the Id.

当我们运行事务时,我们看到92条记录被删除,并且如果我们从包装查询中再次运行select语句,则ID的值只有1。

All values with an Id of 2 have been removed.

ID为2的所有值均已删除。

We see with the common table expression that values have been removed from the underlying table – like we’ve seen with updates. We run a delete against a CTE in SQL Server and the table’s values are affected – this differs from taking data from a table to a temp table and removing data from the temp table. The source table still has the records. This logic does not carry over to using these with joined delete statements. In the below code, we run two delete statements that we rollback – one uses a join that selects one table’s data within a SQL CTE while the other performs a delete operation with the same join on the one table. The delete with the common table expression throws an error that communicates to us about underlying tables being affected, even though we see only tbAlmondData is affected by the delete. By contrast, we can run a delete with the same join without the SQL CTE that also deletes only from tbAlmondData. The second transaction is a direct delete against tbAlmondData based on the join statement.

通过公用表表达式,我们可以看到已从基础表中删除了值,就像在更新中看到的那样。 我们对SQL Server中的CTE运行删除操作,并且该表的值会受到影响–这不同于将数据从表移到临时表并从临时表中删除数据。 源表仍具有记录。 此逻辑不会继续使用结合使用的delete语句。 在下面的代码中,我们运行两个我们回滚的delete语句–一个使用联接,该联接在SQL CTE中选择一个表的数据,而另一个使用对一个表的相同联接执行删除操作。 即使我们看到只有tbAlmondData受到删除的影响,带有公用表表达式的delete也会引发一个错误,通知我们有关受影响的基础表的信息。 相比之下,我们可以在没有SQL CTE的情况下使用相同的联接运行删除操作,该操作也只能从tbAlmondData中删除。 第二个事务是基于join语句针对tbAlmondData的直接删除。

BEGIN TRAN;WITH CauseError AS(SELECT t.*FROM tbAlmondData tINNER JOIN QuarterTable tt ON tt.QuarterId = DATEPART(QUARTER,t.AlmondDate)
)
DELETE FROM CauseErrorDELETE FROM tbAlmondDataFROM tbAlmondData tINNER JOIN QuarterTable tt ON tt.QuarterId = DATEPART(QUARTER,t.AlmondDate)ROLLBACK TRAN

Even with one table’s data in the delete statements, this will not remove data.

即使在delete语句中包含一个表的数据,也不会删除数据。

The latter delete statement runs (rolled back).

后者的delete语句运行(回滚)。

While we can use SQL CTEs to minimize errors in situations where an error causes significant cost, like in the case of deletes, we still may not be able to use them in some circumstances. In these situations, we may prefer to design for automatic removal using cascades where referenced rows are removed automatically.

尽管我们可以使用SQL CTE在错误导致大量损失的情况下(例如在删除情况下)将错误减至最少,但在某些情况下我们仍然无法使用它们。 在这些情况下,我们可能更喜欢使用级联设计为自动删除,该级联会自动删除引用的行。

结论 (Conclusion)

Deletes can be a costly operation as they can take more effort to reverse. Using caution by saving the data we plan to remove conveniently (and having automation in place to remove these backups automatically if they remain unused) along with carefully crafting a delete statement will ensure that we avoid situations where we have to spend resources on undoing a delete. As we see, SQL CTEs can offer us an intuitive tool to run delete statements and considering the ease of ordering data with them, they may be a tool that helps us smoothly remove records. Like with inserts and updates, if the performance is the same or better than alternatives, we may choose to use this route.

删除可能是一项昂贵的操作,因为它们可能需要花费更多的精力来撤消。 通过谨慎地保存数据,我们计划方便地删除数据(并具有自动删除这些备份的自动功能(如果未使用它们将自动删除))以及精心制作delete语句,可确保避免出现必须花费资源来撤消删除的情况。 如我们所见,SQL CTE可以为我们提供直观的工具来运行删除语句,并考虑到使用它们进行数据排序的便利性,它们可能是帮助我们顺利删除记录的工具。 与插入和更新一样,如果性能相同或优于替代方法,我们可以选择使用此路由。

目录 (Table of contents)

CTEs in SQL Server; Querying Common Table Expressions
Inserts and Updates with CTEs in SQL Server (Common Table Expressions)
CTE SQL Deletes; Considerations when Deleting Data with Common Table Expressions in SQL Server
CTEs in SQL Server; Using Common Table Expressions To Solve Rebasing an Identifier Column
SQL Server中的CTE; 查询公用表表达式
在SQL Server中使用CTE进行插入和更新(公用表表达式)
CTE SQL删除; 在SQL Server中删除具有公用表表达式的数据时的注意事项
SQL Server中的CTE; 使用公用表表达式解决重新编制标识符列的问题

翻译自: https://www.sqlshack.com/cte-sql-deletes-considerations-when-deleting-data-with-common-table-expressions-in-sql-server/

cte公用表表达式

cte公用表表达式_CTE SQL删除; 在SQL Server中删除具有公用表表达式的数据时的注意事项相关推荐

  1. Mac如何删除在磁盘空间中的可清除空间以及Mac开机时进度条卡100%的解决办法

    Mac如何删除在磁盘空间中的可清除空间以及Mac开机时进度条卡100%的解决办法 1.Mac如何删除在磁盘空间中的可清除空间 对于mac来说磁盘的空间是十分宝贵的,小编会定期的查看一下自己电脑的磁盘使 ...

  2. 在SQL Server中使用JOIN更新表?

    我想更新在其他表上进行联接的表中的列,例如: UPDATE table1 a INNER JOIN table2 b ON a.commonfield = b.[common field] SET a ...

  3. mysql用一条sql语句删除重复记录_mysql中删除重复记录,并保留重复数据中的一条数据的SQL语句...

    正好想写一条删除重复语句并保留一条数据的SQL,网上查了一部分资料写的很详细,但还是在这里写下自己的理解,以遍后续学习 .如下: 表字段和数据: SQL语句: DELETE FROM`user`WHE ...

  4. sql语句截断_SQL Server中SQL截断和SQL删除语句之间的区别

    sql语句截断 We get the requirement to remove the data from the relational SQL table. We can use both SQL ...

  5. SQL Server中的内存优化表变量

    This article will cover the usage details and performance advantages of the memory-optimized table v ...

  6. oracle中删除yuj_[转载]Oracle中删除表操作trunc delete和drop的说明

    相同点: 1.truncate和不带where子句的delete, 以及drop都会删除表内的数据. 2.drop,truncate都是DDL语句,执行后会自动提交. 不同点: 1. truncate ...

  7. sql server中创建数据库和表的语法

    下面是sql server中创建数据库,创建数据表以及添加约束的sql语句: use master --创建数据库 if exists (select * from sysdatabases wher ...

  8. 【excel使用】批量删除excel工作簿中多个工作表的同一列内容?

    1.首先要保证多个工作表(sheet页)表头保持一致,或者部分保持一致(只能修改一致的部分) 2.如果想要删除所有工作表中的B列内容 ,一个一个的删除会很麻烦,所以需要使用批量删除: 1)鼠标点选工作 ...

  9. modify sql_在SQL Server中使用JSON_MODIFY()修改JSON数据

    modify sql This article explores JSON_MODIFY() function to modify JSON Data in the SQL Server. 本文探讨了 ...

最新文章

  1. matlab game of life,模拟器cellular auotomata元胞自动机 matlab
  2. 【LeetCode-704 | 二分查找】
  3. 第九次作业——测试报告与用户手册
  4. DPDK架构与特点(转)
  5. poj 2392 Space Elevator
  6. 刷完EMNLP 2021论文列表,我们挑出了这8篇预训练相关必读论文
  7. 毕业二十年,为什么人和人之间的差距那么大?
  8. and型变量哲学家问题C语言,利用AND型信号量解决哲学家进餐问题,要windows下的C/C++的完整源代码程序。(五个哲学家五只筷子)...
  9. Java生成真正格式的Excel文件
  10. C语言的代码内存布局
  11. loadrunner中文件的操作
  12. return、break、continue三者的区别
  13. input输入身份证验证
  14. 【Visual C++】游戏开发五十四 浅墨DirectX教程二十一 视觉的诡计:公告板(Billboard)技术
  15. c语言课程设计高校水电费管理系统
  16. 【转载】冰美人淘宝装修教程--索引
  17. 【个人研究】21世纪西方运用脑电(EEG)的音乐研究动向分析(二)
  18. python输出word内容_使用python-docx生成Word文档
  19. 数学 - 超级次方 - Leetcode 372
  20. 解决SSH连接闲置一会就断开需要重新连接

热门文章

  1. python 搭建web_webpy搭建一个简单的网站
  2. python列表到元祖_python列表与元祖
  3. 计算机用三角函数时如何用弧度制,三角函数1任意角和弧度制.PPT
  4. jzoj3736. 【NOI2014模拟7.11】数学题
  5. 2018/12/06 eclipse 快速加载需要的包
  6. 1.Spring框架入门
  7. 浅入浅出数据结构(18)——希尔排序
  8. 在浏览器里友好的变量输出查看函数方法
  9. 使用谷歌语音识别打造语音管家HiVoice
  10. 输入url并按下回车的那一刻发生了什么?