How to cast variables in T-SQL for bulk insert?
Asked Answered
N

6

18

The following code gives an error (its part of a T-SQL stored procedure):

-- Bulk insert data from the .csv file into the staging table.
DECLARE @CSVfile nvarchar(255);
SET @CSVfile = N'T:\x.csv';
BULK INSERT [dbo].[TStagingTable]
-- FROM N'T:\x.csv' -- This line works
FROM @CSVfile -- This line will not work
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n',
FIRSTROW = 2    
)

The error is:

Incorrect syntax near the keyword 'with'. 

If I replace:

FROM @CSVfile

with:

FROM 'T:\x.csv'

... then it works nicely.

Naze answered 16/2, 2011 at 16:22 Comment(2)
I find it astonishing that the BULK INSERT syntax of SQL Server fails to accept an expression that evaluates to an SQL string following the keyword FROM. How random.Brutal
And that's why PostgreSQL is so nice: weirdly obtuse corner case like this just get fixed, not left there to fester.Naze
L
17

As I know only literal string is required in the from. In that case you have to write a dynamic query to use bulk insert

declare @q nvarchar(MAX);
set @q=
    'BULK INSERT [TStagingTable]
    FROM '+char(39)+@CSVfile+char(39)+'
    WITH
    (
    FIELDTERMINATOR = '','',
    ROWTERMINATOR = ''\n'',
    FIRSTROW = 1  
    )'
exec(@q)
Lionfish answered 16/2, 2011 at 16:37 Comment(3)
Brilliant, this worked with just a few modifications. It didn't seem to work if I used any double quotes in the query at all, your solution is pretty much perfect.Naze
What about SQL Injection?Fizgig
All of the answers seem to ignore SQL Injection. Is there no way to parameterise the dynamic SQL for bulk insert?Construe
T
4

Have you tried with dynamic SQL?

SET @SQL = "BULK INSERT TmpStList FROM '"+@PathFileName+"' WITH (FIELDTERMINATOR = '"",""') "

and then

EXEC(@SQL)

Ref.: http://www.sqlteam.com/article/using-bulk-insert-to-load-a-text-file

Toxinantitoxin answered 16/2, 2011 at 16:25 Comment(2)
What about SQL Injection?Fizgig
Exactly. Surely there is a way to do this using sp_ExecuteSQL with parameters?Construe
C
2

you have to engage in string building & then calling EXEC() or sp_executesql BOL has an example:

DECLARE @bulk_cmd varchar(1000)
SET @bulk_cmd = 'BULK INSERT AdventureWorks2008R2.Sales.SalesOrderDetail
FROM ''<drive>:\<path>\<filename>'' 
WITH (ROWTERMINATOR = '''+CHAR(10)+''')'
EXEC(@bulk_cmd)
Clarence answered 16/2, 2011 at 16:30 Comment(1)
What about SQL Injection?Fizgig
E
1

A string literal is required.

http://msdn.microsoft.com/en-us/library/ms188365.aspx

You could use dynamic sql to generate the string literal.

Edacity answered 16/2, 2011 at 16:27 Comment(0)
M
0

Most of the time the variable i'm looking for in a file name is the date, and this one works perfectly for bulk inserting files with date, for use such as in a daily job. Change as per your need, date format, table name, file path, file name and delimiters.

    DECLARE @DT VARCHAR (10)
    DECLARE @INSERT VARCHAR (1000)
    SET @DT = (CONVERT(VARCHAR(10),GETDATE()-1,120))
    SET @INSERT = 'BULK INSERT dbo.table FROM ''C:\FOLDER\FILE'+@DT+'.txt'''+' WITH  (FIRSTROW=2, FIELDTERMINATOR=''\t'', ROWTERMINATOR=''\n'')'
    EXEC (@INSERT);
Manometer answered 19/8, 2014 at 1:3 Comment(1)
What about SQL Injection?Fizgig
S
-1

Can you try FROM ' + @CSVfile + '

Shoshanashoshanna answered 16/2, 2011 at 16:25 Comment(1)
See "How to Answer" and Explaining entirely code-based answers". While this might be technically correct, it doesn't explain why it solves the problem or should be the selected answer. We should educate along with helping solve the problem.Tish

© 2022 - 2024 — McMap. All rights reserved.