2011-07-06 82 views
0

我有一個SQL服務器運行在我的Windows服務器上,並且在一個表的特定列上,我有一個Zip文件的路徑(它反過來又有數據庫中存儲的數據的來源)。其中一些無效(不匹配數據庫中的數據)。我需要讓SQL Server驗證這些Zip文件是否存在,並且它們與存儲zip文件的路徑和名稱的列匹配。這樣我將刪除錯誤的文件路徑列對應關係。如何使用SQL驗證Windows中是否存在文件?

回答

2

但是,您可以使用xp_fileexist請注意這是無證和不支持。

您可以使用SQLCLR,但是您並未指定您正在使用的SQL Server版本,因此它可能不相關 - 在任何情況下,默認情況下都會禁用它,並且安全策略會阻止其用於有一些地方。

您可以使用#temp表和xp_cmdshell,但是由於SQLCLR相同的原因,xp_cmdshell通常處於禁用狀態。根據新的要求

/* if you need to enable xp_cmdshell: 

exec master..sp_configure 'show adv', 1; 
reconfigure with override; 
exec master..sp_configure 'xp_cmdshell', 1; 
reconfigure with override; 
exec master..sp_configure 'show adv', 0; 
reconfigure with override; 

*/ 

SET NOCOUNT ON; 

DECLARE 
    @file VARCHAR(1000), 
    @path VARCHAR(255), 
    @cmd VARCHAR(2048); 

SELECT 
    @file = 'foo.zip', 
    @path = 'C:\wherever\'; 

SELECT @cmd = 'dir /b "' + @path + @file + '"'; 

CREATE TABLE #x(a VARCHAR(1255)); 
INSERT #x EXEC master..xp_cmdshell @cmd; 
IF EXISTS (SELECT 1 FROM #x WHERE a = @file) 
    PRINT 'file exists'; 
ELSE 
    PRINT 'file does not exist'; 
DROP TABLE #x; 

編輯。它顯示錶中或數據庫中的文件列表,並指示該文件是僅位於一個位置還是兩者。它假定路徑+文件是< = 900個字符長(僅能夠在至少一側使用索引)。

USE tempdb; 
GO 

CREATE TABLE dbo.files(f VARCHAR(1000)); 

INSERT dbo.files(f) SELECT 'zip_that_does_not_exist.zip' 
    UNION ALL SELECT 'c:\path\file_that_does_not_exist.zip' 
    UNION ALL SELECT 'c:\path\file_that_exists.zip' 
    UNION ALL SELECT 'zip_that_exists.zip'; 

DECLARE 
    @path VARCHAR(255), 
    @cmd VARCHAR(2048); 

SELECT 
    @path = path_column, 
    @cmd = 'dir /b "' + path_column + '"' 
FROM 
    dbo.table_that_holds_path; 

CREATE TABLE #x(f VARCHAR(900) UNIQUE); 

INSERT #x EXEC master..xp_cmdshell @cmd; 
DELETE #x WHERE f IS NULL; 
UPDATE #x SET f = LOWER(f); 

WITH f AS 
(
    SELECT f = REPLACE(LOWER(f), LOWER(@path), '') 
     FROM dbo.files 
) 
SELECT 
    [file] = COALESCE(x.f, f.f), 
    [status] = CASE 
     WHEN x.f IS NULL THEN 'in database, not in folder' 
     WHEN f.f IS NULL THEN 'in folder, not in database' 
     ELSE 'in both' END 
FROM 
    f FULL OUTER JOIN #x AS x 
    ON x.f = f.f; 

DROP TABLE #x, dbo.files; 
+0

謝謝你的回答,只是另一個問題。我如何使用包含我的「@path」的另一個表中的值在我的所有列上自動執行此腳本? – Diogo

+0

是否所有文件都在同一個文件夾中,或者每個文件都可能位於不同的文件夾中?讓我猜,你在一列中有完整的路徑,而不是分開路徑和文件名? –

+0

所有文件都在同一個文件夾中,每個文件都有(或可能有)數據庫的完整路徑。 – Diogo

7

可以使用無證PROC​​ xp_fileexist將返回1,如果它存在,否則爲0

SET NOCOUNT ON 
DECLARE @iFileExists INT 

EXEC master..xp_fileexist 'c:\bla.txt', 
@iFileExists OUTPUT 

select @iFileExists 
+0

您是否需要額外的權限來執行文件讀取操作 - 正如您在設置inital sql帳戶時默認沒有的權限一樣? –

+0

xp_fileexist在SQL Server運行IIRC的帳戶下運行,由維護作業和其他內部函數使用 – SQLMenace

+0

啊,非常酷。謝謝:) –

相關問題