Welcome to EMC Consulting Blogs Sign in | Join | Help

Jim 2.0

SQL Server 2005: Passing variables into an OPENQUERY argument

Today I ran into a blocker when trying to do this. Having spent a reasonable amount of time taking all of my sql statements out of the OPENQUERY argument and putting them into a string variable I then found it didn't work. The reason (from BOL) it turns out is that, and I quote; "OPENQUERY does not accept variables for its arguments."

Why this is the case I haven't been able to find out so far, however there is a workaround I have discovered with thanks to this forum.

First, let's look at the statement I started with: Here I have a simple openquery statement to select everything from the table named 'Atable' in an Oracle database named 'OracleDB' (we're assuming a linked server has already been set up), for records since June 1st 2007.

select  *

into    MyTable

from    openquery    (    OracleDB

                     ,    'select  *

                          from     Atable

                          where    DateValue >= to_date(''20070601'', ''YYYYMMDD'')'

                     )

 

What I wanted to do was make the date sent to the Oracle database a variable so I could easily change it, so I declare this variable above the query and use it in the argument.

 

declare @TheDate     datetime

set     @TheDate =   '2007-06-01T00:00:00'

 

select  *

into    MyTable

from    openquery    (    OracleDB

                     ,    'select  *

                          from     Atable

                          where    DateValue >= to_date(''' + convert(varchar(30),@TheDate,120) + ''', ''YYYY-MM-DD HH24:MI:SS'')'

                     )

 

This doesn't work however, because . . . "OPENQUERY does not accept variables for its arguments." (See above).

The next step therefore is to put the select statement to be sent to the Oracle database in a string variable and use the date variable within this string. The variable '@MyString' is then used in the OPENQUERY statement.

 

declare @TheDate     datetime

,       @MyString    varchar(max)

set     @TheDate =   '2007-06-01T00:00:00'

set     @MyString =  'select  *

                     from     Atable

                     where    DateValue >= to_date(''' + convert(varchar(30),@TheDate,120) + ''', ''YYYY-MM-DD HH24:MI:SS'')'

 

select  *

into    MyTable

from    openquery    (    OracleDB

                     ,    @MyString

                     )

 

This again does not work however, because we are still trying to use a variable as an argument in the OPENQUERY statement, so now the trickery begins!

 

Immediately after setting the string variable as the select statement, it is then set again as the entire sql statement we are trying to execute, with the previously defined string used as an argument in the new string. Note that 'N' is used preceeding the string value to convert the tring to Nvarchar to eliminate any confusion around special characters.

 

This string is then executed without error because all variables have been converted by this point. I have included a print command in order to verify the statement that is executed, which is useful for debugging.

 

declare @TheDate     datetime

,       @MyString    varchar(max)

set     @TheDate =   '2007-06-01T00:00:00'

set     @MyString =  'select  *

                     from     Atable

                     where    DateValue >= to_date(''' + convert(varchar(30),@TheDate,120) + ''', ''YYYY-MM-DD HH24:MI:SS'')'

set     @MyString =  N'select    *

                     into        MyTable

                     from        openquery    (    OracleDB

                                              ,    ''' + REPLACE(@MyString, '''', '''''') + '''

                                              )'

 

print   @MyString

 

EXEC    (@MyString)

And that's how you get more cowbell from OPENQUERY

James

Published 28 June 2007 17:32 by James.Pipe

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

OraTransplant » Log Buffer #51: a Carnival of the Vanities for DBAs said:

June 29, 2007 17:02
 

Don't fear the reaper said:

I was struggling with parameters in openquery until you shared this sweet cowbell action...thanks!

August 29, 2007 17:51
 

Starry said:

thanks alot. It sweet...

September 10, 2007 20:53
 

Rick said:

Nicely done!

September 28, 2007 16:56
 

Richard said:

After loads of searching on the web, and even more Trial and Error, this single page has solved all my problems. Brilliant!  

October 9, 2007 10:36
 

Thomas Mathiesen said:

Thank you very much.

Simple, yet very effective :)

October 19, 2007 12:47
 

Hrudhay said:

After tons  of searching on the web ,finally you shown me the path to solve the issue.

November 15, 2007 09:36
 

Dhaval said:

Same as everyone else, this solved the issue, easy to follow through your logic.

December 7, 2007 21:32
 

Jesse said:

Thank you for posting this, I just slammed into this very problem and was wondering what was going on.  Thanks for saving me lots of time!

December 19, 2007 12:27
 

Ranjan said:

Thanks a lot Jim. Was working hard to sort out the issue but thought that all my hard work went in vain then saw your blog and was successful in reaching the output.

Thanks a ton,

Ranjan

January 8, 2008 10:59
 

Geoffrey said:

I want to add an extra "feature" to this behavoir.

When you want to use output parameters.

Then you need to use sp_executesql.

ExamplE:

declare @sql nvarchar(500)

declare @param nvarchar(100)

declare @Cnt int

declare @docNr int

set @docNr = 123

set @sql = 'Select @Cnt = count(*) from openquery(LINKEDSERVER, ''select 1 from table where  nr_entry = ' + cast(@docNr  as varchar(20)) + ''')'

set @param = '@Cnt int output'

exec sp_executesql

@sql,

@param,

@Cnt output

print @Cnt

February 14, 2008 13:45
 

Sasha said:

Thanks for the information on using OpenQuery.  I have made an attempt at implementing the logic where the linkedserver is going to an ADS database.  However I am still getting an error message that the column is not found and it highlights my variable as if it were the column name.  I need another pair of eyes to help me in finding out what the issue is with my query.

See my query below:

declare @strCompanyNum varchar(20)

declare @strSQL varchar(max)

set @strCompanyNum = (select MIN(companynum) from dbo.tCRMClient)

set @strSQL = 'SELECT

COMPANYNUM,

NAME,

RecStat,

LTR_NAME,

ADDRESS1,

ADDRESS2,

CITY,

STATE,

ZIP,

GP_CODE,

L_UPD

FROM

company

WHERE COMPANYNUM = @strCompanyNum'

set @strSQL = 'select

*

from openquery(QuestSource, ''' + REPLACE(@strSQL, '''', '''''') + ''')'

print @strSQL

exec (@strSQL)

Error Message:

OLE DB provider "MSDASQL" for linked server "QuestSource" returned message "[Extended Systems][Advantage SQL][ASA] Error 7200:  AQE Error:  State = S0000;   NativeError = 2121;  [Extended Systems][Advantage SQL Engine]Column not found: @strCompanyNum -- Location of error in the SQL statement is: 212 (line: 15 column: 24)".

Msg 7321, Level 16, State 2, Line 1

An error occurred while preparing the query "SELECT

COMPANYNUM,

NAME,

RecStat,

LTR_NAME,

ADDRESS1,

ADDRESS2,

CITY,

STATE,

ZIP,

GP_CODE,

L_UPD

FROM

company

WHERE COMPANYNUM = @strCompanyNum" for execution against OLE DB provider "MSDASQL" for linked server "QuestSource".

March 3, 2008 20:13
 

Miguel Lima said:

Really cool! Thanks for that.

Cheers,

Miguel

March 28, 2008 00:38
 

Mike said:

Thanks, That works a treat.

Cheers

Mike

April 2, 2008 11:51
 

Owen said:

There's a nice summary of the solutions to be found at: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q314520

April 25, 2008 11:34
 

~~arg said:

this page is really, really, really helpful!!!ü

thanks a lot for sharing it..

May 23, 2008 02:13
 

Carlos Casaverde said:

Thanks for your help. Your solution is great!!

June 16, 2008 23:37
 

openquery said:

July 1, 2008 14:52
 

Blue Oyster Cultist said:

thanks for posting. great help

September 9, 2008 14:16
 

John Wakefield said:

Really useful. A very clear explanation.

September 18, 2008 11:30
 

Hey said:

Great Job James!!! Cheers

September 25, 2008 23:42
 

Eric Hrnicek said:

SOOOO much better than microsoft's examples. I beat on those for an hour without success. I modified this to my situation and had my query working in less than 10 minutes to a nasty H.T.E. database on an AS400.  THANKS!

October 9, 2008 16:48
 

Lenys said:

T.H.A.N.K.S!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

October 16, 2008 20:22
 

Terry said:

My openquery (with parms) to Oracle linked server now works.

Being a beginner I just mimic'ed what you did because I don't quite understand it.

But it works.

Thanks

November 10, 2008 17:30
 

John said:

This find was great! I'v been working to get something like this for a long time.

Thanks!

March 26, 2009 15:43
 

John said:

I don't know if anyone could use this, but here is the stored procedure that I made from Jim's article above. It retrives information for a user from the Active Directory through SQL.

Thanks again Jim

---------------------------------------------------------

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

Create PROCEDURE get_active_directory_user_info

@UserName varchar(100)

AS

Declare

@N varchar (100),

@Q varchar(max)

Set @N ='''' + @UserName + ''''

Set @Q = 'select sn,

givenName,

initials,

displayName,

telephoneNumber,

mail,

streetAddress,

l,

st,

adspath

From ''''LDAP://cn=Computers,dc=NA,dc=yourdomain,dc=com''''

   Where sAMAccountName = ''' + @N +

''' and objectclass = ''''user'''''')'

Set @Q = N'select sn AS LastName,

givenName AS FirstName,

initials AS MiddInitial,

displayName AS DisplayName,

    telephoneNumber AS Phone,

mail AS EMail,

streetAddress AS Address,

l AS City,

st AS State,

adspath AS Path

From OPENQUERY(ADSI,''' + REPLACE(@Q, '', '''''''') + ' AS Rowset_1'

Exec (@Q)

------------------------------------------------------

March 26, 2009 16:02
 

Eralper said:

Hello James,

Actually you are creating a dynamic sql statement and passing the resultant sql code to the OPENQUERY, isn't it?

I need to get parameter values out from the openquery like executing a stored procedure like output parameters.

But as far as I know this is not possible, only work arounds is not it?

Thanks,

Eralper

March 31, 2009 08:50
 

Hee said:

you are the best!!!

April 7, 2009 09:18
 

Mehul said:

simply superb... :)

April 30, 2009 22:33
 

John said:

You are awesome.

May 26, 2009 06:48
 

Joe said:

Amazing! worked like a charm. You are a genius

May 29, 2009 12:29
 

nrao said:

Great!!! Thanks.

May 29, 2009 16:42
 

Paul said:

Helped me out!

July 1, 2009 20:39
 

Javacrazy (blog.manager@gmail.com) said:

Can use your information in my blog?

July 29, 2009 21:01
 

Brian from Ireland said:

Nice piece of work Jim and well explained.

Go raibh maith agait (thanks!)

August 25, 2009 11:44
 

HC said:

Excelente explicación y funcional

October 5, 2009 22:49
 

Joshua from TN said:

GOtta say... this page is on the my faves and thought I do not use if often, it is a great little work around.  Thanks Jim!

October 7, 2009 23:38
 

sheeptick said:

Thank you - very ingenious, and very helpful.

October 29, 2009 11:58
 

Denny said:

Fantastic!

December 11, 2009 17:52
 

Tessa said:

@Geoffrey You saved my schoolproject! Thanks! *smile*

January 4, 2010 03:09
 

Chicken said:

Just wanted to echo everyones comments, you solution solved my issue! Thank you for posting it!!!!

btw, 'cowbell' referecne was great!

January 11, 2010 22:01
 

me said:

this was perfect! James you are awesomeness

January 15, 2010 00:50
 

sandip patel (sandip@milestoneintenet.info) said:

great work :)

April 5, 2010 12:24
 

Pete Haas said:

Ahh, been looking for this for a long time.  Very thankful for the post.  

June 4, 2010 18:45
 

Sameer Chachad said:

This worked for me too ...

Thanks for the wonderful solution.

June 17, 2010 12:35
 

Tim Woolley said:

Works Great!

July 22, 2010 04:14
 

Shivshankar said:

thanks dear.

Ur given solution helped me a lot.

declare @TheDate     datetime

,       @MyString    varchar(max)

set     @TheDate =   '2007-06-01T00:00:00'

set     @MyString =  'select  *

                    from     Atable

                    where    DateValue >= to_date(''' + convert(varchar(30),@TheDate,120) + ''', ''YYYY-MM-DD HH24:MI:SS'')'

set     @MyString =  N'select    *

                    into        MyTable

                    from        openquery    (    OracleDB

                                             ,    ''' + REPLACE(@MyString, '''', '''''') + '''

                                             )'

print   @MyString

EXEC    (@MyString)

And that's how you get more cowbell from OPENQUERY

August 26, 2010 12:49
 

Scott S said:

Any ideas how you could stuff that into a FUNCTION? That way I could use it on a Linked Server with about 300 DB and pass two parms. One the DB name and One the Table name and use like Select * from mylinkedservername('DBName','tablename')  

September 10, 2010 19:49
 

Darren said:

RE: "Any ideas how you could stuff that into a FUNCTION?"

I've been trying to find a way to do this for some time now.

I beleive the reason you can't is because there is no such thing as "late binding" inside a database. Meaning the returned table can potentially be any format for the column definitions and that the table valued functions must return based on a single select statement (output format is known) or define a return "Table" variable (output format also known)

Possibly a .NET based function can do it?

November 3, 2010 15:45
 

Abascus said:

Truly amazing !!

Thanks a bunch,

Abascus

November 18, 2010 17:17
 

Jude said:

Hi Jim,

A big THANK YOU for sharing this!

January 10, 2011 10:02
 

Eric L said:

RE: "Any ideas how you could stuff that into a FUNCTION?"

I've been working on a way to do this for a long time too.  With no luck.

Can't use EXEC inside a FUNCTION.  

January 14, 2011 21:47
 

Alex Paverman said:

You're the best, Jim! Grand THANKS for the solution!!

February 17, 2011 06:39
 

Abdul Jaleel said:

Great Post. Very nice trick. Thanks alot.

June 15, 2011 12:22
 

Abdul Mannan said:

Realy Great tricky solution.Very helpful.. Thanks a lot..

June 24, 2011 07:39
 

Rosh said:

Thanks mate - did the trick ..

August 23, 2011 14:15
 

Hector said:

Hugeeee help, nice post, thanks!!!

October 5, 2011 19:30
 

ravi said:

USE [EyeSense1]

GO

/****** Object:  StoredProcedure [dbo].[USP_GetCustomerBalence]    Script Date: 10/20/2011 10:35:04 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

--(SELECT IdCustomer FROM CustomerMaster WHERE Phone Like'25540005%')

ALTER PROCEDURE [dbo].[USP_GetCustomerBalence]

(

@mobile NVARCHAR(15)

,@firstname NVARCHAR(50)

,@lastname NVARCHAR(50)

,@spousename NVARCHAR(50)

,@birthday VARCHAR(50)

,@offcity NVARCHAR(50)

,@offpincode NVARCHAR(50)

,@resicity NVARCHAR(50)

,@resipincode NVARCHAR(50)

,@emailid NVARCHAR(300)

,@telno NVARCHAR(15)

,@offaddress NVARCHAR(50)

,@resiaddress NVARCHAR(50)

)

AS

BEGIN

DECLARE @STRQUERY1 AS VARCHAR(1500)

DECLARE @STRQUERY2 AS VARCHAR(1500)

DECLARE @STRQUERY3 AS VARCHAR(1500)

DECLARE @STRQUERY4 AS VARCHAR(5000)

DECLARE @birthday1 AS NVARCHAR(1500)

SET @STRQUERY2=''

SET @STRQUERY1=('SELECT IdCustomer FROM CustomerMaster WHERE ')

IF(@mobile IS NOT NULL)

BEGIN

SET @STRQUERY2=(@STRQUERY2 + ('Mobile Like'''+ @mobile + '%' + + '''') + ' AND '  )

END

IF(@firstname IS NOT NULL)

BEGIN

SET @STRQUERY2= (@STRQUERY2 + ('FirstName Like'''+ @firstname + '%' + + '''') + ' AND ' )

END

IF(@lastname IS NOT NULL)

BEGIN

SET @STRQUERY2= (@STRQUERY2 + ('LastName Like'''+ @lastname + '%' + + '''') + ' AND ' )

END

IF(@spousename IS NOT NULL)

BEGIN

SET @STRQUERY2= (@STRQUERY2 + ('SpouseName Like'''+ @spousename + '%' + + '''') + ' AND ' )

END

IF(@birthday IS NOT NULL)

BEGIN

SET @birthday1=CONVERT(NVARCHAR(50),@birthday,100)

SET @birthday1=SUBSTRING(@birthday1,1,(LEN(@birthday1)-7))

SET @STRQUERY2= (@STRQUERY2 +('DOB Like'''+ @birthday1 + '%' + + '''') + ' AND ' )

END

IF(@offcity IS NOT NULL)

BEGIN

SET @STRQUERY2=(('CityWork Like'''+ @offcity + '%' + '''') + ' AND '  )

END

IF(@offpincode IS NOT NULL)

BEGIN

SET @STRQUERY2=(@STRQUERY2 + ('PincodeWork Like'''+ @offpincode + '%' + + '''') + ' AND '  )

END

IF(@resicity IS NOT NULL)

BEGIN

SET @STRQUERY2=(@STRQUERY2 + ('CityResi Like'''+ @resicity + '%' + + '''') + ' AND '  )

END

IF(@resipincode IS NOT NULL)

BEGIN

SET @STRQUERY2=(@STRQUERY2 + ('PinCodeResi Like'''+ @resipincode + '%' + + '''') + ' AND '  )

END

IF(@emailid IS NOT NULL)

BEGIN

SET @STRQUERY2=(@STRQUERY2 + ('EmailId Like'''+ @emailid + '%' + + '''') + ' AND '  )

END

IF(@telno IS NOT NULL)

BEGIN

SET @STRQUERY2=(@STRQUERY2 + ('Phone Like'''+ @telno + '%' + + '''') + ' AND '  )

END

IF(@offaddress IS NOT NULL)

BEGIN

SET @STRQUERY2=(@STRQUERY2 + ('AddressWork Like'''+ @offaddress + '%' + + '''') + ' AND '  )

END

IF(@resiaddress IS NOT NULL)

BEGIN

SET @STRQUERY2=(@STRQUERY2 + ('AddressResi Like'''+ @resiaddress + '%' + + '''') + ' AND '  )

END

SET @STRQUERY3=SUBSTRING(@STRQUERY2,1,(LEN(@STRQUERY2)-3))

SELECT @STRQUERY3

SET @STRQUERY4=SUBSTRING(@STRQUERY3,1,(LEN(@STRQUERY3)-3))

--SELECT @STRQUERY4 AS STRQUERY

--PRINT (@STRQUERY4)

--EXEC (@STRQUERY1+@STRQUERY3)

SELECT IdJobCard,IdCustomer,Balence FROM JobCardMaster WHERE IdCustomer=( @STRQUERY4)

END

October 20, 2011 06:08
 

ALI SAMAVATI said:

LIKE

October 31, 2011 20:16
 

Oh Yeah said:

Thanks!!!!!! ;)

February 1, 2012 09:07
 

life quotes said:

excellent piece of information, I had come to know about your website  from my friend kishore, pune,i have read atleast 8 posts of yours by now, and let me tell you, your site gives the best and the most interesting information. This is just the kind of information that i had been looking for, i'm already your rss reader now and i would regularly watch out for the new posts, once again hats off to you! Thanx a lot once again, Regards, <a href="http://lifequotes99.com">life quotes</a>

February 9, 2012 09:50
 

Neha said:

Perfect.. Finally found something that works

February 23, 2012 05:55
 

Ninz said:

execellent piece of information

February 23, 2012 06:14
 

Kusum said:

Excellent information!!! Worked like a charm!!!

Thanks a lot for posting this!

April 5, 2012 05:47
 

Garrett Fitzgerald said:

I don't believe this just worked. :-) Thank you! I used it to pass a date in to a Crystal Reports SQL command -- just replaced @TheDate with {?TheDate}, and it ran fine. :-)

April 13, 2012 20:53
 

Jason said:

Thank you for this method of getting around OPENQUERY limitations!  

April 26, 2012 15:16
 

sqlquery said:

Thanks, but all turned into generating dynamic sql command using string concatenation :(

May 17, 2012 11:28
 

Dr. Tony said:

I'm using this with SSRS on SQL 2008 R2. It took me a while to make it work because my query is almost 1000 characters long with lots of single quotes, but it's good now. Thank you very much for a lifesaving tip.

May 17, 2012 21:22

Leave a Comment

(required) 
(optional)
(required) 
Submit
Powered by Community Server (Personal Edition), by Telligent Systems