【问题标题】:How is data being removed from tables that are not defined in a delete or truncate statement?如何从未在删除或截断语句中定义的表中删除数据?
【发布时间】:2016-11-04 03:16:17
【问题描述】:

给定一个包含许多表的数据库,我有一个包含多个删除和截断语句的脚本。我的数据库中的每个表都没有删除语句或截断语句。该脚本如下所示(我已更改名称并缩短了长度):

TRUNCATE table db.dbo.table1
TRUNCATE table db.dbo.table2
TRUNCATE table db.dbo.table3

--cannot truncate table because it is being referenced by a FK constraint
--TRUNCATE table db.dbo.table4
--TRUNCATE table db.dbo.table5
--TRUNCATE table db.dbo.table6
--TRUNCATE table db.dbo.table7

DELETE FROM db.dbo.table4
DBCC CHECKIDENT ('db.dbo.table4',RESEED, 0)
DELETE FROM db.dbo.table5
DBCC CHECKIDENT ('db.dbo.table5',RESEED, 0)
DELETE FROM db.dbo.table6
DBCC CHECKIDENT ('db.dbo.table6',RESEED, 0)
DELETE FROM db.dbo.table7
DBCC CHECKIDENT ('db.dbo.table7',RESEED, 0)
DELETE FROM db.dbo.table8
DELETE FROM db.dbo.table9
DELETE FROM db.dbo.table10
DELETE FROM db.dbo.table11
DELETE FROM db.dbo.table12
DELETE FROM db.dbo.table13
DELETE FROM db.dbo.table14
DELETE FROM db.dbo.table15

执行脚本后,我发现正在从未包含在脚本中的表中删除数据。

为了验证哪些表有数据,我使用here 找到的 SO 答案中提供的以下查询。

SELECT 
    t.NAME AS TableName,
    SUM(p.rows) AS [RowCount]
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
WHERE   
    i.index_id <= 1
GROUP BY 
    t.NAME, i.object_id, i.index_id, i.name 
ORDER BY 
    SUM(p.rows) DESC

我有数据库的备份。接下来我:

  1. 恢复数据库
  2. 运行“表数据”查询:再次检查删除/截断脚本中未包含的表中是否确实存在数据
  3. 执行删除/截断脚本
  4. 运行“表数据”查询

我的发现是这样的:正在从我的删除/截断脚本中未定义的表中删除数据。

我的问题:鉴于我要从数据库中的多个表而不是所有表中删除或截断,如何从未在删除或截断语句中定义的表中删除数据?

【问题讨论】:

    标签: sql-server database sql-delete truncate sql-server-2016


    【解决方案1】:

    如果表包含具有级联引用完整性约束操作值CASCADE 的外键,则可以从未在删除或截断语句中定义的表中删除数据行。

    我发现以下位于here 的 Microsoft 文档很有帮助。

    级联参照完整性
    通过使用级联参照完整性约束,您可以定义操作 当用户尝试删除或更新密钥时,数据库引擎采取的 现有的外键指向哪个。以下级联动作可以是 已定义。
    ...
    级联
    在引用中更新或删除相应的行 在父表中更新或删除该行时的表。级联 如果时间戳列是 外键或引用的键。 ON DELETE CASCADE 不能 为具有 INSTEAD OF DELETE 触发器的表指定。在更新 不能为具有 INSTEAD OF UPDATE 的表指定 CASCADE 触发器。
    ...

    接下来检查表,数据正在被删除,是否有外键级联参照完整性约束以及操作值是什么。

    方法一: 查询它。我正在使用在here 找到的 SO 答案中提供的以下查询。

    SELECT name, delete_referential_action_desc
    FROM sys.foreign_keys
    

    方法二: 在 Microsoft SQL Server Management Studio 2016 中使用对象资源管理器:

    1. 导航到要从中删除数据的表
    2. 展开表格对象
    3. 展开“密钥”文件夹
    4. 右键单击外键并单击修改
    5. 展开位于右下窗格中的INSERT And UPDATE Specific 部分
    6. 识别Delete Rule

    我发现正在删除数据的表有一个外键级联参照完整性约束,其值为Cascade

    此外,我测试了这是否是真正的原因。我将值更新为No Action,恢复数据库,执行删除/截断脚本,运行“表数据”查询,发现数据保持不变。

    【讨论】:

    • 所以你提出一个问题来回答自己?顺便说一句,我没有投票。
    • 以防万一,考虑触发器也可能导致删除。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-14
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 2015-03-05
    相关资源
    最近更新 更多