Using a Variable in OPENROWSET Query - sql

I'm having trouble with this query:
SELECT *
FROM OPENROWSET(
'SQLNCLI',
'DRIVER={SQL Server};',
'EXEC dbo.sProc1 #ID = ' + #id
)
Gives an error:
Incorrect syntax near '+'.
Anyone know why I'm getting this error?

As suggested by Scott , you cannot use expressions in OPENROWSET.Try creating a dynamic sql to pass the parameters
Declare #ID int
Declare #sql nvarchar(max)
Set #ID=1
Set #sql='SELECT *
FROM OPENROWSET(
''SQLNCLI'',
''DRIVER={SQL Server};'',
''EXEC dbo.usp_SO #ID =' + convert(varchar(10),#ID) + ''')'
-- Print #sql
Exec(#sql)

OPENROWSET requires string literals, not expressions. It's complaining about the plus sign, becaue it doesn't expect anything more than a string literal and you follewed the string literal with an operator.
See http://msdn.microsoft.com/en-us/library/ms190312.aspx which states:
'query'
Is a string constant sent to and executed by the provider...

Declare #Route VARCHAR(200)
Declare #sql nvarchar(max)
Set #Route='C:\OCRevisiones.xlsx;'
Set #sql='SELECT * INTO FFFF
FROM OPENROWSET(
''Microsoft.ACE.OLEDB.12.0'',
''Excel 12.0;HDR=YES;Database=' + #Route + ''',
''SELECT * FROM [Sheet1$]'')'
Print #sql
--Exec(#sql)

If you need parameters you can also use sp_executesql:
BEGIN
DECLARE
#p_path varchar(200)='D:\Sample\test.xml',
#v_xmlfile xml,
#v_sql nvarchar(1000)
SET #v_sql=N'select #v_xmlfile= CONVERT(XML, BulkColumn) FROM
OPENROWSET(BULK '''+#p_path+''', SINGLE_BLOB) AS x;'
EXEC sp_executesql #v_sql,N'#v_xmlfile xml output',#v_xmlfile output;
SELECT #v_xmlfile
END

For what it is worth..
The reason we use openrowset rather than a straight linked server query is that the processing for a linked server query happens on the local server. (Slow and often brings most of the table back)
Yes we can do the string concatination as above.
A different option where you have ease of syntax and the power of parameters.
Create a stored proc on the remote box, that proc has all the parameters you need.
Call the stored proc from with a standard linked server query (same perf or better than the above soultion and significantly easier to code with.
e.g. linkedservername.database.dbo.myproc 123,'abc','someparam',getdate()
Just an option....

You can use Char(39) instead of '
set #lcSql= 'SELECT production_pbook_uq,variety_uq,color_uq,grade_uq,diff_qty
FROM OPENROWSET("SQLNCLI",
"Server=.;Trusted_Connection=yes;",
"EXEC serversql.dbo.sp_flower_production_varieties_consolidated #lcproduction_pbook_uq='+char(39)+#lcWo_uq+char(39)+', #lcproduct_piso_uq ='+char(39)+#lcpiso_uq+char(39)+'")'
+'where diff_qty>0'
print #lcSql

Related

Setting SQL Variable via Dynamic SQL

I know I am overthinking this, but I've been banging against this for too long so I'm reaching out for help.
This is the statement I'm trying to run: SELECT #cntMax = MAX(id) FROM [Raw_Item-FieldReport]
BUT, the table name is a variable #reportTable
This doesn't work:
SET #sql = 'SELECT #cntMax = MAX(id) FROM #reportTable'
EXEC sp_executesql #sql
I even tried having the actual table name in the SET #sql and that doesn't work either.
I didn't think it would be this difficult, please tell me I'm missing something easy/obvious.
Here's the full bit of code for those who want it:
DECLARE
#inTable nvarchar(255) = 'Raw_Item',
#reportTable nvarchar(255),
#fieldName nvarchar(255),
#cnt int,
#cntMax int,
#sql nvarchar(max)
SET #reportTable = #inTable + '-FieldReport'
SET #cnt = 1
SELECT #cntMax = MAX(id) FROM [Raw_Item-FieldReport]
PRINT #cntMax
SET #cntMax = 0
SET #sql = 'SELECT #cntMax = MAX(id) FROM [Raw_Item-FieldReport]'
EXEC sp_executesql #sql
PRINT #cntMax
SQL Server 12.0.2008.8 (on Azure)
You need to use an output parameter, otherwise SQL Server has no idea how to connect #cntMax in the dynamic SQL to #cntMax not in the dynamic SQL, since they are different scopes. And to protect yourself from SQL injection (some tips here and here), always check that your object exists, and use QUOTENAME() as opposed to manually adding square brackets (and you should always use QUOTENAME() when building object names from user input or variables, even when they don't have bad characters like dashes):
DECLARE #sql nvarchar(max),
#inTable nvarchar(255) = N'Raw_Item',
#reportTable nvarchar(255);
SET #reportTable = N'dbo.' + QUOTENAME(#inTable + '-FieldReport');
IF OBJECT_ID(#reportTable) IS NOT NULL
BEGIN
SET #sql = N'SELECT #cntMax = MAX(id) FROM ' + #reportTable + N';';
EXEC sys.sp_executesql #sql,
N'#cntMax int output',
#cntMax = #cntMax OUTPUT;
PRINT #cntMax;
END
ELSE
BEGIN
PRINT 'Nice try, h#xx0rs!';
END
Always use schema reference (dbo), always use statement terminators, and please try to avoid naming things with invalid identifier characters like dash (-). And one additional tip: always use N prefix on N'nvarchar string literals'.

Execute openrowset stored procedure, parameter use

Little bit of background information:
I have a stored procedure, lets call it SP1. SP1 calls another stored procedure: SP2. SP2 calls another stored procedure: SP3.
Now, the first stored procedure (SP1) returns a resultset. The resultset are parameters for SP2, this is done with a cursor.
Because of these nested inserts and executes, i have to use an openrowset dynamic SQL string to execute my stored procedures.
This is my query:
DECLARE #P_Source varchar(255) = 'test'
DECLARE #P_Location varchar(255) = 'test'
DECLARE #sql varchar(max)
SET #sql = 'INSERT INTO #tmp
SELECT *
FROM OPENROWSET (
''SQLOLEDB'',
''Server=(local);TRUSTED_CONNECTION=YES;'',
''set fmtonly off
EXECUTE dbo.SP1
#P_Source = '''''+#P_Source+'''''''
,#P_Location = '''''+#P_Location+'''''''
)'
exec(#sql)
(I have ofcourse created the table #tmp). I have more parameters to be exact (12), all varchar, but I left them out to not make it messy.
I'm getting the following error
Msg 102, Level 15, State 1, Line 12
Incorrect syntax near ','.
am I using the openrowset command in the correct way with the corresponding procedure parameters?
All those quotes get confusing. By doing select #sql prior to the exec you can see what SQL Server is going to try and do. Based on the query you've provided #sql currently contains:
INSERT INTO #tmp
SELECT *
FROM OPENROWSET (
'SQLOLEDB',
'Server=(local);TRUSTED_CONNECTION=YES;',
'set fmtonly off
EXECUTE dbo.SP1
#P_Source = ''test'''
,#P_Location = ''test'''
)
To help you build up to the final solution you could try having a dummy SP1 that takes two numeric parameters - that'll eliminate some quotes for you to worry about. Once you have that working you can proceed to add string parameters until you get what you want.
For sql linked server use OPENQUERY
https://learn.microsoft.com/en-us/sql/t-sql/functions/openquery-transact-sql
and sp_executesql
DECLARE #P_Source varchar(255) = 'test'
DECLARE #P_Location varchar(255) = 'test'
DECLARE #SQL NVARCHAR(MAX) = '',
#QUERY NVARCHAR(MAX) = '',
#Params NVARCHAR(500) = N'DECLARE #P_Source VARCHAR(255),#P_Location VARCHAR(255); ',
#ParamsValue NVARCHAR(500) = N'SELECT #P_Source = '''''+#P_Source+''''', #P_Location = '''''+#P_Location+''''';'
SET #Query = N'set fmtonly off; EXECUTE dbo.SP1 #P_Source, #P_Location'
SET #SQL = 'SELECT * FROM OPENQUERY([Local],'' sys.sp_executesql ' + #Params + #ParamsValue + #Query +''' )'
INSERT INTO #Tmp
EXEC (#SQL)

Is it possible to set a part of a select statement in a variable

I have a query of which the select-part is really long. I'd like to split this in several pieces, especially because some parts are in there twice or even more often.
What I'd like is something like the following:
Declare #SQLPart as varchar(1000)
Set #SQLPart = 'Field1,
case ... as Field2,'
Select ..., #SQLPart, ... From .....
Unfortunately this results error messages. I tried something like EXEC(#SQLPart) as well but of course this also didn't work. How would I solve this?
Yes, dynamic sql and sp_executesql:
CREATE TABLE ##Temp (Field1 int, Field2 int)
Declare #SQLPart nvarchar(1000)
Set #SQLPart = N'Field1, Field2 '
DECLARE #SQL nvarchar(1000) = N'SELECT ' + #SQLPart + 'FROM ##Temp'
PRINT #SQL
EXEC sp_executesql #SQL
DROP TABLE ##Temp
Your SQL code must be nvarchar type.
Alse sp_executesql is better than EXECUTE function, when you have many similar queries, sp_executesql caches executaion plans, and it can be better in perfomance.
You can use dynamic sql here,and use a EXECUTE keyword to execute this dynamic query
Declare #SQLPart as varchar(1000)
Set #SQLPart = 'Field1,
case ... as Field2,'
EXECUTE ('SELECT ....,'+#SQLPart+',... FROM ...')
SQL Server does not support Macro-Substitution, so you would have to use Dynamic SQL.
Declare #SQL varchar(max) ='Select ... ' + #SQLPart + '... from ...'
Exec(#SQL)

Procedure to insert Xml Into Sql Server -- Must Declare Scalar Variable

I am using the below procedure to try and insert xml via the filepath into a xml column. I am getting an error must declare scalar variable for ForeignId. Is there a better way of doing what I am trying to do, or am I on the right path?
Here is the procedure
ALTER PROC [dbo].[InsertXml] #path nvarchar(100)
,#ForeignId uniqueidentifier
AS
BEGIN
SET NOCOUNT ON
DECLARE #SQL nvarchar(4000) =
'INSERT INTO XmlTable(XmlId
, ForeignId
, TestXml)
SELECT NEWID()
, #ForeignId
,* FROM OPENROWSET(
BULK ''' + #path + ''',
SINGLE_BLOB) AS x;'
EXECUTE(#SQL);
RETURN ##ERROR;
END
When you're executing the SQL statement using EXECUTE(SQL) it has no access to the #ForeignId value
One way to solve this is to use sp_excuteSQL and do this instead of EXECUTE(#SQL);
DECLARE #ParmDefinition nvarchar(500);
SET #ParmDefinition = N'#ForeignId uniqueidentifier';
EXECUTE sp_executesql #SQL, #ParmDefinition, #ForeignId ;
You could also just concatenate the #ForeignId to your sql string but I can't recall if there are issues with that when using a uniqueidentifier

How to set morethan max size charecters in NVARCHAR(MAX),sql Server2005

I am using
declare #insertsql nvarchar(MAX)
--above #insertsql for sp_executesql takes only nvarchar as input
set #insertsql='--i am giving More than 10000 characters here -----'
EXEC sp_executesql #insertsql, N'#inXMLRequest XML OUTPUT', #inXMLRequest OUTPUT
how to insert morethan 10000 charecters in NVARCHAR(MAX) in sql server2005
can any one help please
Thanks in advance
This has happened to me when I use inline SQL statements instead of stored procs.
If you are hitting that ceiling, you may want to consider moving to stored procs.
The parameter that you use for the command to run in sp_executesql (#insertsql in your case) is NVARCHAR(4000) not NVARCHAR(MAX) so you are limited to a 4000 character dynamic SQL command.
If you are running out of space in the variable, you'll need to do some code re-factoring.
Thanks to All,
i got the answer
Insted of using SP_Executesql directly we Executing nvarchar variable
Above we Are preparing #insertsql nvarchar variable morethan 8000 characters and it is giving to sp_executesql like this
EXEC sp_executesql #insertsql, N'#inXMLRequest XML OUTPUT',#inXMLRequest OUTPUT
insted of above query replaced with below query
Exec ('DeClare #inXMLRequest XML SET #inXMLRequest='------above 8000 characters---')
Finally we will execute that nvarchar string and get out put
sp_executesql will accept an NVARCHAR(MAX) which can be longer than 4000, only it cannot be assigned all at once. It needs to be assigned 4000 characters in a single assignment statement and then appended as shown here:
declare #strSQL nvarchar(max)
--#strSQL + REPLICATE(' ', 5000)+' ''ERROR!'''
--exec sp_executesql #strSQL
SET #strSQL = N'SELECT'+ REPLICATE(' ', 3000)
SET #strSQL = #strSQL + REPLICATE(' ', 3000)+' ''This works'''
exec sp_executesql #strSQL
select LEN (#strSQL)