SQL Server – Read all files in directory and store in Table

Recently I was in need to analyze Salesforce debug log for one stubborn issue which was very hard to reproduce. Was able to download 1500+ debug logs on my system, however to analyze it, I decided to take help of SQL Server.

Very soon I came into challenge to read all files in a directory and store it back in SQL Server table.

Found very good article here which helped me to come up with below queries. If you need to read more in detail about below T-SQL and stored procedures please navigate to original article.

Table where we need to load files

CREATE TABLE [dbo].[DebugLogs](
	[Id] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
	[LogText] [nvarchar](max) NULL,
	[FileName] [nchar](500) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Stored procedure which reads all files in a directory

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[ListPathsXML]
@FileSpec VARCHAR(2000),
@order VARCHAR (80) = '/O-D',--sort by date time oldest first
@xmlFileList XML OUTPUT
 
AS
DECLARE @myfiles TABLE (MyID INT IDENTITY(1,1) PRIMARY KEY, FullPath VARCHAR(2000))
DECLARE @CommandLine VARCHAR(4000)
IF @order IS NOT NULL -- abort if the order is silly
   BEGIN
   SELECT @CommandLine =LEFT('dir "' + @FileSpec + '" /A-D /B /S '+@order,4000)
   INSERT INTO @MyFiles (FullPath)
       EXECUTE xp_cmdshell @CommandLine
   DELETE FROM @MyFiles WHERE fullpath IS NULL
       OR fullpath = 'File Not Found'
   END
SET @xmlFileList = (SELECT fullpath FROM @MyFiles
                         FOR
                          XML PATH('thefile'),
                              ROOT('thefiles'),
                              TYPE)

Stored procedure which reads content of file one at a time

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[spLoadTextFromAFile]
   @Filename VARCHAR(255),
   @Unicode INT = 0
AS 
   SET NOCOUNT ON
   DECLARE @MySpecialTempTable VARCHAR(255)
   DECLARE @Command NVARCHAR(4000)
   DECLARE @RESULT INT

--firstly we create a global temp table with a unique name
   SELECT   @MySpecialTempTable = '##temp' 
       + CONVERT(VARCHAR(12), CONVERT(INT, RAND() * 1000000))
--then we create it using dynamic SQL, 
   SELECT   @Command = 'create table [' 
       + @MySpecialTempTable + '] (MyLine '
       + CASE WHEN @unicode <>0 THEN 'N' ELSE '' END +'varchar(MAX))
 '
   EXECUTE sp_ExecuteSQL @command

   SELECT   @command = 'bulk insert [' 
       + @MySpecialTempTable + '] from' + ' ''' 
       + REPLACE(@Filename, '"', '') + '''' 
       + ' with (FIELDTERMINATOR=''|~||''' + ',ROWTERMINATOR = ''
'''        + CASE WHEN @unicode <>0 THEN ', DATAFILETYPE=''widechar'''ELSE '' END
       + ')'
-- import the data
   EXEC (@Command)
   EXECUTE ('Select * from ' + @MySpecialTempTable)
   EXECUTE ('Drop table ' + @MySpecialTempTable)

Final T-SQL query to read content of every file exists in directory and store in Table in SQL Server

DECLARE
       @ii INT,
       @iiMax INT,
       @File VARCHAR(2000)
DECLARE @files TABLE (MyID INT IDENTITY(1,1) PRIMARY KEY, [Path] VARCHAR(2000))
DECLARE @lines TABLE (MyID INT IDENTITY(1,1) PRIMARY KEY, [line] NVARCHAR(MAX), fName nVARCHAR(200))
 
DECLARE @FileList XML
EXECUTE ListPathsXML 'C:\ForceUtil\18_Jan_2017\DebugLogs\',
    DEFAULT , @XMLFileList = @FileList OUTPUT
 
INSERT INTO @files(path)
   SELECT   x.thefile.value('fullpath[1]', 'varchar(2000)') AS [path]
        FROM    @FileList.nodes('//thefiles/thefile') AS x ( thefile )
DELETE FROM @files WHERE REVERSE(path) LIKE 'golrorre%'
--don't look at the current errorlog!
SELECT @ii=1, @iiMax=MAX(MyID) FROM @Files
WHILE @ii<=@iiMax
   BEGIN
   SELECT @File= [path] FROM @files WHERE MyID=@ii
   INSERT INTO @lines(line)
       EXECUTE spLoadTextFromAFile @file, @Unicode=1

   INSERT INTO [dbo].[DebugLogs] (LogText, [FileName])
	SELECT  Line, @file FROM @lines
   
   --Empty temp table
   Delete FROM @lines

   SELECT @ii=@ii+1
   END

Posted

in

by

Tags:


Related Posts

Comments

3 responses to “SQL Server – Read all files in directory and store in Table”

  1. Erich Thalacker Avatar
    Erich Thalacker

    So very helpful! Exactly what I needed. Made file conversion so much easier!!!

  2. Mike Avatar
    Mike

    Hi. This is great however is throwing an error. An INSERT EXEC statement cannot be nested.

  3. Aidan Avatar
    Aidan

    Hi, I know this is an old post, but I’m very unexperienced at adapting queries for my own purpose, (I’m a first year apprentice with no previous experience in computing),but these procedures and T-SQL are exactly what I need for security auditing purposes. Specifically, using the Log files, I need to see the users who have accessed the database and when and where they have ran queries. Could I get some help as to where I can add my filepath, what I dont need to include and anything additional I need to add for my own requirements?

    Anything will be much appreciated.

    Thanks,
    Aidan

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from Jitendra Zaa

Subscribe now to keep reading and get access to the full archive.

Continue Reading