How to use a variable in Openrowset command With SQL Commands - sql

I want to update database from a .sql file which contain some commands like update and edit and delete.
I try hard to pass the .sql file to the procedure to make it run.
This is my code which only shows me the file instead of running it:
DECLARE #filePath nvarchar(1000)
DECLARE #command nvarchar(1000)
DECLARE #query nvarchar(1000)
SET #filePath = 'd:\amz\update_price001.sql'
SET #command = '(SELECT * FROM OPENROWSET(BULK '''+#filePath+''', SINGLE_CLOB) AS Contents)'
SELECT #command
SET #query = #command
EXEC sp_executesql #query
This is the result of the select #command:
(SELECT * FROM OPENROWSET(BULK 'd:\amz\update_price001.sql', SINGLE_CLOB) AS Contents)
but the result of the EXEC sp_executesql #query is the filecontent - not the execution result.

Related

Stored Procedure to Import XML into SQL Server

I'm trying to import XMLs into SQL Server. If I print the below #command, I can copy and paste into SSMS and the code runs perfectly. However, I get the following error if I try to run this as an sp.
exec etl.import_xml 'c:\xml_file.xml'
Msg 137, Level 15, State 1, Line 1
Must declare the scalar variable "#stream".
ALTER PROCEDURE etl.import_xml (
#file_name VARCHAR(1000)
) AS
BEGIN
DECLARE #command NVARCHAR(1000)
DECLARE #stream VARCHAR(MAX)
SET #command = N'SELECT #stream = CAST(BulkColumn AS VARCHAR(MAX))
FROM OPENROWSET(BULK ''' + #file_name + ''', SINGLE_BLOB) AS x;'
--EXEC sp_executesql #command, N'#file_stream_out VARCHAR(MAX) OUTPUT', #stream_out = #stream OUTPUT
EXECUTE(#command)
SET #stream = dbo.strip_xmlns(#stream)
UPDATE swf.etl.raw_data
SET xml_string = CONVERT(XML, #stream)
WHERE xml_file_name = #file_name
END
As per Dale K, I need to declare everything within the command string. Obviously there are still issues with SQL injection, however no user will have access to this proc and will only be run on an automation server.
ALTER PROCEDURE etl.import_xml (
#file_name VARCHAR(1000)
) AS
BEGIN
DECLARE #command NVARCHAR(1000)
DECLARE #stream VARCHAR(MAX)
SET #command = N'DECLARE #stream VARCHAR(MAX) SELECT #stream = CAST(BulkColumn AS VARCHAR(MAX))
FROM OPENROWSET(BULK ''' + #file_name + ''', SINGLE_BLOB) AS x;
SET #stream = dbo.strip_xmlns(#stream)
UPDATE swf.etl.raw_data
SET xml_string = CONVERT(XML, #stream)
WHERE xml_file_name = ''' + #file_name + '''
'
EXECUTE(#command)
END
Here is how to do it with an XML file name as a parameter.
SQL
DECLARE #xml XML
, #sql NVARCHAR(MAX)
, #fileName VARCHAR(256) = 'e:\Temp\Diego.xml';
SET #sql = N'SELECT #xmlOut = XmlDoc FROM OPENROWSET (BULK ' + QUOTENAME(#fileName,NCHAR(39)) + ', SINGLE_BLOB) AS Tab(XmlDoc)';
EXEC sys.sp_executesql #sql, N'#xmlOut XML OUTPUT', #xmlOut = #xml OUTPUT;
SELECT #xml;

Error in dynamic execute with local variable

I'm getting the error :
Procedure expects parameter '#params' of type 'ntext/nchar/nvarchar'
for the following execute statement. I'm a little confused with this, after reading several posts on the website,
I came to understand that I would need to pass #val as a variable since exec will execute the command as-is.
declare #val varchar(max);
declare #query nvarchar(max);
set #query = 'set #val = (select ' + #cols + ' from temp where loan_number = ''72'')'
exec sp_executesql #query, '#val varchar(max) output', #val output
Conversely, if I executed the exec as a non-dynamic query as just exec(#query), I get the error
Must declare the scalar variable "#val".
IF the statement "Should the output of the query be a 1x1 table since I" is true, then you need to use a SELECT to set the value:
DECLARE #val varchar(MAX);
DECALRE #query nvarchar(MAX);
SET #query = N'SELECT #val = ' + QUOTENAME(#cols) + N' FROM temp WHERE loan_number = ''72'');';
EXEC sp_executesql #query, N'#val varchar(MAX) OUTPUT', #val OUTPUT;
The fact that you have a variable called #cols implies that the variable will hold the names of many columns, not one.

Execute stored procedure using openrowset without doing with result sets for every column

When I execute a stored procedure using openrowset, which has dynamic SQL in it, it throws an error
Contains dynamic SQL. Consider using WITH RESULT SETS
An example is as follows.
select output.*
from openrowset ('SQLOLEDB','SERVER=(local);Trusted_Connection=yes;',
'SET FMTONLY OFF;SET NOCOUNT ON; exec storedproc ') as output
Since I have many output parameters, is there a simple way to display all the columns?
Note: I have to use openrowset as the stored procedure is being executed inside a script (R).
I also tried the following but didn't work.
declare #sqlstmt nvarchar(max)
declare #queryout nvarchar(max)
set #queryout = 'storedproc #parameter1=''''D'''', #param2=''''08/19/2018'''', '
set #queryout = '''exec ' + #queryout
set #sqlstmt = N'select outputprod.* from openrowset (''SQLOLEDB'',''SERVER=(local);Trusted_Connection=yes;'' , ' + #queryout + ''') as outputprod'
print(#sqlstmt)
exec (#sqlstmt)
You can use Dynamic Query with full select statement inside varchar variable then execute it with EXEC. see here.
for example
DECLARE #sqlCommand varchar(1000)
DECLARE #columnList varchar(75)
DECLARE #city varchar(75)
SET #columnList = 'CustomerID, ContactName, City'
SET #city = '''London'''
SET #sqlCommand = 'SELECT ' + #columnList + ' FROM customers WHERE City = ' + #city
EXEC (#sqlCommand)
Modify the Stored procedure with output parameter to return the generated query, to avoid dynamic stored procedure being passed.
DECLARE #queryout NVARCHAR(max)
DECLARE #sqlstmt NVARCHAR(max)
EXEC storedproc #queryout OUTPUT
SET #sqlstmt = N'SET FMTONLY OFF;SET NOCOUNT ON;' + #queryout
select output.* from openrowset (
'SQLOLEDB','SERVER=(local);Trusted_Connection=yes;', #sqlstmt) as output

How to use a variable in Openrowset command

I am trying to use a variable filepath in a SQL Openrowset command. I'm aware that it can't explicitly accept a variable and that I need to make use of dynamic SQL.
What currently works -
SELECT #file_stream = CAST(bulkcolumn AS VARBINARY(MAX))
FROM OPENROWSET(BULK 'C:\Temp\print4.pdf', SINGLE_BLOB) AS x
However if I try to use my variable filepath
declare #file_stream VARBINARY(MAX)
declare #filePath NVARCHAR(128)
set #filePath = 'C:\Temp\print4.pdf'
set #command = N'SELECT #file_stream = CAST(bulkcolumn AS varbinary(MAX))
from OPENROWSET(BULK ' + #filePath + ',
SINGLE_BLOB) ROW_SET'
EXEC sp_executesql #command, #filePath, #file_stream;
I get the error 'Msg 137, Level 15, State 2, Line 15
Must declare the scalar variable "#filePath".'
I'm sure this is an issue of syntax but haven't been able to figure out how it should be formatted yet.
Change your script like below.
DECLARE #file_stream VARBINARY(MAX)
DECLARE #command nvarchar(1000)
DECLARE #filePath NVARCHAR(128)
set #filePath = 'C:\Temp\print4.pdf'
set #command = N'SELECT #file_stream1 = CAST(bulkcolumn AS varbinary(MAX))
from OPENROWSET(BULK ''' + #filePath + ''',
SINGLE_BLOB) ROW_SET'
EXEC sp_executesql #command, N'#file_stream1 VARBINARY(MAX) OUTPUT',#file_stream1 =#file_stream OUTPUT
select #file_stream
Sample Output :

Create SQL Server stored procedure with stock data

I am trying to turn some code I have from SQL Server into a stored procedure with parameters that I can pass through but I am not sure how to do this. I want the 4 letter stock symbol of the URL to be a variable so that I can pass through different symbols, I also need this code to work as a stored procedure.
GOOG is where I need the variable.
http://finance.yahoo.com/webservice/v1/symbols/GOOG/quote'
--RSS FEED
DECLARE #docHandle INT;
DECLARE #xmlData XML;
DECLARE #URL NVARCHAR(255);
DECLARE #file NVARCHAR(255);
DECLARE #cmd NVARCHAR(255);
DECLARE #sql NVARCHAR(255);
DECLARE #tXML TABLE(data XML);
SET #URL = 'http://finance.yahoo.com/webservice/v1/symbols/GLUU/quote';
SET #file = 'c:\temp\quotes.xml';
-- Downloading the data
SET #cmd = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell (new-object System.Net.WebClient).DownloadFile( ''' + #URL + ''',''' + #file + ''' )'
EXEC master.dbo.xp_cmdshell #cmd, no_output
-- Loading the Downloaded File into the XML variable
SET #sql = 'SELECT BulkColumn FROM OPENROWSET( BULK ''' + #file + ''', SINGLE_BLOB ) AS a'
INSERT #tXML EXEC(#sql);
SELECT #xmlData = data from #tXML
-- Preparing the Relational Table from the XML variable
EXEC sp_xml_preparedocument #docHandle OUTPUT, #xmlData;
INSERT INTO tblstockdata ([Name], [Price], [Symbol], [TS], [Type], [Volume])
SELECT * FROM OPENXML(#docHandle, N'//list/resources/resource')
WITH ( Name VARCHAR(10) 'field[#name="name"]',
Price VARCHAR(10) 'field[#name="price"]',
Symbol VARCHAR(10) 'field[#name="symbol"]',
TS VARCHAR(10) 'field[#name="ts"]',
Type VARCHAR(10) 'field[#name="type"]',
Volume VARCHAR(10) 'field[#name="volume"]');
EXEC sp_xml_removedocument #docHandle;
Thanks!
:)
You have working SQL, which is the tough part. Now bracket your working SQL with
CREATE PROCEDURE <schema>.<Name>(
#param <type>
) as begin
and
end
and you should be good to go. For starters you can use dbo as the value of <schema> until you need to use a non-default schema. It is recommended that you not use the prefix "sp" or "xp" for your procedure name as these are used to identify system and extended procedures by SQL Server.
If you need additional parameters they can be added to the parameter list using a comma as the delimiter.
Below is a stored procedure example gleaned from your code that takes the needed symbol parameter. Here, I used the XML data type methods rather than sp_xml_preparedocument. If multiple users might call this stored procedure at the same time, I suggest you generate a unique name for the file an delete afterwards. You might consider a CLR stored procedure to avoid both the temporary file and OPENROWSET ugliness.
CREATE PROC dbo.usp_GetEquityQuote
#symbol varchar(10)
AS
DECLARE #URL NVARCHAR(255);
DECLARE #file NVARCHAR(255);
DECLARE #cmd NVARCHAR(255);
DECLARE #sql NVARCHAR(255);
DECLARE #tXML TABLE(data XML);
SET #URL = 'http://finance.yahoo.com/webservice/v1/symbols/' + #symbol + '/quote';
SET #file = 'c:\temp\quotes.xml';
-- Downloading the data
SET #cmd = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell (new-object System.Net.WebClient).DownloadFile( ''' + #URL + ''',''' + #file + ''' )';
EXEC master.dbo.xp_cmdshell #cmd, no_output;
-- Loading the Downloaded File into the XML variable
SET #sql = 'SELECT BulkColumn FROM OPENROWSET( BULK ''' + #file + ''', SINGLE_BLOB ) AS a';
INSERT #tXML EXEC(#sql);
SELECT data from #tXML ;
SELECT
resources.resource.value('field[#name="name"][1]', 'varchar(10)') AS name
,resources.resource.value('field[#name="price"][1]', 'decimal(18,4)') AS price
,resources.resource.value('field[#name="symbol"][1]', 'varchar(10)') AS symbol
,resources.resource.value('field[#name="ts"][1]', 'bigint') AS ts
,resources.resource.value('field[#name="type"][1]', 'varchar(10)') AS type
,resources.resource.value('field[#name="volume"][1]', 'bigint') AS volume
FROM (SELECT data FROM #tXML) AS tXML(data)
CROSS APPLY data.nodes('/list/resources/resource') AS resources(resource);