使用查询或存储过程将文本文件导入 SQL 服务器 table

Import text file into SQL server table using query or stored procedure

我想每天将文件夹中的文本文件导入 sql 服务器 table。我可以使用批量插入来做到这一点,但每日文本文件名不同,然后我必须更改脚本(仅文件名)。一旦我们在文件夹中收到文件并且 sp 可以动态读取文件名,有什么方法可以导出文件。

这种任务最好用SSIS来完成。但有时 SSIS 需要开发人员额外的依赖项。所以他们尝试使用 SQL 服务器来做到这一点。

因此您可以使用以下 SETPS 来完成此操作。它会从特定位置动态读取您的文本文件,并在读取后移动到另一个位置。

假设您有以下数据库和table。

CREATE DATABASE [Codefirst]
GO

USE [Codefirst]
GO

CREATE TABLE [dbo].[tbl_NewVendorData](
    [AccountNumber] [nvarchar](15) NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [ModificationDate] [datetime] NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [AccountNumber] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

并且您在需要插入到 table 的文本文件中有以下文本数据。阅读后您还需要将文件移动到另一个位置。 只需将以下数据复制并粘贴到您的文本文件中即可。

AC001 ,Raju Ahmed, 1989-11-18 00:00:00.000;
AC002 ,Robin Hossain, 1991-12-08 00:00:00.000;
AC003 ,Raju Ahmed 2, 1989-11-18 00:00:00.000;
AC004 ,Raju Ahmed 3, 1989-11-10 00:00:00.000;
AC005 ,Raju Ahmed 4, 1989-11-12 00:00:00.000;
AC006 ,Raju Ahmed 5, 1989-11-19 00:00:00.000;
AC007 ,Raju Ahmed 6, 1989-11-02 00:00:00.000;
AC008 ,Raju Ahmed 7, 1989-11-10 00:00:00.000;
AC009 ,Raju Ahmed 8, 1989-05-18 00:00:00.000;
AC010 ,Raju Ahmed 9, 1989-10-13 00:00:00.000;
AC011 ,Raju Ahmed 10, 1989-01-16 00:00:00.000;
AC012 ,Raju Ahmed 11, 1989-01-14 00:00:00.000;

SETP:1创建以下SP。假设你的@oldDir='C:\Data' 和 @newDir='C:\Data2'。 @oldDir 表示将从这里读取您的文本文件 & @newDir 表示读取后文件将移动到哪里。

CREATE PROC uspReadTextFileAndMove
(
    @oldDir VARCHAR(1000)='C:\Data',
    @newDir VARCHAR(1000)='C:\Data2'
)
AS
BEGIN
DECLARE @command VARCHAR(1000);
DECLARE @insertCommand VARCHAR(1000);
DECLARE @cmdFileMove VARCHAR(1000);
DECLARE @files TABLE ([Id] INT IDENTITY, [FileName] VARCHAR(1000));
DECLARE @FileToRead VARCHAR(1000)

SET @command = 'dir /b ' + @oldDir;
INSERT INTO @files EXECUTE xp_cmdshell @command;

DECLARE fileReadCursor CURSOR FOR

     SELECT [FileName] FROM @files

OPEN fileReadCursor;
FETCH fileReadCursor INTO @FileToRead;
WHILE (@@FETCH_STATUS = 0) 
BEGIN
    
        SET @insertCommand= 'BULK INSERT [dbo].[tbl_NewVendorData] FROM ''' +@oldDir+'\'+ @FileToRead + ''' WITH  ( FIELDTERMINATOR='','', ROWTERMINATOR='';\n'');' 
        EXECUTE(@insertCommand);
        
        SET @cmdFileMove= 'MOVE ' + @oldDir + '\' + @FileToRead  +' '+ @newDir +'\'+@FileToRead
        EXEC master..xp_cmdshell @cmdFileMove
    
    --PRINT @insertCommand;
    --PRINT @FileToRead;
    --PRINT @cmdFileMove;
    
    FETCH fileReadCursor INTO @FileToRead;
END;
CLOSE fileReadCursor;
DEALLOCATE fileReadCursor;

END

STEP:2 创建一个 SQL 服务器 Job Schedular 以每天或每小时或任何你想要的方式执行 STEP: 1。

根据您的需要按照以下脚本中的注释行和 运行 脚本进行更改以创建作业调度程序,该程序将 运行 每 1 分钟后一次(您可以更改它每小时、每天等)&它将执行我们的 SP。

USE tempdb
GO
IF OBJECT_ID('##tempJobTableConfig', 'U') IS NOT NULL 
BEGIN
    DROP TABLE ##tempJobTableConfig; 
        
END

DECLARE @DatabaseName VARCHAR(200)='Codefirst'  --Change Here: Change Your Database name.
DECLARE @TrialDays INT = 0 --Change Here: Change your trial days number from @TrialDays variable.
DECLARE @freq_subday_type_Variable INT= 4 --if you want it as minute change it value as 4,If value is 8 then it will be hour, 
DECLARE @freq_subday_interval_Variable INT=1 --Change here as: If your @freq_subday_type=8 then 12 will be hour, @freq_subday_type=4 then 12 will be minutes, 

SELECT  @DatabaseName AS DatabaseName 
       ,DATEADD(DAY,@TrialDays,GETDATE()) AS ExpairationDate
       ,ISNULL(@freq_subday_type_Variable,4) AS freq_subday_type_Variable
       ,ISNULL(@freq_subday_interval_Variable,15) AS freq_subday_interval_Variable
INTO ##tempJobTableConfig



USE [msdb]
GO

DECLARE @jobId2 BINARY(16)
SELECT @jobId2 = job_id FROM msdb.dbo.sysjobs WHERE (name = N'TextFileReadAndMoveJob')
IF (@jobId2 IS NOT NULL)
BEGIN
    EXEC msdb.dbo.sp_delete_job @jobId2
END

BEGIN TRANSACTION

DECLARE @DateInIntData INT
DECLARE @jobId BINARY(16)
DECLARE @ReturnCode INT
DECLARE @User NVARCHAR(500)=(SELECT SUSER_NAME())

/*===========================================================================================================================================================================
        Value of @DateInIntData will be like this =20210224, where 2021=year,02=month & 24=day & it'll dynamically add current date as your schedular start date.
=============================================================================================================================================================================*/

SELECT @ReturnCode = 0 
SET @DateInIntData=CAST(
                    (CAST((SELECT DATEPART(YEAR,GETDATE())) AS VARCHAR(4))
                   +RIGHT('00'+CAST((SELECT DATEPART(MONTH,GETDATE())) AS VARCHAR(4)),2)
                   +RIGHT('00'+CAST((SELECT DATEPART(DAY,GETDATE())) AS VARCHAR(4)),2))
                   AS INT)

IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
    EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
END

EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'TextFileReadAndMoveJob', 
        @enabled=1, 
        @notify_level_eventlog=0, 
        @notify_level_email=0, 
        @notify_level_netsend=0, 
        @notify_level_page=0, 
        @delete_level=0, 
        @description=N'No description available.', 
        @category_name=N'[Uncategorized (Local)]', 
        @owner_login_name=@User, @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

DECLARE @databaseValue VARCHAR(400)=(SELECT DatabaseName FROM tempdb..##tempJobTableConfig)
DECLARE @commandValue NVARCHAR(500)=N'USE '+@databaseValue+' 
GO
EXEC uspReadTextFileAndMove;
'
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Execution', 
        @step_id=1, 
        @cmdexec_success_code=0, 
        @on_success_action=1, 
        @on_success_step_id=0, 
        @on_fail_action=2, 
        @on_fail_step_id=0, 
        @retry_attempts=0, 
        @retry_interval=0, 
        @os_run_priority=0, @subsystem=N'TSQL', 
        @command=@commandValue, 
        @database_name=N'master', 
        @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
DECLARE @schedule_uid2 NVARCHAR(500)=(SELECT NEWID())

DECLARE @freq_subday_type_Value INT=(SELECT ISNULL(freq_subday_type_Variable,4) FROM tempdb..##tempJobTableConfig)
DECLARE @freq_subday_interval_Value INT=(SELECT ISNULL(freq_subday_interval_Variable,4) FROM tempdb..##tempJobTableConfig)
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'TextFileReadAndMoveJobSchedule', 
        @enabled=1, 
        @freq_type=4, 
        @freq_interval=1, 
        @freq_subday_type=@freq_subday_type_Value,
        @freq_subday_interval=@freq_subday_interval_Value,
        @freq_relative_interval=0, 
        @freq_recurrence_factor=0, 
        @active_start_date=@DateInIntData, 
        @active_end_date=99991231, 
        @active_start_time=0, 
        @active_end_time=235959, 
        @schedule_uid=@schedule_uid2
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:
GO

注意:您可能需要启用'xp_cmdshell的权限。为此,请执行以下代码。

-- this turns on advanced options and is needed to configure xp_cmdshell
EXEC sp_configure 'show advanced options', '1'
RECONFIGURE
-- this disables xp_cmdshell
EXEC sp_configure 'xp_cmdshell', '0' 
RECONFIGURE