How Can I use parameter in OPENROWSET() function? - sql-server

I am trying to get an image from a shared folder, but while I am trying to pass parameter in OPENROWSET function I am getting an error:
Incorrect Syntax near......
I tried this one so far:
alter FUNCTION dbo.GetImage (#imagePath varchar(200))
RETURNS varbinary(max)
AS
BEGIN
DECLARE #Result varbinary(max);
EXEC master..xp_cmdshell 'net use Z: \\192.168.1.175\Rack /user:192......\username pass';
SELECT #Result = ProjectImage
FROM OPENROWSET(BULK 'Z:' + #imagePath, SINGLE_BLOB) AS ProjectImage(ProjectImage);
RETURN #Result;
END;

The short answer is you can't. OPENROWSET only takes a string constant, so you need to use dynamic SQL to inject your file path to the SQL then execute that SQL. You will however not be able to do this within a function, so you're best bet is to use a stored procedure and an output parameter to get the varbinary out:
CREATE PROCEDURE dbo.GetImage (#imagePath varchar(200), #Result VARBINARY(max) OUTPUT)
AS
BEGIN
EXEC master..xp_cmdshell 'net use Z: \\192.168.1.175\Rack /user:192......\username pass';
DECLARE #SQL nvarchar(max) =
N'SELECT #Result = BulkColumn
FROM OPENROWSET(BULK ''Z:' + #imagePath + N''', SINGLE_BLOB) AS t';
EXECUTE sp_executesql #SQL, N'#Result varbinary(max) OUTPUT', #Result OUTPUT;
RETURN #Result;
END;
With that being said, if you're only looking to read a file and convert it to binary then SQL doesn't really feel like the right tool for the job - I'm never a big fan of conflating file system tasks with the database except for in ad hoc processes, but ad hoc processes should not require a permanent solution like a function or a stored procedure.

Related

OPENROWSET: sp_executesql statement failing at #param

I am developing a program to pull in the XML file that WordPress enables you to download (essentially a backup copy).
At this point I was automating the process to allow frequent backup of my data on SQL Server, and for some reason I am stuck at developing the query to run the OPENROWSET where the XML file will be located.
DECLARE #SQL NVARCHAR(MAX)
DECLARE #ParamDefinition NVARCHAR(500) = N'#fstring NVARCHAR(MAX)'
DECLARE #string VARCHAR(MAX) =
N'C:\[FilePath]\Reviews\thehesperian2016-07-29.xml'
SET #SQL =
N'INSERT INTO #Temp (Extract_Date, XMLDATA)
SELECT GETDATE()
, A.*
FROM OPENROWSET(BULK #fstring, SINGLE_BLOB, CODEPAGE = ' + '''RAW''' + ') AS A'
EXEC sp_executesql #SQL
, #ParamDefinition
, #fstring = #string
The error:
Msg 102, Level 15, State 1, Line 4
Incorrect syntax near '#fstring'.
I can turn this into a simple query on a table in the predicate, so I have reason to suspect it is the way the filepath is read.
I've spent a few hours racking my brain trying to figure out why this is wrong. While I COULD use QUOTENAME as in this example in the BULKINSERT, I was hoping to embed all of that in the dynamic SQL (thus still use sp_executesql)
What or why am I doing this wrong? Any help will be greatly appreciated.
- Regards,
ANSWER
OPENROWSET - MSDN declares in its own paragraph:
OPENROWSET does not accept variables for its arguments.
QUOTENAME is sufficient, although I did run a few minor REPLACEfunctions anyways.
The data file path the OPENROWSET function does not allow a parameter. Instead, build the needed string with the literal:
DECLARE #string varchar(MAX) = N'C:\[FilePath]\Reviews\thehesperian2016-07-29.xml';
DECLARE #SQL nvarchar(MAX);
SET #SQL =
N'INSERT INTO #Temp (Extract_Date, XMLDATA)
SELECT GETDATE()
, A.*
FROM OPENROWSET(BULK ' + QUOTENAME(#string, '''') + ', SINGLE_BLOB, CODEPAGE = ''RAW'') AS A';
EXEC sp_execute #SQL;
--EXECUTE(#SQL);
UPDATE:
Added QUOTENAME in case the provided file path is from an untrusted source. Also, note that OPENROWSET queries are not autoparameterized. It makes no difference whether one executes the query with sp_executesql or EXECUTE here.

Call SQL linked sever function or stored procedure from select statement

I have a stored procedure which calls a lookup function as part of the SELECT statement:
-- PX type
CASE WHEN coi.SKU_ID like 'PX%' THEN
[GG].dbo.PXStockInventoryLookup(coi.SKU_ID)
ELSE
0
END
In the production environment, the GG database is on a different server so a linked server is used to reference it. Trying to call the function using 4 part naming gives this error:
Remote function reference 'UATLINK.GG.dbo.PXStockInventoryLookup' is not allowed, and the column name 'UATLINK' could not be found or is ambiguous.
After some research I found out about using Dynamic SQL, OPENQUERY and sp_executesql in a local function:
DECLARE #ParamDefinition as nvarchar(100)
SET #ParamDefinition = N'#Result int output'
DECLARE #sql nvarchar(4000);
SET #sql = 'SELECT * FROM OPENQUERY( [UATLINK], ''SELECT [GG].[dbo].[PXStockInventoryLookup](''''' + #param + ''''')'')'
exec sp_executesql #sql, #ParamDefinition, #Result = #sii output
return #sii
This code works fine in isolation, but I can't create it a function as SQL doesn't allow me to call a function from within another function. I can create is as a stored procedure but then I can't call it from the select statement!
I'm just going round in circles trying to solve this, any ideas?

Using dynamic sql in openrowset produces error

I need to create a stored procedure that gets a path as a parameter and inserts from file into table via OPENROWSET command.
After lots of searching and trying, I learned that OPENROWSET does not
support parameters and thus needs to be called with dynamic SQL.
That is the part that doesn't work, it shows me a strange error.
It could be caused by the OPENROWSET not accepting the string parameter
but - I saw many code snippets that are built similarly and users say they work.
Please help me understand what I'm missing here and how do I make this work?
Here is my code:
Declare #string varchar(MAX) = 'C:\Users\akoga_000\Desktop\test1.xlsx'
DECLARE #sqlString AS varchar(MAX)=
'insert into gameIt_DBSummer.dbo.tblUser
select * from openrowset(
''Microsoft.ACE.OLEDB.12.0'',
''EXCEL 12.0;DataBase=''
'+cast(#string as varchar(max))+'
'';Extended Properties="EXCEL 12.0 Xml;HDR=YES'',
''SELECT * FROM [Sheet1$]''
)';
EXEC (#sqlString)
//I tried also with EXEC sp_executesql and a nvarchar variable among other options
Here is the error:
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near 'C:'.
I think you are getting that error because you need double extra '' character surrounding the path (#string variable). Try this:
Declare #string varchar(MAX) = 'C:\Users\akoga_000\Desktop\test1.xlsx'
DECLARE #sqlString AS varchar(MAX)=
'insert into gameIt_DBSummer.dbo.tblUser
select * from openrowset(
''Microsoft.ACE.OLEDB.12.0'',
''EXCEL 12.0;DataBase=''''
'+#string+'
'''';Extended Properties="EXCEL 12.0 Xml;HDR=YES'',
''SELECT * FROM [Sheet1$]''
)';
select #sqlString

Passing concat query parameters to SQL OPENQUERY

Due to the constraints within the workplace I have to use a local stored procedure to call another remote stored proc on a linked sql server, however the problem lies in passing a necessary parameter to the remote stored proc.
This is the query I constructed:
select *
from OPENQUERY([REMOTE_SRVR],'exec db.dbo.dwStoredProc_sp ''#id''')
In order to pass #id to the remote stored proc I understand I could concatenate the above as a string and then use exec
Something along the lines of:
set #query = 'select * from OPENQUERY([REMOTE_SRVR], ''EXEC db.dbo.dwStoredProc_sp '' #id '''''
exec(#query)
I cannot get the local stored proc to successfully call the other. The single quote mess doesn't help!
I get the error: Could not find stored procedure 's'
To help with the quote mess I like to do this in steps. It is more code but easier to understand. I am not sure from your example if #id is an integer. In that case you can lose the double quotes around __ID__.
set #query = 'EXEC db.dbo.dwStoredProc_sp ''__ID__'''
set #query = REPLACE(#query,'__ID__',#id)
set #query = REPLACE(#query,'''','''''')
set #query = REPLACE('SELECT * FROM OPENQUERY([REMOTE_SRVR], ''__REMOTEQUERY__'')','__REMOTEQUERY__',#query)
You could avoid dynamic queries by simply by using EXEC (..., ParamValue) AT LinkedServer (see product's documentation, example [L. Using a parameter with EXECUTE and AT linked_server_name]):
1) On target server:
CREATE PROCEDURE dbo.Proc1( #id NVARCHAR(50) )
AS
SELECT #id AS [id];
GO
2) On the source server you create the linked server and then you can call the stored procedure using EXEC ... AT ... syntax:
DECLARE #p1 NVARCHAR(50);
SET #p1 = N'DROP TABLE dbo.CocoJambo'
EXECUTE (N'dbo.Proc1 ? ' , #p1 ) AT LOCALINKEDSEREV
Output:
id
------------------------
DROP TABLE dbo.CocoJambo

How do I get an stored procedure output into a variable inside a function in T-SQL?

I've got a task which can be only accomplished by construction a QUERY at runtime and executing it with sp_executesql. The result has to be a boolean (0/1 integer) value which I need to return as a result of the function.
The only way I found to capture an SP's output is "INSERT INTO [table] EXECUTE [sp]" query, but functions forbid this.
Any ideas how to overcome this?
sp_executesql allows you to pass in parameters, but also to declare parameters as being for output. Just have a look at this simple example that is not very dynamic, but shows how output parameters for sp_executesql work
declare #sql nvarchar(max)
declare #user sysname
select #sql = 'SELECT #user = SYSTEM_USER'
exec sp_executesql #sql, N'#user sysname OUTPUT', #user OUTPUT
select #user

Resources