I am currently going through the process of exporting a CSV file from an SQL Server DB for each unique key in a database that contains meter readings. I am doing this one at a time manually via Export data in SSMS.... It is making me want to die since I have 200 unique key values.
Here is my query:
SELECT DataTime, DataValue
FROM [i96X].[dbo].[PointValue]
WHERE PointID = 68352
The bulk of the query stays the same, the only value i change is the PointID. I need tab separated CSV's as output where the filename = the PointID.
Can someone help?
You can use xp_cmdshell and bcp to achieve what you want but it requires more privileges, in case you're thinking about running this in production.
You need to configure enable advanced options in order to enable xp_cmdshell and then enable xp_cmdshell
EXEC sp_configure 'show advanced options', 1 RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1 RECONFIGURE
Then we gather all PointIDs into a cursor so we can process individually
Declare curPointIDS Cursor For
Select Distinct PointID From [i96X].[dbo].[PointValue]
Open curPointIDS
Declare #pointId Int, #cmd Varchar(max)
Fetch Next From curPointIDS Into #pointId
While ##FETCH_STATUS = 0
Begin
Set #cmd = 'bcp "SELECT DataTime, DataValue FROM [i96X].[dbo].[PointValue] '
+ 'WHERE PointID = ' + LTRIM(#pointId) + '" queryout '
+ '"C:\Temp\Results_' + LTRIM(#pointId) + '.csv" -T -c -t,'
EXEC xp_cmdshell #cmd
End
Close curPointIDS
Deallocate curPointIDS
xp_cdshell: Runs commands in command prompt (https://msdn.microsoft.com/en-us/library/ms175046.aspx)
bcp: Sql Server's data extract utility https://msdn.microsoft.com/en-us/library/ms162802.aspx
Parameters:
-T: Use trusted connection
-c: Data type will be characters
-t: Specify delimiter, in this case it's comma (,)
You can use a loop and a temp table to accomplish this.
declare #i int = (select count(distinct PointID) from [i96X].[dbo].[PointValue])
select row_number() over(order by PointID) as rn, *
into #tmp --temp table
from [i96X].[dbo].[PointValue]
declare #id int
declare #sql varchar(4000)
while #i > 0
begin
set #id = (select PointID from #tmp where rn = #i)
SELECT DataTime, DataValue
FROM [i96X].[dbo].[PointValue]
WHERE PointID = #id;
select #sql = 'bcp "SELECT DataTime, DataValue FROM [i96X].[dbo].[PointValue] WHERE PointID = '+str(#id)+'" queryout "C:\Temp\'+str(#id)+'+'.csv'+'" -S servername -d databasename -U username -P password'
exec master..xp_cmdshell #sql
set #i = #i-1;
end
If you have a fix list of meters you can create a batch file and extract this information, on a regular basis, using the Task Scheduler.
Basically you should put on this batch file one row for each meter you want to extract and use sqlcmd to extract the historical records.
For example, let's say you want to extract the historical data for the pointIDs (1, 2, 3). You can create a batch file called "extract.bat" with the following lines:
sqlcmd -Q "select * from i96x.dbo.PointValue where Pointid=1" -s "\t" -o "C:\Results\1.csv"
sqlcmd -Q "select * from i96x.dbo.PointValue where Pointid=2" -s "\t" -o "C:\Results\2.csv"
sqlcmd -Q "select * from i96x.dbo.PointValue where Pointid=3" -s "\t" -o "C:\Results\3.csv"
You just need to run this batch file and get your files. This files will use tab as a column separator. If you want to use comma as column separator just change -s , on each row.
You can use excel to make easier to generate this batch file.
Another head up, with that query you will get ALL the values for each pointid. If you are working with meter probably you will be interested in extract only the last month. To do that you will need to adjust the query.
Related
I have this stored procedure; I am printing the value of the variable in SSMS.
Instead, I want to store this result in a .txt file.
NOTE: I don't want to do it using SSMS options of right clicking on the result and then saving the result as. I want it to be done using any SQL code/built-in function directly in the stored procedure itself.
CREATE PROCEDURE [dbo].[usp_printresulttofile]
AS
BEGIN
DECLARE #var NVARCHAR(MAX) = ''
SET #var = 'print this data in txt file'
PRINT 'Data is : ' + #var
/* SQL query here to store result of Print statement in text file */
END
EXEC [dbo].[usp_printresulttofile]
Sharing the updated working SP here so that it might be useful to someone with a similar requirement Thanks #David Browne - Microsoft
ALTER PROCEDURE [dbo].[usp_printresulttofile]
AS
BEGIN
DECLARE #fileTimeStamp varchar(200) = convert(varchar,getDate(), 112 )+'_'+ Replace(convert(varchar,getDate(), 114 ),':','') -- select convert(varchar, getdate(), 121)
DECLARE #fileExtension varchar(5) = 'txt'
DECLARE #var NVARCHAR(MAX) = ''
SET #var = 'print this data in txt file'
PRINT 'Data is : ' + #var
declare #fn varchar(500) = 'c:/log/SP_output_'+#fileTimeStamp+'.'+#fileExtension;
declare #cmd varchar(8000) = concat('echo ', #var, ' > "', #fn, '"');
print #cmd
exec xp_cmdshell #cmd, no_output
set #cmd = concat('type "', #fn, '"');
print #cmd
exec xp_cmdshell #cmd;
END
GO
As the comments and other answers indicate, this is not usually a good idea. But here's how to do it anyway, assuming you're a sysadmin on SQL Server. :)
-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1;
GO
-- To update the currently configured value for advanced options.
RECONFIGURE;
GO
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1;
GO
-- To update the currently configured value for this feature.
RECONFIGURE;
GO
CREATE OR ALTER PROCEDURE [dbo].[usp_printresulttofile]
AS
BEGIN
DECLARE #var NVARCHAR(MAX) = ''
SET #var = 'print this data in txt file'
PRINT 'Data is : ' + #var
declare #fn varchar(200) = 'c:\temp\out.txt';
declare #cmd varchar(8000) = concat('echo ', #var, ' > "', #fn, '"');
print #cmd
exec xp_cmdshell #cmd, no_output
set #cmd = concat('type "', #fn, '"');
print #cmd
exec xp_cmdshell #cmd;
END
go
EXEC [dbo].[usp_printresulttofile]
I might recommend creating a batch file to accomplish this. You can simply do this:
sqlcmd -i ExecSQLProc.sql > Results.txt
Save your EXEC command in a file named ExecSQLProc.sql and then create a batch script with the line above. You can also attach this to the scheduler if needed so that you can regularly generate these scripts. Also you can create a process to output whatever your process produces into an email using only SQL server and see the results this way as well.
Generally I have found it better to use the Operating System to manipulate individual files, if you want to append results you have options:
sqlcmd -i ExecSQLProc.sql >> CumulativeResults.txt
Update your stored process to keep track of your data in the database that is a large container - a blob for instance, and then when you execute your script it will generate a file that has everything in it.
Use bcp command to copy data into any format. You just need to mention the format in which you want. Like .text
bcp 'select * from table' queryout c:\sql\bcp.txt -c -T
Example and explaination in below link :-
https://www.mssqltips.com/sqlservertip/4353/export-sql-server-records-into-individual-text-files/
Just remember to be careful with the string going to the text file. If it has quotes / double quotes, etc. it will affect its ability to save. I automatically put double quotes around my outgoing string and it typically helps but if your string is more complicated (i.e. a SQL query with literal comparisons) then you likely will have more work to do.
I want to export data using bcp command and the output of the bcp command should be stored in the variable.
My try:
DECLARE #Result varchar(max)
DECLARE #SQL nvarchar(max)
SET #SQL = N'Execute xp_cmdshell ''bcp "SELECT * FROM EMP" QueryOut "E:\BCP\Result.pec" -T -t#_# -c -o "E:\BCP\LogReport.txt"'''
EXEC sp_executesql #SQL, N'#Result nvarchar(75) OUTPUT', #Result =#Result output
PRINT(#Result)
But getting an error in the output:
output
------------------------------------------------------------------------------
bcp: Unable to open output file E:\BCP\LogReport.txt: No such file or directory
NULL
Questions:
1. How to store the above output result into the variable?
2. Given permission to the file and folder too, but still getting this error.
---------------------------------------- 1 -------------------------------------------
DECLARE #Result TABLE
(error_msg VARCHAR(800))
DECLARE
#SQL varchar(8000),
#Result_var VARCHAR(MAX)=''
SET #SQL = N'bcp "SELECT * FROM <MY_DATABASE>.<MY_SCHEMA>.<MY_TABLE>" QueryOut "E:\BCP\Result.pec" -T -t#_# -c -o "E:\BCP\LogReport.txt"'''
-- Insert the output from xp_cmdshell into the table #Result
INSERT INTO #Result (error_msg)
EXEC xp_cmdshell #SQL
-- Merge the rows
SELECT #Result_var = #Result_var + ' ' + ISNULL(error_msg,'') FROM #Result
-- Output in variable
PRINT #Result_var
--------------------------------------------------------------------------------------
2. For me, your command works, check access to folders and subfolders (for database user), check permissions on the sql server.
i am facing an issue while executing the BCP command in the remote server.
i have the following command in a batch file which executes a script file.
The script file process a temporary table and writes the records in temporary table to a file.
SQLCMD -SQA_Server236 -dtestdb -Usa -PPassword1 -i"D:\script\Writing to Files\Write to CSV.sql" -o"D:\script\script_logs.log"
--script files contains...
declare #table NVARCHAR(255)
declare #filename VARCHAR(100)
set #filename='C:\TextFile\abcd.csv'
set #table ='##Indexes_Add'
IF OBJECT_ID('tempdb..#Indexes_Add') IS NOT NULL
BEGIN
DROP TABLE ##Indexes_Add
END
CREATE TABLE ##Indexes_Add
(
id int IDENTITY(1,1) PRIMARY KEY,
alter_command NVARCHAR(MAX),
successfully_readded BIT NULL,
)
insert into ##Indexes_Add select 'a',0
insert into ##Indexes_Add select 'a',0
SET NOCOUNT ON;
IF OBJECT_ID('tempdb..'+#table) IS NOT NULL
BEGIN
DECLARE
#sql NVARCHAR(MAX),
#cols NVARCHAR(MAX) = N'';
SELECT #cols += ',' + name
FROM tempdb.sys.columns
WHERE [object_id] = OBJECT_ID('tempdb..'+#table)
ORDER BY column_id;
SELECT #cols = STUFF(#cols, 1, 1, '');
SET #sql = N'EXEC master..xp_cmdshell ''bcp "SELECT '''''
+ REPLACE(#cols, ',', ''''',''''') + ''''' UNION ALL SELECT '
+ 'RTRIM(' + REPLACE(#cols, ',', '),RTRIM(') + ') FROM '
+ 'tempdb.dbo.'+#table + '" queryout "' + #filename + '" -c -t, -SQA_Server236 -Usa -PPassword1''';
EXEC sp_executesql #sql;
print #sql
END
My problem-:
When i run the above batch command in a batch file and i give my local server other than server name "QA_Server236" , i am getting the file "abcd.csv" created in my system but when i give the server name as "QA_Server236" the file is created in the remote machine i.e QA_Server236. But i want the file to be created in my system if the given server is a remote server say "QA_Server236"
Can anyone help me in this issue. i am not getting any method to do so.
If I'm right BCP does not allow saving result sets and/or logs to remote machines. But you could try to mount a folder on remote PC to a shared folder on your local machine and set the output location there, or maybe try using network path "\[YOURPC]....".As I'm not sure it works (actually, I think it won't), here's the only solution I can think of: add a line to your batch which moves the file(s) from the remote machine to your PC (xcopy or similar) after BCP finished executing (in batch, do this as "Call bcp.exe [params]" instead of just "bcp.exe ...")Hope this helps!
I have a database table with a column named File Content, and many rows. What I need is to create a text file for each row of File Content column.
Example:
Sr. File Name File Content
1. FN1 Hello
2. FN2 Good Morning
3. FN3 How are you?
4. FN4 Where are you?
Suppose I have 4 rows, then 4 text files should be created (maybe with any name which we want)
File1.txt should have text "hello" in it.
File2.txt should have text "Good Morning" in it.
File3.txt should have text "How are you?" in it.
File4.txt should have text "Where are you?" in it
Although you said you said you need to do it in TSQL, I wouldn't do it that way if possible. Ram has shown you one solution, but it has the disadvantages that you need to use xp_cmdshell and the SQL Server service account needs permission to access the file system in whatever location you want to have the files.
My suggestion would be to write a script or small program in your preferred language (PowerShell, Perl, Python, C#, whatever) and use that instead. TSQL as a language is simply badly suited for manipulating files or handling anything outside the database. It is obviously possible (CLR procedures are another way), but you often run into problems with permissions, encodings and other issues that are much easier to deal with in an external language.
This can be done with BCP OUT syntax of SQL server.
For the setup: just make sure that you have xp_cmdshell exec permissions on the server. This can be checked from master.sys.configurations table. Also change filelocation path corresponding to your server or network share. I checked and was able to generate 4 files as there are 4 records in the table.
use master
go
declare #DSQL Nvarchar(max)
declare #counter int
declare #maxrows int
declare #filename Nvarchar(30)
select #counter=1, #maxrows = 0
create table t1 (
sno int identity(1,1) not null,
filename varchar(5),
filecontent varchar(100)
)
insert into t1
select 'FN1', 'Hello'
UNION
select 'FN2', 'Good Morning'
UNION
select 'FN3', 'How are you?'
UNION
select 'FN14', 'Where are you?'
select #maxrows = count(*) from t1
--SELECT * FROM T1
while (#counter <= #maxrows)
begin
select #filename = filename from t1
where sno = #counter
select #DSQL = N'exec xp_cmdshell' + ' ''bcp "select filecontent from master.dbo.T1 where sno = ' + cast(#counter as nvarchar(10)) + '" queryout "d:\temp\' + #filename + '.txt" -T -c -S home-e93994b54f'''
print #dsql
exec sp_executesql #DSQL
select #counter = #counter + 1
end
drop table t1
I am using SQL Server 2005. Is there any command or GUI tool (e.g. any menu/function from SQL Server management studio) to convert database table into XML schema file (.xsd)?
thanks in advance,
George
I've found this. Give it a try
Select CourseID, Name, CoursePrice
FROM CouseMaster.Course Course
FOR XML AUTO, XMLSCHEMA
You can write to file like this:
bcp.exe "select top 0 * from (select 1 as iCol) as t for xml auto, xmlschema" queryout outfile.xsd -T -c
I'm Using the TOP 0 to exclude the xml of the actual query data since you only want the schema. The -c causes it to be plain character data in the output, use -w instead if you want utf-16 (unicode) output.
EDIT - and if you want to change the xml structure, look at PATH with FOR XML.
Declare #SQL nvarchar(1000)
SET #SQL= 'bcp.exe '+ '"select * from yourdbname.yourschema.yourtablename for xml path (''record''), ROOT (''tabel'')"' +' queryout '+ 'c:\yourfilename.xsd' +' -w -r -t -SyourServerName -T'
print #SQL
EXEC Master..xp_CmdShell #SQL
Replace allvalues starts with 'your', accordingly