如何将存储在MS Access中引用的文件共享上的附件迁移到SQL Server

qmb5sa22  于 2022-10-22  发布在  SQL Server
关注(0)|答案(1)|浏览(202)

我有一个MS Access数据库,我们正在将其转换为SQL Server后端。此数据库有一个Attachments表,其中包含几个简单列:

PK, FK to MainTable.RecordID, Description, filename

附件存储在文件共享中。VBA代码使用硬编码文件路径和ShellExecute将附件保存到RecordID子文件夹下的目录中。
我们将使用文件流在SQL Server中存储附件。
我需要将这些附件从文件共享移动到SQL Server,同时保持RecordID的完整性。SQL Server表和列已设置。
这些附件的扩展名不同(.msg、.doc、.xlsx、.pdf)
我一直在研究“OPENROWSET”,但我看到的每个示例都只使用一个文件。
我一直在调查SSMA,但找不到我想要的。
任何我可以使用/重新利用的参考/参考文章或代码资源都将不胜感激。

z0qdvdin

z0qdvdin1#

听起来您想编写一个SQL存储过程,它将查找给定文件路径中的所有文件,遍历这些文件,并将文件插入表中。
这篇文章将在总体上有所帮助:https://www.mssqltips.com/sqlservertip/5432/stored-procedure-to-import-files-into-a-sql-server-filestream-enabled-table/
本文是关于xp_dirtree:https://www.sqlservercentral.com/blogs/how-to-use-xp_dirtree-to-list-all-files-in-a-folder
下面是从SQL读取文件系统的示例代码。这是未经测试的代码,您需要根据需要进行修改,但它可以让您了解如何进行循环和读入文件。

--You will need xm_cmdshell enabled on SQL server if not already.
USE master
GO
EXEC sp_configure 'show advanced option',1
RECONFIGURE WITH OVERRIDE
EXEC sp_configure 'xp_cmdshell',1
RECONFIGURE WITH OVERRIDE
GO

--Create a variable to hold the pickup folder.
DECLARE @PickupDirectory nvarchar(512) = '\\folder_containing_files_or_folders\';

--Create a temp table to hold the files found in the pickup directory.
PRINT 'Parsing directory to identify most recent file.';
DECLARE @DirTree TABLE (
    id int IDENTITY(1,1)
    , subdirectory nvarchar(512)
    , depth int
    , isfile bit
);

--Enumerate the pickup directory.
INSERT @DirTree
EXEC master.sys.xp_dirtree @PickupDirectory,1,1 --Second variable is depth.

--Create variables to loop through folders and files.
DECLARE @folderCount int;
DECLARE @folderName nvarchar(max);
DECLARE @folderPath nvarchar(max);
DECLARE @i int = 0;

DECLARE @fileCount int;
DECLARE @fileName NVARCHAR(max);
DECLARE @filePath varchar(max);
DECLARE @j int = 0;

DECLARE @RecordID nvarchar(50);
DECLARE @SQLText NVARCHAR(max);

SET @folderCount = (SELECT Count(*) FROM @DirTree WHERE isfile = 0);

WHILE ( @i < @folderCount )
BEGIN
    --Get the next folder to process.
    SET @folderName = (
        SELECT TOP 1 subdirectory 
        FROM @DirTree as dt
            LEFT OUTER JOIN @processedFolders as pf
                on pf.folder_name = dt.subdirectory
        WHERE isfile = 0 
            AND pf.folder_name IS NULL
    );

    --Get the recordID from folder name.
    SET @recordID = @folderName; --Edit this to get the RecordID from your folder structure.

    --Concat root path and new folder to get files from.
    SET @folderPath = @PickupDirectory + @folderName + '\';

    --Enumerate the this subdirectory to process files from.
    INSERT @filesToProcess
    EXEC master.sys.xp_dirtree @folderPath,1,1

    --Get count of files to loop through.
    SET @fileCount = (SELECT COUNT(*) FROM @filesToProcess WHERE isfile = 1);

    WHILE (@j < @fileCount)
    BEGIN
        --Get next filename.
        SET @fileName = (SELECT TOP 1 subdirectory FROM @filesToProcess WHERE isfile = 1);

        --Concat the whole file path.
        SET @filePath = @folderPath + @fileName;

        SET @SQLText = '
            INSERT INTO [table_name](RecordID,[filename],[filestreamCol])   
            SELECT 
                ''' + @RecordID + '''
                , ''' + @fileName + '''
                , BulkColumn 
            FROM OPENROWSET(Bulk ''' + @filePath + ''', Single_Blob) as tb'

        EXEC Sp_executesql @SQLText

        DELETE FROM @filesToProcess
        WHERE subdirectory = @fileName;

        SET @j = @j + 1;
    END

    INSERT INTO @processedFolders (folder_name)
    SELECT @folderName;

    PRINT 'Folder complete: ' + @folderName;

    SET @i = @i + 1
END

我想您只需要使用上面的xp_dirtree命令解析根目录。这将显示应包含“RecordID”的所有子目录。将RecordID读入变量,然后解析每个子目录以获得实际文件。如果需要更详细的代码,则必须显示目录结构和目标表的一些示例。

相关问题