【问题标题】:Efficiently Storing Images with Access and SQL Server使用 Access 和 SQL Server 高效存储图像
【发布时间】:2020-12-10 22:27:33
【问题描述】:

我目前正在从事一个项目,我将在 Microsoft SQL Server 中创建一个关系数据库,其中 Access 作为用户输入信息的前端。

用户的其中一个请求是允许上传与特定记录相关联的图像文件。

虽然我知道 Access 能够允许将图像文件等附件放入记录中,但根据我的阅读,这听起来是一种非常低效的文件存储方式,从长远来看可能会降低性能。

我看到很多人建议将图像文件位置存储为实际条目,并将图像存储在文件系统中。

我的问题是,是否有一种好方法可以基本上允许用户通过 Access 上传图像,但将这些图像保存在文件系统上,然后让记录自动变成文件位置。 (换句话说,文件会被自动保存并在特定文件夹中指定一个ID,并且记录本身将包含文件路径)

我对其他想法持开放态度,只要它们仍然具有可扩展性并能高效工作。我已经看到了一些想法,例如将文件保存到一个单独的表格中并自动生成想法,但我不确定这是否会很好。

任何建议都将不胜感激,无论是通过 Access 还是 SQL Server 实现相同结果的方法。我也知道如何在 Python3 中编写一些代码,如果这将是一种更简单的方法来实现这一点,但我尽可能希望最终用户能够通过一个界面来实现一切。

【问题讨论】:

  • 你可以看看 SQL Server File Tables。文件内容在物理上存储为文件系统上的单独文件(由 SQL Server 管理),并可通过 UNC 路径(如普通文件)或通过 varbinary(MAX) 列中的 T-SQL 访问。

标签: sql-server image ms-access


【解决方案1】:

在 SQL Server 中,您可以选择将文件(图像和其他文件)作为记录保存在数据库中,并且 SQL Server 将此文件存储在文件系统而不是数据库中。

这样你有一些好处:

  • 您的文件不会影响数据库文件大小
  • 您可以使用T-SQL 添加/删除您的文件
  • 您可以轻松备份数据库和所有文件

对于这种方法,您需要在数据库中启用file stream

您需要 3 个步骤来启用file stream

  1. 在服务级别启用文件流
  2. 在数据库中添加文件组
  3. 创建要存储的表

第一步(在服务级别启用文件流):

打开 SQL Server 配置管理器并选择您的数据库并启用文件流。

它的文档是here

注意:如果找不到SQL Server Configuration Manager,请参阅此document

然后在 SQL Server Management Studio 中,单击 New Query 以显示查询编辑器并在查询编辑器中输入以下 Transact-SQL 代码并单击执行:

EXEC sp_configure filestream_access_level, 2  
RECONFIGURE 

然后重启 SQL Server 服务 注意:您可以在 SQL Server Management Studio 图形界面中执行此操作,如下所示:

第二步(在数据库中添加文件组):

  • filestream文件组添加到数据库

  • 添加数据库文件

或者您可以通过基于此document 的脚本来完成:

CREATE DATABASE Archive 
ON
PRIMARY ( NAME = Arch1,
    FILENAME = 'c:\data\archdat1.mdf'),
FILEGROUP FileStreamGroup1 CONTAINS FILESTREAM( NAME = Arch3,
    FILENAME = 'c:\data\filestream1')
LOG ON  ( NAME = Archlog1,
    FILENAME = 'c:\data\archlog1.ldf')
GO

第三步(创建表和存储):

然后简单的步骤是创建表:

CREATE TABLE Archive.dbo.Records
(
    [Id] [uniqueidentifier] ROWGUIDCOL NOT NULL UNIQUE,
    [Image] VARBINARY(MAX) FILESTREAM NULL
)

注意:[uniqueidentifier] ROWGUIDCOL NOT NULL UNIQUE 的列类型为必填项,您的图像列类型应为VARBINARY(MAX) FILESTREAM

然后你可以像下面这样插入任何数据,more example:

INSERT INTO Archive.dbo.Records
    VALUES (newid (), 3, 
      CAST ('Seismic Data' as varbinary(max)));

但是如果你想使用MS Access,我认为最好的方法是将文件名存储在数据库中并通过编码处理文件管理。

【讨论】:

  • 谢谢,除了其他 cmets 之外,这非常有用。我能够设置文件表,它似乎按预期工作。我想我会命名目录以对应数据库中的相关项目。我想知道的一件事是,Access 是否可以直接从这里访问文件?我想我可能需要有点创意并编写一个查询来自动生成实际的文件路径,以便用户查看基于父路径定位器的文件,但如果有更直接的方法会很好做这个。再次感谢!
  • 欢迎您,您不需要文件路径,您只需要读取行并将图像加载为二进制文件并将其发送给请求的人。
【解决方案2】:

这真的归结为服务器将在同一个网络上。

换句话说?传递存储指向相关文件的链接。原因是巨大的。

例如: 假设您有一个巨大的 PDF 文件夹,这些文件夹是从 Access 前端链接和管理的。好吧,现在我可以使用各种工具来处理、浏览、查看、使用这些文件,并且可以在 Access 之外进行。这适用于任何数据库附近的该死。

通常说 PDF 是 2020-12-06 I34343.PDF

因此,我们现在可以根据今天的日期从该文件夹中获取发票 I34343。我什至不需要软件来做到这一点。所以现在其他代码系统,其他程序可以直接抓取和使用那些文件。哎呀,甚至可以在 Access 之外编写和运行每晚打印一些 PDF 的批处理文件。

那么,使用过数据库“内部”文件和外部文件?获胜者是文件夹和文件 - 以及指向这些文件的链接。在 Access 表单中有一些按钮或链接是微不足道的,当按下时,您可以加载、使用、显示、处理、打印或对这些 PDF 文件执行任何操作。如果将文件放在数据库中,则无法轻松读取、抓取和使用这些文件。

然而,这条规则有一个很大的例外。

也就是说,如果服务器 + 数据库不在您的网络上,并且您没有公共文件共享系统。例如,您可能正在构建一个网站或使用托管的 SQL 服务器。您有一个到该数据库的套接字连接,但您将无法使用该服务器平台上的文件系统。在这种情况下,将文件存储在数据库中会带来很大的好处,因为您不再需要文件系统。

所以现在任何可以连接到数据库的系统也可以提取文件。所以,我不建议将文件存储在数据库中 - 这是一个有大量限制和简单文件操作的选择,复制文件和使用这些文件变得非常痛苦。

但是,如果您没有通用文件共享系统?然后数据库中的文件而不是文件路径是一个选项。当您有选择和可用的文件系统时?然后肯定会使用文件路径。这也意味着对于存档、备份和搜索 PDF 等,您可以使用一大堆其他搜索工具。如果您将数据库中的文件捆绑在一起,那么您的选择将变得非常有限。

在数据库中存储的另一个非常大的用例?拇指指甲和预览。在可能的情况下,对于这样的小文件,您对系统上的每个文件都有这个“额外”的预览文件?然后,您可以消除文件混乱,并且对于每个说 PDF 文件,预览缩略图文件会导致大量文件计数膨胀。因此,对于小文件,可以再次创建一个用例来存储在数据库中。例如,在这个网页上,PDF文件存储在一个大的PDF文件文件夹系统+层次结构中?我不想用 jpg 或 PNG 文件预览来搞乱所有这些文件。

在上面,PDF 预览缩略图存储在数据库中。因此,这不会用预览文件弄乱漂亮的 PDF 和文件夹。还有其他系统可以扫描/读取放入文件夹中的文件并对其执行操作。因此,再一次,外部文件提供了更多选项,甚至可以在无需使用数据库的情况下对这些文件执行操作的第 3 方软件(第 3 方工具甚至可能不支持)。

所以在数据库中存储文件或图像?对于大量小文件,可以很好地存储在数据库中,因为它可以大量减少文件和文件夹的混乱。

【讨论】:

  • 多年来我一直使用 Access 和 SQL 后端。我所有的系统都保存指向 SQL 数据库中文档的指针。我正在研究更改为 SQL FileTable 以获得更好的事务完整性和在文档上使用 T-SQL 的能力。从我观看的在线课程和阅读的内容来看,FileTable 可以将自己作为标准 UNC 文件夹呈现给客户端。列出文档,探索“虚拟文件系统”,使用复制命令添加文档,编辑这些文档。 FileTable 有什么缺点?
【解决方案3】:

所以我最终对此做了一些解决方法。

我首先根据上面 cmets 中 Yari 和 Guzman 的反馈设置了一个 FileTable。

我很难将 Access 直接连接到 FileTable,因此我使用了一个函数来根据记录的唯一 ID 在 FileTable 目录中创建一个目录。

基本上,我使用以下 vba 代码来创建它,因此 Access 将自动使用 ID 的名称创建一个目录(除非它已经存在),然后打开同一个目录。

这实现了我试图完成的相同事情,而无需直接连接到 FileTable。

函数在指定的字符串处创建一个新目录。按钮单击命令将该功能与指定的父目录一起使用,新文件夹以当前记录的唯一标识符命名(如果它不存在)。然后它会打开该文件夹,以便添加附件等。

Sub MakeFolder(strPath As String)
    If Dir(strPath, vbDirectory) > vbNullString Then
        Exit Sub
    End If
    MkDir strPath
End Sub

Private Sub Command5_Click()
 MakeFolder "\\ServerName\MSSQLSERVER\FileStream\DocumentStore\" & Me.ID
 Shell "explorer.exe" & " " & "\\ServerName\MSSQLSERVER\FileStream\DocumentStore\" & Me.ID, vbNormalFocus
End Sub

最终结果会出现在我最初想要的 SQL FileTable 中。

【讨论】:

    猜你喜欢
    • 2011-01-05
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 1970-01-01
    • 2013-09-18
    • 2014-08-13
    相关资源
    最近更新 更多