从网络共享文件夹导入时,如何绕过SQL BULK INSERT语句访问/双跳问题?

问题描述 投票:0回答:1

在我的环境中,我们不允许为SQL服务帐户授予对网络共享文件夹的访问权限。

因此,我创建了一个包含所有BULK INSERT参数的相同存储过程,并将使用xp_cmdshell代理帐户,该帐户可以配置为任何需要的用户。

因此,该过程接受了另外2个参数,首先将文件复制到服务器上的本地%TEMP%文件夹中,然后在文件上应用批量插入,然后将其删除。

我希望这会有所帮助,因为别无选择。

后四个参数使您可以使用普通的BULK INSERT或在服务器%TEMP%文件夹中缓存文件的参数,以及其他一些设置。

CREATE PROCEDURE [dbo].[up_BULK_INSERT] (
    -- main params
    @DESTINATION_TABLE NVARCHAR(250),
    @SOURCE_DATAFILE NVARCHAR(250),
    -- bulk insert params
    @BATCHSIZE NVARCHAR(100) = NULL,
    @CHECK_CONSTRAINTS NVARCHAR(100) = NULL,
    @CODEPAGE NVARCHAR(100) = NULL,
    @DATAFILETYPE NVARCHAR(100) = NULL,
    @DATA_SOURCE NVARCHAR(100) = NULL,
    @ERRORFILE NVARCHAR(100) = NULL,
    @ERRORFILE_DATA_SOURCE NVARCHAR(100) = NULL,
    @FIRSTROW NVARCHAR(100) = NULL,
    @FIRE_TRIGGERS NVARCHAR(100) = NULL,
    @FORMATFILE_DATASOURCE NVARCHAR(100) = NULL,
    @KEEPIDENTITY NVARCHAR(100) = NULL,
    @KEEPNULLS NVARCHAR(100) = NULL,
    @KILOBYTES_PER_BATCH NVARCHAR(100) = NULL,
    @LASTROW NVARCHAR(100) = NULL,
    @MAXERRORS NVARCHAR(100) = NULL,
    @ORDER NVARCHAR(100) = NULL,
    @ROWS_PER_BATCH NVARCHAR(100) = NULL,
    @ROWTERMINATOR NVARCHAR(100) = NULL,
    @TABLOCK NVARCHAR(100) = NULL,
    -- bulk insert - input file format options
    @FORMAT NVARCHAR(100) = NULL,
    @FIELDQUOTE NVARCHAR(100) = NULL,
    @FORMATFILE NVARCHAR(100) = NULL,
    @FIELDTERMINATOR NVARCHAR(100) = NULL,
    @MAKE_TEMP_LOCALCOPY BIT = 1,
    @CLEANUP_TEMP BIT = 1,
    @TRUNCATE_FIRST BIT = 0,
    @DEBUG BIT = 0
    ) AS
BEGIN

DECLARE @strSQL_Query NVARCHAR(MAX)
DECLARE @importFile NVARCHAR(MAX) = @SOURCE_DATAFILE

IF @DESTINATION_TABLE = '' OR @SOURCE_DATAFILE = ''
BEGIN
    RAISERROR (15600,-1,-1, 'up_BULK_INSERT');  
END

IF @MAKE_TEMP_LOCALCOPY = 1
BEGIN

    DECLARE @tempFolder NVARCHAR(MAX) = '\AppData\Local\Temp\'
    DECLARE @result TABLE (Line NVARCHAR(512))

    IF @DEBUG = 1 PRINT 'Getting profile fullpath: EXEC xp_cmdshell ''ECHO %USERPROFILE%'''
    INSERT INTO @result EXEC xp_cmdshell 'ECHO %USERPROFILE%'

    SET @tempFolder = (select top 1 * from @result where Line is not null) + @tempFolder

    DECLARE @strCMDSHELL NVARCHAR(4000) = N'COPY /Y "' + @SOURCE_DATAFILE + '" "'+@tempFolder+'"'

    IF @DEBUG = 1 PRINT 'Copying the file to local profile temp folder: EXEC xp_cmdshell ''' + @strCMDSHELL + ''''
    EXEC xp_cmdshell @strCMDSHELL,no_output

    SET @importFile = @tempFolder + RIGHT(@SOURCE_DATAFILE, CHARINDEX('\', REVERSE(@SOURCE_DATAFILE)) -1)
END

SET @strSQL_Query = 'BULK INSERT [' + @DESTINATION_TABLE + '] FROM ''' + @importFile  + ''''

IF  @BATCHSIZE IS NOT NULL OR 
    @CHECK_CONSTRAINTS IS NOT NULL OR 
    @CODEPAGE IS NOT NULL OR 
    @DATAFILETYPE IS NOT NULL OR 
    @DATA_SOURCE IS NOT NULL OR 
    @ERRORFILE IS NOT NULL OR 
    @ERRORFILE_DATA_SOURCE IS NOT NULL OR 
    @FIRSTROW IS NOT NULL OR 
    @FIRE_TRIGGERS IS NOT NULL OR 
    @FORMATFILE_DATASOURCE IS NOT NULL OR 
    @KEEPIDENTITY IS NOT NULL OR 
    @KEEPNULLS IS NOT NULL OR 
    @KILOBYTES_PER_BATCH IS NOT NULL OR 
    @LASTROW IS NOT NULL OR 
    @MAXERRORS IS NOT NULL OR 
    @ORDER IS NOT NULL OR 
    @ROWS_PER_BATCH IS NOT NULL OR 
    @ROWTERMINATOR IS NOT NULL OR 
    @TABLOCK IS NOT NULL OR 
    -- bulk insert - input file format options
    @FORMAT IS NOT NULL OR 
    @FIELDQUOTE IS NOT NULL OR 
    @FORMATFILE IS NOT NULL OR 
    @FIELDTERMINATOR IS NOT NULL
BEGIN
    --start Bulk insert conditions definition
    SET @strSQL_Query = @strSQL_Query + ' WITH ( '
    -- bulk insert main parameters
    IF @BATCHSIZE IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'BATCHSIZE = ' + @BATCHSIZE + ','
    IF @CHECK_CONSTRAINTS IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'CHECK_CONSTRAINTS,'
    IF @CODEPAGE IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'CODEPAGE = ''' + @CODEPAGE + ''','
    IF @DATAFILETYPE IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'DATAFILETYPE = ''' + @DATAFILETYPE + ''','
    IF @DATA_SOURCE IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'DATA_SOURCE = ''' + @DATA_SOURCE + ''','
    IF @ERRORFILE IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'ERRORFILE = ''' + @ERRORFILE + ''','
    IF @ERRORFILE_DATA_SOURCE IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'ERRORFILE_DATA_SOURCE = ''' + @ERRORFILE_DATA_SOURCE + ''','
    IF @FIRSTROW IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'FIRSTROW = ' + @FIRSTROW + ','
    IF @FIRE_TRIGGERS IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'FIRE_TRIGGERS,'
    IF @FORMATFILE_DATASOURCE IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'FORMATFILE_DATASOURCE = ''' + @FORMATFILE_DATASOURCE + ''','
    IF @KEEPIDENTITY IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'KEEPIDENTITY,'
    IF @KEEPNULLS IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'KEEPNULLS,'
    IF @KILOBYTES_PER_BATCH IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'KILOBYTES_PER_BATCH = ' + @KILOBYTES_PER_BATCH + ','
    IF @LASTROW IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'LASTROW = ' + @LASTROW + ','
    IF @MAXERRORS IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'MAXERRORS = ' + @MAXERRORS + ','
    IF @ORDER IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'ORDER ( ' + @ORDER + ' ),'
    IF @ROWS_PER_BATCH IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'ROWS_PER_BATCH = ' + @ROWS_PER_BATCH + ','
    IF @TABLOCK IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'TABLOCK,'
    -- bulk insert - input file format options
    IF @FORMAT IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'FORMAT = ''' + @FORMAT + ''','
    IF @FIELDQUOTE IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'FIELDQUOTE = ''' + @FIELDQUOTE + ''','
    IF @FORMATFILE IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'FORMATFILE = ''' + @FORMATFILE + ''','
    IF @FIELDTERMINATOR IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'FIELDTERMINATOR = ''' + @FIELDTERMINATOR + ''','
    IF @ROWTERMINATOR IS NOT NULL SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + 'ROWTERMINATOR = ''' + @ROWTERMINATOR + ''','
    -- Correct SQL query final character
    IF RIGHT(@strSQL_Query,1) = ',' SET @strSQL_Query = LEFT(@strSQL_Query,LEN(@strSQL_Query)-1)
    -- SQL close syntax
    SET @strSQL_Query = @strSQL_Query + CHAR(13) + CHAR(10) + ')'
END

--TRUNCATE FIRST if specified
IF @TRUNCATE_FIRST = 1
BEGIN
    DECLARE @strTRUNCSQL NVARCHAR(MAX) = 'TRUNCATE TABLE ' + @DESTINATION_TABLE
    IF @DEBUG = 1 PRINT 'Truncating table specified: ' + @strTRUNCSQL
    exec sp_executesql @strTRUNCSQL
END

IF @DEBUG = 1 PRINT 'Bulk Insert operation: ' + @strSQL_Query
EXEC sp_executesql @strSQL_Query

IF @CLEANUP_TEMP = 1
BEGIN
    SET @strCMDSHELL = 'DEL /F /Q "' + @importFile + '"'
    IF @DEBUG = 1 PRINT 'Clean-up after Bulk Import: EXEC xp_cmdshell ''' + @strCMDSHELL + ''''
    EXEC xp_cmdshell @strCMDSHELL, no_output
END

END
sql sql-server bulkinsert
1个回答
0
投票

将BULK INSERT放入在同一服务器上运行并执行该命令的Sql Agent作业中。

© www.soinside.com 2019 - 2024. All rights reserved.