I have a temp table where I want to store the results of a stored procedure. To execute the stored procedure, I need to use variable values for the Database name, Database Server, and Stored Procedure name that are stored in a table. I need to work out how to write the SELECT * INTO using the OPENROWSET with my variables. This is what I have so far but there are syntax errors:
SELECT * INTO #tmpAccountsRetrieved
FROM OPENROWSET(#TempDbName, 'Server=' + #TempDbServer + ';Trusted_Connection=yes;', 'EXEC ' + #TempStoredProcName)
I'm pretty rusty on SQL so any help is much appreciated!
Try to put these configurations in place before using openRowset:
-- FOR USING OPENROWSETS
EXEC sp_configure 'Ad Hoc Distributed Queries'
,1
RECONFIGURE
I think your syntax is correct.
So just Try to Go through this POST for more help
Related
I have a set of SQL queries that need to be run against 3 databases, they are stored on 2 different servers that have been linked.
All 3 databases have the the exact same tables and tables name, however the database names are different.
The queries have been written and all use just table names not the full database.dbo.table syntax so I can't use an automated find and replace on "linked.database1" to "linked.database2"
All the queries will always be executed through one server "Server1"
I'm trying to come up with a method of passing the queries to one of the linked servers but have a "use" command go through as it means I only have to change the database in the "use" line.
So far I have tried the following from Server1:
Select * from [Linked].Database.DBO.Table - Successful
Exec ('Select * from [Linked].Database.DBO.Table') - Successful
Direct on Server2 (using the account the linked server operates on):
EXEC ('Use Database; SELECT * from Table') - Successful
So with these above three I can ascertain
The login on Server1 can reach the databases needed and can access the data with a basic select and when passed with and Exec command.
The account on Server2 can run the Exec command and passing the "Use Database" line with Exec works on Server2.
However when I try using the below:
Select * from openquery ([Linked], 'Exec (Use Database; Select * from Table)')
I get the following error:
OLE DB provider "SQLNCLI10" for linked server "172.20.11.123" returned message "Deferred prepare could not be completed.".
Msg 8180, Level 16, State 1, Line 7
Statement(s) could not be prepared.
Msg 102, Level 15, State 1, Line 7
Incorrect syntax near ')'.
Msg 156, Level 15, State 1, Line 7
Incorrect syntax near the keyword 'Use'.
Have I messed up the syntax anywhere in the OpenQuery or can the USE command never be passed through OpenQuery.
If what I'm trying to do with OpenQuery and USE isn't possible then is there a way of passing the database you want the OpenQuery run against in the statement?
Or as a second thought, is there a way of putting together the Linked Server account so that it uses a particular database as its default database?
No, the way to do this, as far as I can tell, if you know which database you need to execute against:
DECLARE #database sysname = N'Database1';
DECLARE #sql nvarchar(max) = N'SELECT * FROM dbo.Table;';
DECLARE #exec nvarchar(4000) = N'[Linked].'
+ QUOTENAME(#database) + N'.sys.sp_executesql';
EXEC #exec #sql;
I'm not quite sure what this was trying to accomplish:
Select * from openquery ([Linked],
'Exec (Use Database; Select * from Table)')
But if you take out from that what you're trying to tell [Linked] to EXEC, it's this:
Exec (Use Database; Select * from Table)
Try that anywhere. Broken. You might get it to work like this, as #AlwaysLearning suggested:
Select * from openquery ([Linked],
'Exec (''Use Database; Select * from Table'')')
...but that's kind of, like, really gross, compared to the solution at the top. Unless you absolutely need to select from openquery for some reason.
I am attempting to query data from our Oracle server via our SQL server. To perform this in a thin-client manner, I am using OpenQuery. I would like to build a single table-based function that can be used to query various linked tables as needed. I can't quite figure out the syntax to make this work. Here is what I have so far. Any help is greatly appreciated!
CREATE FUNCTION [dbo].[fnTEST](
#Table varchar (100),
#Fields varchar (1000),
#Condition varchar(5000)
)
RETURNS
#TEST TABLE()
AS
BEGIN
DECLARE #OPENQUERY nvarchar(4000);
DECLARE #TSQL nvarchar(4000);
SET #OPENQUERY = 'SELECT * FROM OPENQUERY([TEST-Link],'''
SET #TSQL = 'SELECT ' + #Fields + ' FROM TEST.' + #Table + ' WHERE ' + #Condition + ''')'
EXEC (#OPENQUERY+#TSQL)
END;
The error I am currently getting is:
Msg 102, Level 15, State 1, Procedure fnTEST, Line 12 [Batch Start Line 7]
Incorrect syntax near ')'.
Highlighted at #TEST TABLE()
This is all not recommended for a number of reasons, but here the big one is that, as indicated in the MS doc, you cannot use dynamic SQL from a user-defined function:
Before You Begin
Limitations and restrictions
...
User-defined functions cannot make use of dynamic SQL or temp tables. Table variables are allowed.
...
Here are some of the other problems with this approach:
Your dynamic SQL is injectable. You should never use dynamic SQL unless you understand what SQL Injection is and how to prevent it in your dynamic SQL code.
Using dynamic sql has potential security requirements and restrictions. In this case the dynamic SQL may not have the same rights as your account and may not be able to use an OPENQUERY.
The nature of Database and Server Trustworthy settings may block this anyway.
IMHO, OPENQUERY is not recommended (some disagree), and remote queries are better handled with Linked Servers and the Remote EXEC command.
You are trying to write a "Universal Query" here. Universal Queries are generally not a good idea and have security problems, even after you fix the SQL Inject issues. It's better to define the specific queries needed by your app and code them as stored procedures and/or fixed queries using parameters only for WHERE conditions.
A SQL Function is not the right place for all of this anyway. You should regard a SQL table function as akin to a View, but with parameters for your WHERE clause. You should not treat it as a way to magically do anything.
The way that I would do something link this is as follows:
Define the explicit queries/datasets that your app needs from the Oracle Database.
Write those queries as stored procedures, on the Oracle database.
Setup a Linked Server definition in your SQL Server database to the Oracle database. Configure the security for each side appropriately.
Write specific stored procedures on your SQL Server to call the corresponding procedures in the Oracle database. Use remote EXEC's to do this through the Linked Server definition.
(NOTE: Remote EXEC execution is done with the AT <linkedServer> clause).
Enable the linked server for rpc out and simplify this to
EXEC (#sql) at [TEST-Link]
I'm wondering if there is a easy way to get a create table syntax for stored procedure's return.
For example we have a stored proc:
CREATE PROCEDURE [dbo].[usp_branches]
AS BEGIN
select * from branches
END
and then I need something like this
insert into #tempBranches
exec usp_branches
Is there a way that I can easily get create table syntax from stored procedure's return? So for this example I will get this
DECLARE #tempBranches TABLE
(
BranchID int
,BranchName varchar(25)
)
In SQL Server 2012, yes. There is new functionality that will retrieve metadata based on an ad hoc SQL string or an object name (see https://sqlblog.org/2010/12/20/sql-server-v-next-denali-metadata-enhancements for more details on that).
In earlier versions (you forgot to tell us which version), there are some less reliable workarounds. e.g.
SELECT * INTO #table FROM OPENROWSET('SQLNCLI',
'Server=(local);Trusted Connection=Yes;',
'EXEC yourdatabase.dbo.usp_branches;');
In order to do this you will first need to say:
EXEC sp_configure 'show adv', 1;
RECONFIGURE WITH OVERRIDE;
GO
EXEC sp_configure 'ad hoc dist', 1;
RECONFIGURE WITH OVERRIDE;
GO
Now you can build the CREATE TABLE statement based on tempdb.sys.columns where name LIKE '#table%';. Or safer where [object_id] = OBJECT_ID('tempdb..#table');.
Just keep in mind that like the new metadata functionality, if there is more than one resultset (or the shape can change depending on the input), all bets are off.
I have a query in a stored procedure that needs to be executed on different servers and databases according to some parameters.
How can I do this without using neither exec, nor sp_executesql?
I'm using SQL Server 2008.
Thank you.
UPDATE
I've found some links
http://www.eggheadcafe.com/software/aspnet/29397800/dynamically-specify-serve.aspx
http://www.sommarskog.se/dynamic_sql.html
Is using SYNONYM possible solution? If yes, than how?
UPDATE 2
I forgot to mention that all this servers are linked to the server where stored procedure is stored.
UPDATE 3
OPENROWSET or OPENDATASOURCE are not accessible either. I need a solution without building query string concating server name, schema name, db name.
It surely can be done by using if or case in stored procedure, but if we have 37 variations, then it's not a good solution.
Any other suggestions?
Nobody wants to answer, so I'll do it myself, just to have accepted answer.
There's isn't any way to do this. You need to use one of specified suggestions, anyway the query must be generating by concatenating.
Does OPENROWSET or OPENDATASOURCE help?
EDIT: If it works, you can change the database at runtime & execute the query using the present connection. I cannot see any other way of executing query the way you want.
What is wrong with running query using string i.e dynamic query?
/* DO THIS FOR EACH TABLE IN THE PROCEDURE*/
--BEGIN TABLE_1
DECLARE #LINKEDSERVER AS VARCHAR(50)
SET #LINKEDSERVER = DBO.FN_RETURN_SERVER('SBROUBLES')
DROP SYNONYM MYLINKEDSERVER
EXEC (' CREATE SYNONYM MYLINKEDSERVER FOR ' + #LINKEDSERVER + 'ANYDB.DBO.ANYTABLE')
--- END TABLE_1
-- UTILIZATION
SELECT COUNT(*) FROM MYLINKEDSERVER
--AND FN_RETURN_SERVER COULD BE ANY SELECT CASE ON SQL AS WELL
I wish to do the following:
select * into tmptbl from sometable
EXCEPT 'sometable' is a stored procedure that returns a result set AND editing the stored procedure to suit my goal is not an option. ALSO i may or may not know the columns and types of what the procedure returns.
Basically i am looking for a proper way of doing this:
select * into tmptbl from exec someSP
Is this even possible, if so, how?
yes it is possible with a loopback query like this
SELECT * INTO #tmptbl
FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;'
,'set fmtonly off exec DatabaseName.dbo.someSP')
More example here: Store The Output Of A Stored Procedure In A Table Without Creating A Table
Be aware that this has to be turned on first, see here: How to enable xp_cmdshell and Ad Hoc Distributed Queries on SQL Server 2005