我在Windows Server上运行了一个SQL Server,并且在表的特定列中,我有一个Zip文件的路径(后者又有数据源存储在数据库中)。其中一些无效(与数据库中的数据不匹配)。我需要让SQL Server验证这些Zip文件是否存在,以及它们是否与存储zip文件的路径和名称的列相匹配。这样我就会删除错误的文件路径列对应关系。
答案 0 :(得分:7)
你可以使用未记录的proc xp_fileexist
如果存在则返回1,否则返回0
SET NOCOUNT ON
DECLARE @iFileExists INT
EXEC master..xp_fileexist 'c:\bla.txt',
@iFileExists OUTPUT
select @iFileExists
答案 1 :(得分:2)
您可以使用xp_fileexist但请注意它没有记录且不受支持。
某些人可以使用SQLCLR,但是您没有指定您正在使用的SQL Server版本,因此它可能不相关 - 并且在任何情况下都默认禁用它,并且安全策略阻止其在某些版本中使用地方。您可以使用#temp表和xp_cmdshell,但是xp_cmdshell通常会被禁用,原因与SQLCLR相同。
/* 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;