2017-03-27 20 views
-1

J'ai une liste massive de fichiers stockés en tant que chemins dans le serveur SQL. Il est assez facile de diviser les chemins en répertoires, cependant, je dois être capable de présenter une liste de tous les fichiers et dossiers d'un niveau à la fois. SQL Server a des utilitaires intégrés pour gérer cela pour les fichiers locaux sur le serveur, mais ils ne s'appliquent pas dans ce cas. L'utilisation d'un caractère générique renverra tout ce qui se trouve en dessous du répertoire en cours, donc j'ai supprimé cela.Produire la liste des répertoires et des fichiers basés sur le répertoire en utilisant T-SQL

données:

C:\test\file.txt 
C:\test\level2\file.txt 
C:\test\level2\bc.txt 
C:\test\level3\another.txt 

Idéalement, je voudrais passer dans un dossier, et de voir tous les fichiers et dossiers à ce niveau. Ensuite, je peux présenter cela dans un contrôle treegrid, mais cette partie est en dehors de la portée de la question.

Passant 'C: \ test \' doit retourner:

C:\test\file.txt 
C:\test\level2 
C:\test\level3 
+0

'CHOISIR un fichier FROM datatable WHERE filename LIKE 'C: \ test \%''? –

+0

'où Filename comme @Path + '%' et Filename pas comme @Path + '% \%'', c'est-à-dire tout au niveau désiré mais pas plus profond, obtiendra des fichiers mais pas des dossiers. Vous pouvez «union» une requête similaire pour obtenir des dossiers. – HABO

+0

HABO - merci, cela me rapproche! Juste à comprendre comment obtenir des répertoires seulement maintenant. – Proteus

Répondre

0

Cela fait l'affaire. OrderBy est inclus pour afficher les noms de fichiers avant les noms de dossier. Si vous ne vous souciez pas de la commande, vous pouvez la supprimer et la clause order by.

-- Sample data. 
declare @Filenames as Table (Filename VarChar(128)); 
insert into @Filenames (Filename) values 
    ('C:\test\file.txt'), ('C:\test\level2\file.txt'), 
    ('C:\test\level2\bc.txt'), ('C:\test\level3\another.txt'), 
    ('C:\test\level3\deeper\nothing.txt'); 
select * from @Filenames; 

declare @Path as VarChar(128) = 'C:\test\'; 

-- Get the files. 
-- Filename longer than @Path , but not containing an additional reverse solidus ('\'). 
select Filename, 1 as OrderBy 
    from @Filenames 
    where Filename like @Path + '%' and Filename not like @Path + '%\%' 
union 
-- Get the directories. 
-- Filename longer than @Path and containing one additional reverse solidus ('\'). 
-- Locate the reverse solidus after the length of @Path and trim from that point onwards. 
-- Since there may be many files in each folder, use distinct to get each folder once. 
select distinct SubString(Filename, 1, CharIndex('\', Filename, Len(@Path) + 1) - 1), 2 
    from @Filenames 
    where Filename like @Path + '%\%' and Filename not like @Path + '%\%\%' 
order by OrderBy, Filename; 
+0

Merci beaucoup, celui-ci fonctionne! – Proteus

+0

Toujours travailler avec ce code - il retourne les dossiers seulement s'ils ont un répertoire de fichiers sous eux. S'il y a un dossier un niveau plus bas mais pas de fichiers, il ne retourne rien. – Proteus

+0

Voulez-vous dire que si vous cherchez '' C: \ foo \ ''et qu'un répertoire vide correspond, ce répertoire n'est pas sorti? Si '' C: \ foo \ '', avec le solide de fin arrière (" \ "), est dans le tableau, il sera sélectionné. '' C: \ foo'' est, selon toutes les apparences, un fichier sans type dans le dossier racine et pas un dossier. – HABO

0

Hope this helps

DECLARE @SearchDir VARCHAR(4000) 
SET @SearchDir = 'C:\test\' 

;WITH cte_TestData(Directory) AS 
(
SELECT 'C:\test\file.txt' UNION ALL 
SELECT 'C:\test2\file.txt' UNION ALL 
SELECT 'C:\test\level2\bc.txt' UNION ALL 
SELECT 'C:\test\level3\another.txt' UNION ALL 
SELECT 'C:\test\level1\level2\bc.txt' UNION ALL 
SELECT 'C:\test\level1\level2\level3\another.txt' 
) 
SELECT CASE 
     WHEN CHARINDEX('\', REPLACE(Directory, @SearchDir, '')) > 0 
      THEN @SearchDir + LEFT(REPLACE(Directory, @SearchDir, ''), CHARINDEX('\', REPLACE(Directory, @SearchDir, '')) - 1) 
     ELSE @SearchDir + REPLACE(Directory, @SearchDir, '') 
     END 
FROM cte_TestData 
WHERE CHARINDEX(@SearchDir, Directory) > 0 
    AND LEN(REPLACE(Directory, @SearchDir, '')) - LEN(REPLACE(REPLACE(Directory, @SearchDir, ''), '\', '')) <= 1 
0

similaires à la solution de Gouri

DECLARE @SearchDir VARCHAR(4000) 
SET @SearchDir = 'C:\test\' 

;WITH cte_TestData(Directory) AS 
(
SELECT 'C:\test\file.txt' UNION ALL 
SELECT 'C:\test2\file.txt' UNION ALL 
SELECT 'C:\test\level2\bc.txt' UNION ALL 
SELECT 'C:\test\level3\another.txt' UNION ALL 
SELECT 'C:\test\level1\level2\bc.txt' UNION ALL 
SELECT 'C:\test\level1\level2\level3\another.txt' 
) 
SELECT * FROM cte_TestData 
WHERE PATINDEX('%\%',REPLACE(Directory,@SearchDir,'')) = 0 --remove the @searchDir filter and what remains shouldnt containa backslash