Saving image in database field to file on server - sql-server

I am trying to save data from a table directly to the servers file system using this t-sql:
DECLARE #ID int
DECLARE #command varchar(1000)
DECLARE #Name varchar(100)
DECLARE #FileName varchar(100)
DECLARE MyCursor CURSOR FOR
SELECT Id, [FileName] FROM FilesTable
OPEN MyCursor
FETCH NEXT FROM MyCursor
INTO #ID, #Name
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #FileName = 'd:\Temp\' + convert(varchar(200), #Name)
SET #command = 'bcp "SELECT FileBytes FROM FilesTable WHERE ID = ' + convert(varchar(18), #Id) + '" queryout "' + #FileName + '" -T -n'
EXEC master..xp_cmdshell #command, no_output
FETCH NEXT FROM MyCursor
INTO #Id, #Name
END
CLOSE MyCursor
DEALLOCATE MyCursor
The table is filled with solid data. accessing this data with a C# program works.
I did configure advanced options gave permission to use xp_cmdshell
When I run this query i don't get any error but no file was written.
I also don't see anything in the logs, (maybe I am looking in the wrong location?)
What am I doing wrong? Or what can I do to checdk 'under the hood'?

Based on the comment from Patrick and the answer in fastest way to export blobs from table into individual files I was able to store the images on my fileserver.
we ended up writing a CLR function something like the one given.

Related

Can i use sp_msforeachDB for registration procedure in all databese

I must resister the same stored procedure in many - over 200 - databases.
I tried this:
-------------------------------------------------------------
DECLARE DB_CURSOR CURSOR FOR
SELECT name
FROM sys.databases
OPEN DB_CURSOR
FETCH NEXT FROM DB_CURSOR INTO #DB_NAME
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql1 = '---' ←Create Procedure
SET #sql0 = 'USE [' + #DB_NAME + ']; EXEC(''' + #sql1 + ''')'
EXEC(#sql0)
END
-------------------------------------------------------------
I checked escape sequence and my query are normal. However, this code valid in only first database.
And it can repeat while number of database, but run at first database.
Is it why?
I searched many website, haven't prove yet.
Please help me.
If possible I want to solve it by a method that does not use sysobject.
Thanks for your advice.

Not displaying select results from dynamic SQL within Cursor

I'm currently learning SQL and trying to think of exercises for myself and I can't seem to make this one work even though it seems simple:
I'm trying to run a cursor through all the filtered tables within my db so that then I could pass that table name to a variable which will be used within a DynamicSQL inside the cursor. The end result should be all values from every column that has the column 'empid' in them.
However, the message returns as "Commands completed successfully" but I get to see no results despite my select statement.
I'm trying to run something like this:
declare #tablename nvarchar(200);
declare #empid int;
declare #sql nvarchar(200) = N'select * from ' + #tablename + N' where empid = ' +#empid;
declare tablecursor cursor for select table_name from information_schema.tables where col_length(table_name, 'empid') is not null;
open tablecursor;
fetch next from tablecursor into #tablename;
while ##fetch_status = 0
begin
execute sp_executesql #sql, 825
fetch next from tablecursor into #tablename;
end
close tablecursor;
deallocate tablecursor;
I've been searching everywhere for answers to make this work but can't find anything. I've tried putting into a stored procedure and then executing it from there but that didn't work either.
Help would be highly appreciated.
DECLARE #SQL Should be outside but assigning the Variable inside the while loop
SET #SQL = N'SELECT * FROM ' + #tableName
Should be in while loop.
The other thing is to increase the length of #SQL Variable.
Thank you kindly for the help. After I listened to your advice I've encountered more errors but at least for these I was able to find answers online. What I also learnt is that you can't have your sql string in quotes when you execute it as that will make SSMS treat #SQL as an actual string and not a variable. I've managed to get it working and my code now looks something like this:
create proc cdr #empid nvarchar(5) as
declare #tablename nvarchar(200);
declare tablecursor cursor for select table_name from information_schema.tables where col_length(table_name, 'empid') is not null;
open tablecursor;
fetch next from tablecursor into #tablename;
declare #sql nvarchar(max)
while ##fetch_status = 0
begin
set #sql = N'select * from ' + #tablename + N' where empid = ' + #empid;
execute sp_executesql #sql
fetch next from tablecursor into #tablename;
end
close tablecursor;
deallocate tablecursor;

Query number of records across all databases

I have multiple databases in my SQL Server. All databases are the same in structure but have different data. These databases are used to store sensor data so each sensor has it's own seperate DB in the SQL Server.
I want a query to Select the Database name and number of records in a specific table of each DB.
I tried with a cursor. I get error saying the name {query} is not a valid identifier. My Cursor is as follows:
Declare #dbname Varchar (50), #sql Varchar(1000)
Declare db_cursor CURSOR FOR
SELECT name
FROM master.dbo.sysdatabases
WHERE name LIKE 'EP505-%' -- All sensors of EP505
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql= 'SELECT Count(*) FROM [' + #dbname + '].dbo.TimeLine'
EXEC #sql
FETCH NEXT FROM db_cursor INTO #dbname
END
CLOSE db_cursor
DEALLOCATE db_cursor
In the output I require the db name and the number of records for the TimeLine table.
What's the best way to achieve what I am trying.
Use parentheses when executing a SQL query string like so:
EXEC (#sql). Without parentheses, SQL Server will interpret #sql as a stored procedure or user-defined function.
your attempt looks quite good so far.
Please try adding a fetch next below the exec-line and try putting the #SQL variable after the exec brackets. That worked in my SQL Server environment.
hope this helps
br
Patrik
You can use sp_executeSQL to execute your dynamic query instead of exec statement which will help you to solve your issue
Here is the modified version
Declare #dbname Varchar (50), #sql nVarchar(1000)
Declare db_cursor CURSOR FOR
SELECT name
FROM master.dbo.sysdatabases
WHERE name LIKE 'kodyaz' -- All sensors of EP505
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql= N'SELECT Count(*) FROM [' + #dbname + '].dbo.Kontaktpersonen'
exec sp_executesql #sql
FETCH NEXT FROM db_cursor INTO #dbname
END
CLOSE db_cursor
DEALLOCATE db_cursor
I change #sql data type to nvarchar() and use
exec sp_executesql #sql

Exporting XML Data to mutiple files but retain structure

I have been searching on the net for the last couple of days and unfortunately cannot find quite what I am looking for. I have a SQL Server 2012 table that contains 2 columns, one is PurchaseOrder DataType varchar(10) the other is Data with a DataType of XML. Currently what is happening ever few hours a stored procedure is run to check a number of table for a value and then create a PurchaseOrder in the desired XML format. This has been achieved and validated by the company that I am going to be sending the data to. The issue I now have is I want to create a SSIS package that looks at this table and creates multiple xml files with the contents of the Data field "not putting the contents in to one long line" and then using the PurchaseOrder field for the file name. I have found various part solutions e.g. using a Script task as there is no native XML Destination in SSIS but struggling and being quite new to SSIS not getting anywhere fast. Can anyone offer any help, guidance, youtube links or even a part way there package.
Thanks P
Further to the above question I have tried to go about it using the bcp command, below is the following code that works great just looking at the top 1 record
DECLARE #fileName VARCHAR(50)
DECLARE #sqlStr VARCHAR(1000)
DECLARE #sqlCmd VARCHAR(1000)
SET #fileName = 'C:\Temp\test.xml'
SET #sqlStr = 'select TOP 1 Data from DatabaseName.dbo.OutputXML'
SET #sqlCmd = 'bcp "' + #sqlStr + '" queryout ' + #fileName + '
-w -T -S Server\Instance'
EXEC xp_cmdshell #sqlCmd
What I have then done is add this in to a cursor, which again works to a point, it creates my files, using the purchaseorder as the file name and outputs the relevant information but it no longer holds the proper xml format, it goes back to looking like a string with none of the original formatting, is this because I am imbedding it in the cursor?? Below is the code that I am using
DECLARE #fileName VARCHAR(50)
DECLARE #sqlStr VARCHAR(1000)
DECLARE #sqlCmd VARCHAR(1000)
DECLARE xml_cursor CURSOR FOR
SELECT PurchaseOrder from DatabaseName.dbo.OutputXML
OPEN xml_cursor
FETCH NEXT FROM xml_cursor INTO #fileName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #fileName = 'C:\Temp\'+#fileName+'.xml'
SET #sqlStr = 'select Data from DatabaseName.dbo.OutputXML'
SET #sqlCmd = 'bcp "' + #sqlStr + '" queryout ' + #fileName + '
-w -T -S Server\Instance'
EXEC xp_cmdshell #sqlCmd
FETCH NEXT FROM xml_cursor into #fileName
END
CLOSE xml_cursor
DEALLOCATE xml_cursor
Since bcp is a command line utility it does not know about your cursor. You can only change the parameters passed. You already pass the #filename from the cursor, you will also need to filter your query. Below is how to fix your problem but it is far from a great solution, it will be quite slow. I don't know what your key is called, so I called it SomeKey
DECLARE #fileName VARCHAR(50)
DECLARE #sqlStr VARCHAR(1000)
DECLARE #sqlCmd VARCHAR(1000)
DECLARE #SomeKey VARCHAR(100) --Put your key datatype here
DECLARE xml_cursor CURSOR FOR
-- replace SomeKey with your key
SELECT SomeKey,PurchaseOrder FROM DatabaseName.dbo.OutputXML
OPEN xml_cursor
FETCH NEXT FROM xml_cursor INTO #SomeKey,#fileName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #fileName = 'C:\Temp\' + #filename + '.xml'
SET #sqlStr = 'SELECT Data FROM DatabaseName.dbo.OutputXML WHERE SomeKey = ''' + #SomeKey +''''
SET #sqlCmd = 'bcp "' + #sqlStr + '" queryout ' + #fileName + '-w -T -S Server\Instance'
EXEC xp_cmdshell #sqlCmd
FETCH NEXT FROM xml_cursor into #SomeKey,#fileName
END
CLOSE xml_cursor
DEALLOCATE xml_cursor

SQL Server 2008 Management Console: Automatically write results to a script and execute it

I would like to write a script which produces various statements out of a database.
Something like :
select 'DROP TABLE ['+ name + ']' from sys.objects where type = 'T' ;
I would like to automatically collect all output of such statements in a new file, and then I would like to execute this file. Is this possible ?
Important: The output should of course be without headers and without any other error/success, messages and so on.
In the optimal case, all necessary options for this should be set in the script itself, other than setting them in the user interface.
First, you create you dynamic script, something like...
DECLARE #sql NVARCHAR(MAX)
SELECT #sql =
COALESCE(#sql + CHAR(13), '') +
'DROP TABLE ['+ name + ']'
FROM sys.objects
WHERE [type] = 'T'
Execute that...
EXEC(#sql)
Then print that out to Messages-window...
PRINT #sql
And finally go to Messages-window, right-click it, select "Save results as...", Save as type > all files, and write your file name like myfile.sql
EDIT
I would never, EVER execute something like this automatically and without transaction. I'd rather save a script from Messages-window, open it, review it and then execute.
Are you wanting something like this?
If you only want to print the script use osql and a script something like this
DECLARE #schema VARCHAR(255)
DECLARE #table VARCHAR(255)
DECLARE PrintOutputCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT [TABLE_SCHEMA], [TABLE_NAME]
FROM INFORMATION_SCHEMA.TABLES
OPEN PrintOutputCursor
FETCH NEXT FROM PrintOutputCursor INTO #schema, #table
WHILE ##FETCH_STATUS = 0 BEGIN
PRINT 'DROP TABLE ['+ #schema + '].[' + #table + '];'
FETCH NEXT FROM PrintOutputCursor INTO #schema, #table
END
CLOSE PrintOutputCursor
DEALLOCATE PrintOutputCursor
If you want to execute the script using osql use this script (NOT RECOMMENDED)
DECLARE #schema VARCHAR(255)
DECLARE #table VARCHAR(255)
DECLARE #exec VARCHAR(4000)
DECLARE PrintOutputCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT [TABLE_SCHEMA], [TABLE_NAME]
FROM INFORMATION_SCHEMA.TABLES
OPEN PrintOutputCursor
FETCH NEXT FROM PrintOutputCursor INTO #schema, #table
WHILE ##FETCH_STATUS = 0 BEGIN
SET #exec = 'DROP TABLE ['+ #schema + '].[' + #table + '];'
-- Uncomment the following to execute the dynamic statement
-- EXEC (#exec)
FETCH NEXT FROM PrintOutputCursor INTO #schema, #table
END
CLOSE PrintOutputCursor
DEALLOCATE PrintOutputCursor

Resources