如何使用SQL Server列出文件夹中的文件
如何在不使用xp_cmdshell
存储过程的情况下列出SQL Server中的文件夹内的文件?
你可以使用xp_dirtree
它有三个参数:
根目录的path , 深度要获取文件和文件夹,最后一个是仅显示文件夹或文件夹和文件。
示例: EXEC xp_dirtree 'C:\', 10, 1
可以使用xp_DirTree完成,然后根据需要循环生成完整的文件path。
以下是我用来自动将数据库还原到testing服务器的脚本的摘录。 它扫描一个文件夹和所有子文件夹的任何备份文件,然后返回完整的path。
DECLARE @BackupDirectory SYSNAME = @BackupFolder IF OBJECT_ID('tempdb..#DirTree') IS NOT NULL DROP TABLE #DirTree CREATE TABLE #DirTree ( Id int identity(1,1), SubDirectory nvarchar(255), Depth smallint, FileFlag bit, ParentDirectoryID int ) INSERT INTO #DirTree (SubDirectory, Depth, FileFlag) EXEC master..xp_dirtree @BackupDirectory, 10, 1 UPDATE #DirTree SET ParentDirectoryID = ( SELECT MAX(Id) FROM #DirTree d2 WHERE Depth = d.Depth - 1 AND d2.Id < d.Id ) FROM #DirTree d DECLARE @ID INT, @BackupFile VARCHAR(MAX), @Depth TINYINT, @FileFlag BIT, @ParentDirectoryID INT, @wkSubParentDirectoryID INT, @wkSubDirectory VARCHAR(MAX) DECLARE @BackupFiles TABLE ( FileNamePath VARCHAR(MAX), TransLogFlag BIT, BackupFile VARCHAR(MAX), DatabaseName VARCHAR(MAX) ) DECLARE FileCursor CURSOR LOCAL FORWARD_ONLY FOR SELECT * FROM #DirTree WHERE FileFlag = 1 OPEN FileCursor FETCH NEXT FROM FileCursor INTO @ID, @BackupFile, @Depth, @FileFlag, @ParentDirectoryID SET @wkSubParentDirectoryID = @ParentDirectoryID WHILE @@FETCH_STATUS = 0 BEGIN --loop to generate path in reverse, starting with backup file then prefixing subfolders in a loop WHILE @wkSubParentDirectoryID IS NOT NULL BEGIN SELECT @wkSubDirectory = SubDirectory, @wkSubParentDirectoryID = ParentDirectoryID FROM #DirTree WHERE ID = @wkSubParentDirectoryID SELECT @BackupFile = @wkSubDirectory + '\' + @BackupFile END --no more subfolders in loop so now prefix the root backup folder SELECT @BackupFile = @BackupDirectory + @BackupFile --put backupfile into a table and then later work out which ones are log and full backups INSERT INTO @BackupFiles (FileNamePath) VALUES(@BackupFile) FETCH NEXT FROM FileCursor INTO @ID, @BackupFile, @Depth, @FileFlag, @ParentDirectoryID SET @wkSubParentDirectoryID = @ParentDirectoryID END CLOSE FileCursor DEALLOCATE FileCursor
创build一个具有外部访问权限的SQLCLR程序集,该权限返回文件列表作为结果集。 有很多例子如何做到这一点,例如。 另一个TVF:从目录返回文件或在SQLCLR(第1部分)的xp_cmdshell中进行交易 – 列出目录内容 。
如果你想要,你可以使用CLR函数/汇编实现这一点。
- 创build一个SQL Server CLR程序集项目。
- 转到属性并确保连接的权限级别设置为外部
- 将Sql函数添加到程序集。
下面是一个例子,它可以让你像表格一样select结果集。
public partial class UserDefinedFunctions { [SqlFunction(DataAccess = DataAccessKind.Read, FillRowMethodName = "GetFiles_FillRow", TableDefinition = "FilePath nvarchar(4000)")] public static IEnumerable GetFiles(SqlString path) { return System.IO.Directory.GetFiles(path.ToString()).Select(s => new SqlString(s)); } public static void GetFiles_FillRow(object obj,out SqlString filePath) { filePath = (SqlString)obj; } };
和你的SQL查询。
use MyDb select * From GetFiles('C:\Temp\');
但请注意,您的数据库需要使用以下SQL命令启用CLR程序集function。
sp_configure 'clr enabled', 1 GO RECONFIGURE GO
CLR程序集(如XP_CMDShell
)在默认情况下是禁用的,所以如果不使用XP Cmd Shell的原因是因为你没有权限 ,那么你可能会被卡住这个选项以及…只是FYI。
我寻找了很多年来寻找一个体面的简单的解决scheme,最后find了一些可笑的复杂的CLR解决scheme,所以决定写我自己的简单的VB一个。 只需从Installed Templates下的Database选项卡创build一个新的VB CLR项目,然后添加一个新的SQL CLR VB用户定义函数 。 我将其重命名为CLRGetFilesInDir.vb 。 这是它里面的代码…
Imports System Imports System.Data Imports System.Data.Sql Imports System.Data.SqlTypes Imports Microsoft.SqlServer.Server Imports System.IO ----------------------------------------------------------------------------- Public Class CLRFilesInDir ----------------------------------------------------------------------------- <SqlFunction(FillRowMethodName:="FillRowFiles", IsDeterministic:=True, IsPrecise:=True, TableDefinition:="FilePath nvarchar(4000)")> _ Public Shared Function GetFiles(PathName As SqlString, Pattern As SqlString) As IEnumerable Dim FileNames As String() Try FileNames = Directory.GetFiles(PathName, Pattern, SearchOption.TopDirectoryOnly) Catch FileNames = Nothing End Try Return FileNames End Function ----------------------------------------------------------------------------- Public Shared Sub FillRowFiles(ByVal obj As Object, ByRef Val As SqlString) Val = CType(obj, String).ToString End Sub End Class
我还将“ 项目属性”窗口中的“程序集名称”更改为CLRExcelFiles ,将“默认名称空间”更改为CLRGetExcelFiles 。
注意:如果使用less于SQL Server 2012的任何东西,请将目标框架设置为3.5。
编译该项目,然后将CLRExcelFiles.dll从\ bin \ release复制到SQL Server机器上的某个位置,如C:\ temp,而不是您自己的。
在SSMS中:
CREATE ASSEMBLY <your assembly name in here - anything you like> FROM 'C:\temp\CLRExcelFiles.dll'; CREATE FUNCTION dbo.fnGetFiles ( @PathName NVARCHAR(MAX), @Pattern NVARCHAR(MAX) ) RETURNS TABLE (Val NVARCHAR(100)) AS EXTERNAL NAME <your assembly name>."CLRGetExcelFiles.CLRFilesInDir".GetFiles; GO
然后调用它
SELECT * FROM dbo.fnGetFiles('\\<SERVERNAME>\<$SHARE>\<folder>\' , '*.xls')
注意:即使我将权限级别更改为项目属性下的SQLCLR选项卡上的EXTERNAL_ACCESS,但每次我(重新)创build它时仍需要运行此项。
ALTER ASSEMBLY [CLRFilesInDirAssembly] WITH PERMISSION_SET = EXTERNAL_ACCESS GO
和wullah! 这应该工作。
非常简单,只需使用SQLCMD语法即可。
请记住在SSMS中启用SQLCMD模式,查看查询 – > SQLCMD模式
尝试执行:
!! DIR
!!:走
或者可能:
!! DIR“c:/ temp”
!!:走