I have a .NET App from which I am calling 2 stored procedures. One of these stored procedures is a Bulk Insert, to which I will pass in the appropriate filename, table name, and delimiter from the .NET app. After some research, I found out that I would need to use dynamic SQL to allow for variable filenames in a BULK INSERT
.
The code I have now reads:
CREATE PROCEDURE transfer_data
@file_path VARCHAR, @t_name VARCHAR, @delimeter VARCHAR
AS
BULK INSERT @t_name
FROM @file_path
WITH (
FIELDTERMINATOR = @delimeter,
ROWTERMINATOR = '\n'
);
How would I refactor this? Other examples that I've seen (BULK INSERT with variable file name) are still setting the variable in the query, however I will be passing the parameters from my .NET App.
1 Answer 1
You need to safely inject the values. You can't replace literals with variables. Due to the File path having the chance of being longer than 128 characters, i use REPLACE
rather than QUOTENAME
. I also assume that the delimiter is only 1 character in length:
CREATE PROCEDURE dbo.transfer_data @file_path nvarchar(255), @s_name sysname = N'dbo', @t_name sysname, @delimiter nchar(1) AS
BEGIN
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET @SQL = N'BULK INSERT ' + QUOTENAME(@s_name) + N'.' + QUOTENAME(@t_name) + @CRLF +
N'FROM N''' + REPLACE(@file_path,'''','''''') + N'''' + @CRLF +
N'WITH (FIELDTERMINATOR = N' + QUOTENAME(@delimiter,'''') + N',' + @CRLF +
N' ROWTERMINATOR = ''\n'');'
--PRINT @SQL;
EXEC sys.sp_executesql @SQL;
END;
VARCHAR(n)
without a value for(n)
. When n isn't specified in a data definition or variable declaration statement, the default length is 1. If n isn't specified when using the CAST and CONVERT functions, the default length is 30. So all of your parameters are currently limited to one byte.