BCP - Export CSV with header - sql-server

I have run the following query to export my Ms SQL table as CSV. It working good. Now I want to add the field name as the first row. How is it possible?
declare #sql varchar(8000)
select #sql = 'bcp "select * from test_table" queryout C:\Test_SP\Tom.csv -c -t, -T -S' + ##servername
exec master..xp_cmdshell #sql
I know that I can specify the names #Red Devil answered. But the table is dynamic, Its fields are not fixed, It will change. I am trying to find a method to fetch the field names from the table definition and prepend it into the result CSV

Try this:
declare #sql varchar(8000)
select #sql = 'bcp "select 'col1', 'col2',... union all select * from test_table" queryout C:\Test_SP\Tom.csv -c -t, -T -S' + ##servername
exec master..xp_cmdshell #sql

Related

T-SQL procedure - BCP - export CSV table with header

I have run the following query to export my SQL Server table as CSV. It is working fine. But now I want to add the column names as the first row. How is that possible?
DECLARE #archivoOUT varchar(800)
DECLARE #sql nvarchar(1000)
SET #archivoOUT = CONCAT('D:\archivosolicitudrestcate', FORMAT (GETDATE(), 'yyyyMMdd'),'.csv')
SET #sql = 'bcp "[dbo].[TEMP_res]" out '+#archivoOUT+' -S '+##SERVERNAME+' -d CentroMedico -c -T -w'
EXEC master..xp_cmdshell #sql
To add column names to your BCP out, you can change your syntax slightly.
You will need to select the columns that you want from the table instead of BCP'ing the entire table.
Currently you have,
'bcp "[dbo].[TEMP_res]" out '...
Modify the query syntax slightly. To select specific columns from the table try,
'bcp "select 'column1', 'column2'
union all
SELECT column1, column2 FROM [testdb].[dbo].[TEMP_res]" out' ...
More details at Microsoft's learning site, but here is an even better answer directly from StackOverflow.
The method I always relied is the one referenced in the link #GuiLeFlea mentioned where you concatenate column and detail rows separately.
DECLARE #archivoOUT varchar(800)
DECLARE #archivoOUTdetails varchar(800)
DECLARE #sql nvarchar(1000)
SET #archivoOUT = CONCAT('D:\archivosolicitudrestcate', FORMAT (GETDATE(), 'yyyyMMdd'),'.csv')
SET #archivoOUTdetails = CONCAT('D:\archivosolicitudrestcate', FORMAT (GETDATE(), 'yyyyMMdd'),'_details.csv')
SET #sql = 'bcp "select ''column1'', ''column2'', ''column3''" queryout '+#archivoOUT+' -S '+##SERVERNAME+' -d CentroMedico -c -T -w'
EXEC master..xp_cmdshell #sql
SET #sql = 'bcp "[dbo].[TEMP_res]" out '+#archivoOUTdetails+' -S '+##SERVERNAME+' -d CentroMedico -c -T -w'
EXEC master..xp_cmdshell #sql
SET #sql = 'cmd /U /C type ' + #archivoOUTdetails + ' >> ' + #archivoOUT
EXEC master..xp_cmdshell #sql
The advantage is this will always order by correctly, regardless of execution plan.
So another way you can achieve your goal, guarantee the rows are ordered, and do it in a simple manner that only requires 1 call to xp_cmdshell is by adding a dummy sort ID column to the UNION ALL query, and then wrapping it in a CTE or subquery so you can order on it without having to select it:
DECLARE #archivoOUT varchar(800)
DECLARE #sql nvarchar(1000)
SET #archivoOUT = CONCAT('D:\archivosolicitudrestcate', FORMAT (GETDATE(), 'yyyyMMdd'),'.csv')
SET #sql =
CONCAT
(
N'bcp ',
N'"SELECT Column1, Column2, Column3 ',
N'FROM ',
N'( ',
N' SELECT ''Column1Name'' AS Column1, ''Column2Name'' AS Column2, ''Column3Name'' AS Column3, 1 AS SortId',
N' UNION ALL ',
N' SELECT Column1, Column2, Column3, 2 AS SortId ',
N' FROM dbo.TEMP_res ',
N') AS Results ',
N'ORDER BY SortId" ',
N'out ', #archivoOUT, ' -S ', ##SERVERNAME, ' -d CentroMedico -c -T -w'
)
EXEC master..xp_cmdshell #sql
This is kind of the best of both worlds and then some, from the other answers.
Note I'm using CONCAT() so I can format the query in a human readable way, that's just my preference, it's not required. You can just stuff the whole code in a single line of code if you prefer, like your original BCP query string.
I just create a view that does this:
SELECT 'Field_1, Field_2, Field_3'
union all
SELECT Field_1,Field_2,Field_3
FROM Table
Edit: A UNION ALL does guarantee the datasets will be in order. The rows in each dataset may not be, but the order of the outputted datasets will be in the order they are executed. Just look at the Execution Plan, it always ends with "Concatenation - Append multiple input tables to form the output table"

Dynamic file creation with BCP Utility

I'm using BCP Utility to copy records out of table before deleting the records.
The function is working just fine, however, I need to copy the records to a new file for the every time I delete, instead of override the same file (as it is now).
It could be creating a new file with timestamp as prefix or something similar.
Any ideas?
My code
Declare #cmd varchar(1000) = 'bcp "select * from ##DeletedRecords" queryout
"C:\Delete\DeletedRecord.txt" -t, -c -T'
print #cmd
EXEC master..XP_CMDSHELL #cmd
just change the filename in the BCP command accordingly by appending date & time to the filename
example :
Declare #cmd varchar(1000);
select #cmd = 'bcp "select * from ##DeletedRecords" queryout '
+ '"C:\Delete\DeletedRecord'
+ convert(varchar(10), getdate(), 112) -- YYYYMMDD
+ replace(convert(varchar(10), getdate(), 108), ':', '') -- HHMMSS
+ '.txt" -t, -c -T'
print #cmd
EXEC master..XP_CMDSHELL #cmd

SQL Server User Defined Table Types and BCP Export

I can't seem to get this script to work. I'm getting the following error:
Msg 137, Level 16, State 1, Line 14
Must declare the scalar variable "#TVP_GLICU".
Can anyone tell me what am I missing?
Declare #TVP_GLICU TVP_GLICU
DECLARE #cmd varchar(500)
Declare #TimeStamp as nvarchar(100) = Replace((CONVERT(varchar(25), getdate(), 121)),':','')
--Insert Batch numbers in user defined table types
Insert Into #TVP_GLICU (ID)
Values ('563704')
Insert Into #TVP_GLICU (ID)
Values ('498721')
--select *
--From #TVP_GLICU
SET #cmd = 'BCP "EXECUTE [F0902].[D365O].[Get-F0911NewRecords]'+#TVP_GLICU+'" QUERYOUT "D:\D365O\DataSource\F0911\'+#TimeStamp+'.csv" -c -t\^, -T -S' + ##SERVERNAME + ''
EXECUTE MASTER..xp_cmdshell #cmd
You can't refer to a table variable from BCP that was created outside the scope of the query parameter. When BCP is executed, it creates a new session and the scope of table variables is limited to the session that created the table variable.
Problem is that you are concatenating string and are trying to append a table-valued type:
SET #cmd = 'BCP "EXECUTE [F0902].[D365O].[Get-F0911NewRecords]'+#TVP_GLICU+'" QUERYOUT "D:\D365O\DataSource\F0911\'+#TimeStamp+'.csv" -c -t\^, -T -S' + ##SERVERNAME + ''
Can you instead create a Staging table in the database and use its name in BCP query?

Why do I get an error in bcp query out where clause?

I'm new to SQL Server and write this query for save select result into csv file:
declare #Cycle_ID as int
set #Cycle_ID = 0
EXECUTE master.dbo.xp_cmdshell 'bcp "select [Telno],[Cycle],[Price] FROM [ClubEatc].[dbo].[CycleAnalysisTable] where cast([Price] as float)>'+ #Cycle_ID +' " queryout d:\download\behi.csv -t"|" -c -S VM_TAZMINDARAMA -U behzad -P beh1368421'
In where clause I write simple variable, but I get this error:
Incorrect syntax near '+'.
Please don't decrease my question! I'm new! Thanks
SQL Server doesn't recognize expressions in exec statements. So, try setting up the query first in a variable and using that:
declare #Cycle_ID as int;
set #Cycle_ID = 0;
declare #sql nvarchar(max);
set #sql = '
bcp "select [Telno],[Cycle],[Price] FROM [ClubEatc].[dbo].[CycleAnalysisTable] where cast([Price] as float)>'+ cast(#Cycle_ID as varchar(255)) +' ";
EXECUTE master.dbo.xp_cmdshell #sql queryout d:\download\behi.csv -t"|" -c -S VM_TAZMINDARAMA -U behzad -P beh1368421';
It seems curious to me that you are comparing a column called Price to a variable called #Cycle_ID, but that has nothing to do with the syntax issue.

Stored Procedure results into a file only if not null

I am trying to execute Stored Procedure on a regular basis using a SQL Job and store the results of this into a .txt file in a folder location.
I have used the BCP command which is like:
DECLARE #command VARCHAR(1000)
SET #command = 'BCP "Exec [DatabaseName].[dbo].[StoredProcedureName] " queryout "D:\In\ErrorDetails'+ '.txt" -c -T -t -k'
EXEC xp_cmdshell #command
I need this to execute only if results of SP are not null.
You can use temp table to store data generated by SP, if there are any rows - write it to file
USE tempdb
IF OBJECT_ID(N'#MyTempTable') IS NOT NULL
BEGIN
DROP TABLE #MyTempTable
END
SELECT * INTO #MyTempTable
FROM OPENROWSET('SQLNCLI', 'Server=HOME\SQLEXPRESS;Trusted_Connection=yes;',
'EXEC Test.dbo.StoredProcedureName');
IF (SELECT COUNT(*) FROM #MyTempTable) > 0
BEGIN
DECLARE #command VARCHAR(1000)
SET #command = 'BCP "USE tempdb SELECT * FROM #MyTempTable " queryout "D:\In\ErrorDetails'+ '.txt" -c -T -t -k'
EXEC xp_cmdshell #command
END

Resources