When we’re developing solutions, we can sometimes forget useful commands we can use in T-SQL that make it convenient to remove data, eliminate objects, or carefully remove data. We look at three of these commands with a few examples of where we might consider using them in development, or in rare production cases. While they may offer us speed and convenience in some cases, we also look at some situations where they may not be the best tool to use.
在开发解决方案时,有时我们会忘记可以在T-SQL中使用的有用命令,这些命令使删除数据,删除对象或仔细删除数据变得很方便。 我们看了其中的三个命令,并提供了一些示例,说明了在开发或生产案例中可能考虑使用它们的位置。 尽管在某些情况下它们可以为我们提供速度和便利,但在某些情况下,它们可能不是最好的工具。
Deleting data can be one of the most expensive DML operations and while we must do it in some situations such as deleting some records in a table, we do have an alternative with truncate if we need to remove every record in a table without each row removal being logged. In development, we will often have more freedom to truncate a table when we need to remove all rows, which will help us over using delete.
删除数据可能是最昂贵的DML操作之一,尽管在某些情况下(例如删除表中的某些记录)我们必须这样做,但是如果我们需要删除表中的每条记录而不删除每一行,我们确实有truncate的另一种选择被记录。 在开发中,当我们需要删除所有行时,我们通常会拥有更大的截断表的自由,这将有助于我们克服使用delete的麻烦。
In practice, one situation where deletes and truncates can be compared is transactional replication where we’ve defined a rule that on a reset, we want to remove every row of data in the destination table and repopulate the data from the source, as a load of inserts in our situation will perform better than updates (if the situation has much fewer updates than inserts, this would not be true). If we don’t want each row elimination tracked in the transaction log, a delete operation before repopulating the data becomes expensive, whereas a truncate operation does not. In this example, we’re still assuming a few things to prefer truncates over deletes or drop, re-creates and inserts:
在实践中,可以比较删除和截断的一种情况是事务复制,其中我们定义了一个规则,即在重置时,我们希望删除目标表中的每一行数据,并从源中重新填充数据,以作为负载。在我们的情况下,插入的性能将优于更新(如果情况的更新少于插入的情况,那将不是事实)。 如果我们不希望在事务日志中跟踪每一行的消除,那么在重新填充数据之前执行删除操作会变得很昂贵,而截断操作则不会。 在此示例中,我们仍然假设有一些事情比删节或删除,重新创建和插入更喜欢截断:
While this command can be helpful in many situations involving development or full refreshes of a table, we should not use (or may be unable to use) the truncate command in some situations, such as the following:
尽管此命令在涉及表开发或表的完全刷新的许多情况下很有用,但在某些情况下,我们不应使用(或可能无法使用)truncate命令,例如:
What about development situations where we want to remove a subset of records over removing all records? If we want to take extra caution about removing records, we can use a CTE for first filtering before removing records. In the below queries we see the work shown with a query that only uses a CTE for a select, then a delete statement from the same CTE.
在我们要删除记录的子集超过删除所有记录的开发情况下,情况又如何呢? 如果我们要特别注意删除记录,可以在删除记录之前使用CTE进行首次过滤。 在下面的查询中,我们看到的查询工作仅使用CTE进行选择,然后使用同一CTE的delete语句。
;WITH RemoveData AS(
SELECT ID, ChVl
FROM tbPairTin
WHERE ID IN (124,5648)
)
DELETE FROM RemoveData
Unlike truncate statements, delete statements may be costly due to errors or an error. If we know that we need to remove all data in a table, we’re less likely to make a mistake with a truncate since all data are being removed from a table. However, a delete statement can introduce errors by accident because if a filter is wrong, mistyped, or forgotten, records are wiped out and must be recovered. Using CTEs add extra work but offers two benefits to delete statements:
与截断语句不同,由于错误或错误,删除语句的代价可能很高。 如果我们知道需要删除表中的所有数据,则由于从表中删除了所有数据,因此不太可能因截断而出错。 但是,删除语句可能会偶然引入错误,因为如果过滤器错误,类型错误或被遗忘,则会清除记录并必须对其进行恢复。 使用CTE会增加工作量,但删除语句有两个好处:
;WITH RemoveData AS(
---- query here
)
DELETE FROM RemoveData
While this does raise awareness and adds a convenient check in place, it does require some extra effort on the part of the developers.
尽管这确实提高了知名度并添加了方便的检查方法,但开发人员确实需要付出额外的努力。
If we’re testing a set of tables for a proof-of-concept and we don’t intend to keep the tables in our development, the below procedure will drop all tables by a schema. If we validate our proof-of-concept, we can retain the tables or migrate them to our default or permanent schema; if we invalidate our proof-of-concept, we can remove all the tables. This procedure also makes it easy when we’re demoing concepts to teams and we create tables during a presentation under a demonstration schema for easy later removal. Finally, if we keep table backups for when we change lookup data or other smaller data sets in production and throughout our environments, we can use other tables schemas for these backups and drop them later after our testing is complete (a rare production use-case).
如果我们要测试一组表以进行概念验证,并且不打算将这些表保留在我们的开发中,则以下过程将按模式删除所有表。 如果我们验证概念验证,则可以保留表或将其迁移到我们的默认或永久模式; 如果我们使概念验证无效,则可以删除所有表。 当我们将概念演示给团队并在演示过程中的演示模式下创建表时,使用此过程也很容易,以便以后删除。 最后,如果当我们在生产环境中以及整个环境中更改查找数据或其他较小数据集时保留表备份,则可以将其他表模式用于这些备份,并在测试完成后将其删除(罕见的生产用例) )。
CREATE PROCEDURE stpDropAllTables
@schema VARCHAR(50)
AS
BEGIN
DECLARE @sql NVARCHAR(MAX) = ''
SELECT
@sql += 'DROP TABLE ' + QUOTENAME(schema_name(schema_id)) + '.' + QUOTENAME([name]) + '
'
FROM sys.tables
WHERE schema_name(schema_id) = @schema
EXEC sp_executesql @sql
END
While it is bad practice to use keywords when naming tables or schemas, this is unfortunately common. The drop statement wraps the schema and table name within brackets using the QUOTENAME function to prevent this situation. In the below example, we create a schema and table that are both keywords and drop them successfully:
虽然在命名表或模式时使用关键字是一种不好的做法,但不幸的是,这很普遍。 drop语句使用QUOTENAME函数将模式和表名包装在方括号中,以防止出现这种情况。 在下面的示例中,我们创建一个都是关键字的架构和表,并将其成功删除:
CREATE SCHEMA [key]
CREATE TABLE [key].[Value] (ID INT)
EXEC stpDropAllTables 'key'
If you are the architect or the designer and have control, it is best practice to avoid using keywords for naming objects, but this will help in those situations where we’re required to use them by architects or clients who do not care for following best practices.
如果您是建筑师或设计师并拥有控制权,则最佳做法是避免使用关键字来命名对象,但这在那些不希望遵循最佳操作的建筑师或客户要求我们使用它们的情况下会有所帮助实践。
With this, we can develop on a schema and only keep objects we use. Otherwise, we can remove all objects by our development (or other named) schema.
这样,我们就可以在模式上进行开发,并且仅保留我们使用的对象。 否则,我们可以通过我们的开发(或其他命名)模式删除所有对象。
翻译自: https://www.sqlshack.com/useful-t-sql-techniques-for-development-in-sql-server/