How can I BCP queryout with filename from table? - sql

I'm extracting many BLOBs to files using BCP and wonder if there's a way to give each file a unique name using an ID field from the SQL table.
This works:
DECLARE #Command NVARCHAR(4000)
SET #Command = 'bcp "SELECT FileData FROM MyDB.dbo.Attachments
WHERE Hist_ID = ''00004F13''"
queryout "C:\Wha.pdf" -T -c -C RAW -S SERVERNAME -U SA -P pa$$word'
EXEC xp_cmdshell #Command
But to get the filename, I've tried:
DECLARE #FileName varchar(50),
#Command NVARCHAR(4000)
SET #FileName = Hist_ID+'wha.PDF'
SET #Command = 'bcp "SELECT FileData FROM MyDB.dbo.Attachments
WHERE Hist_ID = ''00004F13''" queryout'
SET #Command = #Command + 'C:\' + #FileName + '-T -c -C RAW
-S SERVERNAME -U SA -P pa$$word'
EXEC xp_cmdshell #Command
I get an error: Invalid column name 'Hist_ID'.
Is there some way to do this? Thanks for any help!

Try this. This is the only way I know have to execute one row at a time.
This code just prints the command. Uncomment the xp_cmdshell to make it actually run. You might want to start with a small sample first (by limiting the select)
DECLARE #Hist_ID VARCHAR(100)
DECLARE #Ext VARCHAR(10)
DECLARE #Command NVARCHAR(4000)
DECLARE cAttachments CURSOR FOR
SELECT DISTINCT Hist_ID,Extension
FROM MyDB.dbo.Attachments
ORDER BY Hist_ID
OPEN cAttachments
FETCH NEXT FROM cAttachments
INTO #Hist_ID, #Ext
WHILE ##FETCH_STATUS = 0
BEGIN
SET #Command = 'bcp "SELECT FileData FROM MyDB.dbo.Attachments
WHERE Hist_ID = ''' + #Hist_ID + '''"
queryout "C:\' + #Hist_ID + '.' + #Ext + '" -T -c -C RAW -S SERVERNAME -U SA -P pa$$word'
PRINT #Command
-- EXEC xp_cmdshell #Command
FETCH NEXT FROM cAttachments
INTO #Hist_ID, #Ext
END
CLOSE cAttachments
DEALLOCATE cAttachments

Related

Strange XML-Export behaviour

declare #cmd nvarchar(255)
SET #cmd = 'bcp "select * from Testdb.dbo.mytable WHERE nr LIKE ''%102065336''' + '" queryout C:\temp\sample.xml -c -t, -S' + ##servername + ' -T'
exec xp_cmdshell #cmd
That Code returns a correct .xml file with correct format, but when i use this #cmd so with "=" instead of "LIKE" the xml file looks broken(only cryptic chars in it) :
SET #cmd = 'bcp "select * from Testdb.dbo.mytable WHERE nr = ''102065336''' + '" queryout C:\temp\sample.xml -c -t, -S' + ##servername + ' -T'
So How is this possible? The queries return the same data if i execute the sql statement...
I cannot reproduce this. Check it out:
USE master;
GO
CREATE DATABASE tstDB;
GO
USE tstDB;
CREATE TABLE mytable(nr VARCHAR(100));
GO
INSERT INTO mytable VALUES('11'),('12'),('22');
GO
declare #cmd nvarchar(255);
SET #cmd = 'bcp "select * from tstDB.dbo.mytable WHERE nr LIKE ''%11'' FOR XML AUTO' + '" queryout C:\temp\sample1.xml -c -t, -S' + ##servername + ' -T';
exec xp_cmdshell #cmd;
SET #cmd = 'bcp "select * from tstDB.dbo.mytable WHERE nr = ''11'' FOR XML AUTO' + '" queryout C:\temp\sample2.xml -c -t, -S' + ##servername + ' -T';
exec xp_cmdshell #cmd;
GO
USE master;
GO
--careful with real data!
DROP DATABASE tstDB;
GO
Some ideas:
You speak about XML export, but the code you show does not create any XML? So maybe the issue is in an area we cannot see...
You declare your command with a size of 255. This is pretty small... Might be, that something is truncated
generall hint: Use -w instead of -c when you export XML. Find details here

bcp field terminator empty

https://technet.microsoft.com/en-us/library/aa196735(v=sql.80).aspx
I'm trying to create a file from bcp, the file was successfully created, but I want to make the field terminator -t empty. The closest way was with the null terminator, but it makes a space between fields.
This is my code.
select #cmd = 'bcp '+ #SP + ' queryout '+ #ruta+' -w -t\0 -S '+#Servidor+ ' -U'+#user +' -P'+ #password
exec master..xp_cmdshell #cmd
I've also tried to leave it without any symbol after t, but it puts more spaces.
select #cmd = 'bcp '+ #SP + ' queryout '+ #ruta+' -w -t -S '+#Servidor+ ' -U'+#user +' -P'+ #password
exec master..xp_cmdshell #cmd
use -t"" This basically gives you a fixed width export file especially when used to source fields defined as char()
for example:
bcp "select * from TEST.dbo.tExportTst" queryout FixedWidth.txt -c -t"" -T -S Svr\instance

SQL Server BCP works with table, but specify specific columns and it fails, why

In the EXAMPLE below, it works creating a file with all rows and columns in FTP_export_BAC table. But if I specify specific columns only to be exported, i.e. SELECT Col1, Col2 FROM Asce.... it fails. Any ideas?
DECLARE #Command varchar(512)
set #Command = 'bcp "SELECT * FROM myDatabase.dbo.[FTP_export_BAC]" queryout "C:\bcp\bcptest.txt" -T -c -S' + ##SERVERNAME
print #Command
EXEC xp_cmdshell #Command

Using bcp utility to export SQL queries to a text file

I debug a stored procedure (SQL Server 2005) and I need to find out some values in a datatable.
The procedure is run by an event of the application and I watch just the debugging output.
I do the following my stored procedure (SQL Server 2005), I took a system table (master.dbo.spt_values) as example:
set #logtext = 'select name, type from master.dbo.spt_values where number=6'
--set #logtext = 'master.dbo.spt_values'
SET #cmd = 'bcp ' + #logtext + ' out "c:\spt_values.dat" -U uId -P uPass -c'
EXEC master..XP_CMDSHELL #cmd
So, when I uncomment the second like everything works, a file apprears on the C:\ drive... but if I coment it back leaving only the first line, any output is generated.
How to fix this problem?
bcp out exports tables.
To export a query use queryout instead - you'll need to wrap your query in "double quotes"
set #logtext = '"select name, type from master.dbo.spt_values where number=6"'
--set #logtext = 'master.dbo.spt_values'
SET #cmd = 'bcp ' + #logtext + ' queryout "c:\spt_values.dat" -U uId -P uPass -c'
EXEC master..XP_CMDSHELL #cmd
http://msdn.microsoft.com/en-us/library/ms162802.aspx

Writing file to network drive in stored proc

I have a stored proc that can write a file to a network drive using BCP, by creating a temporary drive on the database server that maps to the shared drive on another server. It is working correctly, however, I am returning an error from the last EXEC command, which says There are open files and/or incomplete directory searches pending on the connection to U:. I am guessing that it is trying to execute the delete drive command before it has finished writing the file. If I run the statement after running the proc, it will successfully delete the drive. Here is the proc:
CREATE PROCEDURE dn_ExportFile
#ServerName varchar(50),
#ServerPath varchar(500),
#FileName varchar(100),
#Query varchar(max),
#UserName varchar(100),
#Password varchar(100),
#Drive varchar(1) = 'U'
AS
BEGIN
SET NOCOUNT ON;
DECLARE #cmd VARCHAR(8000)
--Set up virtual drive pointing to desired path
SET #cmd = 'NET USE ' + #Drive + ': ' + #ServerPath + ' /user:' + #ServerName + '\' + #UserName + ' ' + #Password
PRINT #cmd
EXEC xp_cmdshell #cmd
--Export data using BCP to virtual drive
SET #cmd = 'BCP "' + #Query + '" QUERYOUT "' + #Drive + ':\' + #FileName + '" -c -t -T'
PRINT #cmd
EXEC xp_cmdshell #cmd
--Delete virtual drive
SET #cmd = 'NET USE ' + #Drive + ': /delete'
PRINT #cmd
EXEC xp_cmdshell #cmd
END
Is there a way to successfully delete the temporary drive within the stored procedure?
I suspect it can't happen while the calling proc is still in scope. So you might try a wrapper stored procedure that does:
EXEC dbo.dn_ExportFile ...;
SET #cmd = 'NET USE ' + #Drive + ': /delete';
PRINT #cmd;
EXEC xp_cmdshell #cmd;
Otherwise I still think you're doing this in the wrong place. Have the program that calls this procedure call the command and dictate the path.