【问题标题】:Delete from FILETABLE with foreign key constraint使用外键约束从 FILETABLE 中删除
【发布时间】:2016-01-20 17:05:51
【问题描述】:

背景

我正在研究创建一个简单的网络应用程序,其中的一部分将显示与 Items 关联的 Images。我决定研究使用 SQL Server 的FILETABLE 功能,该功能将允许将二进制图像数据直接上传到公开的共享中。因此,有一个用例允许通过 Windows 资源管理器删除文件(FILETABLE 中的行)。此示例复制了该问题,该问题源于与 FILETABLE 的外键关系。

结构

已经使用文件资源管理器将图像添加到FILETABLE 与path_locator 的0xFF5354649088A1EFEE8F747CD11030F80800170620:

CREATE TABLE [dbo].[Image] AS FILETABLE WITH (FileTable_Directory = 'Images');
GO
CREATE TABLE [dbo].[ImageLink] (
     [id] INT NOT NULL IDENTITY(1, 1)
    ,[path_locator] HIERARCHYID NOT NULL
    ,FOREIGN KEY ([path_locator]) REFERENCES [dbo].[Image] ([path_locator])
);
GO
INSERT INTO [dbo].[ImageLink] ([path_locator]) VALUES (0xFF5354649088A1EFEE8F747CD11030F80800170620);

问题

通过文件资源管理器删除文件时...

...文件从目录中消失,因为 Windows 报告删除成功,但该行并未从 FILETABLE 中删除。

但是,尝试通过SQL Server删除时,抛出熟悉的引用约束冲突错误:

DELETE FROM [dbo].[Image] WHERE [path_locator] = 0xFF5354649088A1EFEE8F747CD11030F80800170620;

Msg 547, Level 16, State 0, Line 69
The DELETE statement conflicted with the REFERENCE constraint "FK__ImageLink__path___5070F446". The conflict occurred in database "FileTableTest", table "dbo.ImageLink", column 'path_locator'.

我向FILETABLE 添加了一个AFTER DELETE 触发器,目的是删除引用行,但这也不会被执行。

问题

  • 如何在通过 Windows 资源管理器删除时通过链接表传播删除?
  • 是否有某种 SQL Server/Windows API 挂钩可以检测并执行处理删除的 DML 代码?

更新 #1

来自BOL,以下部分确认了该行为,但未提供任何进一步的信息。

事务语义

当您使用文件 I/O API 访问 FileTable 中的文件时,这些操作与任何用户事务无关,并且具有以下附加特征:

  • 由于对 FileTable 中 FILESTREAM 数据的非事务访问与任何事务无关,因此它没有任何特定的隔离语义。但是,SQL Server 可以使用内部事务对 FileTable 数据强制执行锁定或并发语义。这种类型的任何内部事务都是通过读提交隔离完成的。

【问题讨论】:

  • 请分享SELECT * FROM sys.database_filestream_options的结果
  • @lad2025 non_trasacted_access = 2, non_transacted_access_desc = 'FULL'

标签: sql-server sql-server-2012 sql-server-2014 filetable


【解决方案1】:

问题是外键。

在您的外键中使用“ON CASCADE DELETE”,因此当您通过文件资源管理器删除时,关联的 ImageLink 也会被删除。

【讨论】:

  • 将 FK 定义更改为:,FOREIGN KEY ([path_locator]) REFERENCES [dbo].[Image] ([path_locator]) ON DELETE CASCADE 确实会传播删除。不知道我当时怎么没有想到这一点,但谢谢!
【解决方案2】:

看起来,外键有问题。由于该表附加了外键,因此您不能简单地删除该行,因为外键约束失败。

所以首先禁用 sql 中的外键检查: SET FOREIGN_KEY_CHECKS = 1;

然后尝试删除这个&是的,不要忘记通过以下方式将外键检查设置为 0: 设置 FOREIGN_KEY_CHECKS = 0; 删除行后。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-11
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 2018-11-28
    相关资源
    最近更新 更多