Could EXEC and Select Into work together? - sql

Im running following statement to get a result from remote server
EXEC ( #var) AT [linkedservername]
Note :
#var holds select query to run on linked server.
Linkedserver is DB2 server.
I would like to save the result into a temptable.
Is it possible ?
Can we achieve like below?
EXEC ( #var) AT [linkedservername] into #t
-- Updating to provider more info.
I came up to this,
read query from file.
execute it in desired DB2 server using linked server.
now i need to save it in a temptable
DECLARE #FileContents VARCHAR(MAX)
SELECT #FileContents=BulkColumn
FROM OPENROWSET(BULK'E:\ADDRESS.txt',SINGLE_BLOB) x;
set #FileContents = Replace(#FileContents,'''''','''')
set #FileContents = #FileContents + ' FETCH FIRST 1 ROWS only'
EXEC ( #FileContents) AT [linkedservername]
I Need something like below,
select * from (
EXEC ( #FileContents) AT [linkedservername] )

Updated for new information.
The answer is no for the way you're attempting to do it.
If you know the structure already, create the temp table first. You might have to change your RPC and DTC settings to get the call to work.
CREATE TABLE #temp
(<Table definition for your results>)
DECLARE #var VARCHAR(100)= 'your command'
INSERT INTO #temp EXEC (#var) AT TRANSACCOUNT
SELECT * FROM #temp
If the structure is unknown you, you can use OPENROWSET or OPENQUERY to generate the table on the fly.
Openquery:
SELECT *
INTO #temp FROM
OPENQUERY(targetServer, 'your command')
Openrowset:
SELECT * INTO
#temp
FROM
OPENROWSET(
'SQLNCLI',
'Server=targetServer;Trusted_Connection=yes;',
'your command'
)
SELECT * FROM #temp
OPENQUERY and OPENROWSET require string literals, so if you need to dynamically set your base command, you'd need to also build your OPENROWSET call. The context of the call would also change the context of any temporary table, so you could use a temporary permanent table to store your results like this:
DECLARE #var VARCHAR(100)= 'your command'
DECLARE #command VARCHAR(MAX)
SELECT #command = CONCAT(
'SELECT * INTO temporaryTable
FROM
OPENROWSET(
''SQLNCLI'',
''Server=targetServer;Trusted_Connection=yes;'',
''', #var,'''
)')
EXEC (#command)
SELECT * FROM temporaryTable

Related

Select into #temp table got an error

I have complicated store procedure and get the data into the #temp table that is worked fine. However when I filter the data from this temp table then I got the error, 'Invalid object name '#temp_2'. After the data in #temp_2 table, I also need to open into cursor. Would someone tell me how to solve it.
There is my script:
DECLARE #sql varchar(500)
IF #strLocations=''
SET #sql='SELECT * into #temp_2 from #temp_1'
ELSE
SET #sql='SELECT * into #temp_2 from #temp_1 t where t.Location_id in ( ' + #strLocations + ')'
EXEC (#sql)
select * from #temp_2
EXEC creates a new session to execute the statements. When the session ends, any local temporary tables created in it are destroyed (i.e. dropped). You will have to create the temporary table before your EXEC statement.

Avoid using dynamic from clause

How can i avoid using dynamic from clause? Even if i don't know the database name, i prefer to use a static statement, like this:
select *
into #tempTable
from #DBName.Invoices
where InvoiceId = 5.
I got this error: Msg 102, Level 15, State 1, Line 6
Incorrect syntax near '.'.
I need to use select into clause because the column names may be different from each databases;
Thanks!
Unfortunately you will have to use dynamic SQL for this, see below for an example
Declare #DBNAME NVARCHAR(MAX) = 'xxx'
Declare #SQL NVARCHAR(MAX) ='select *
into #tempTable
from ' + #DBName + '.Invoices
where InvoiceId = 5.'
execute sp_executesql #SQL
How can i avoid using dynamic from clause? Even if i don't know the database name, i prefer to use a static statement
SQL wont accept columnnames,tablenames,databasenames as parameters.so unless you you avoid them,you cant avoid dynamic sql..
Change your query to dynamic sql to avoid error..But again you will have a problem with temp tables scope
--This will fail ,because temp table falls under different scope
Declare #sql nvarchar(4000)
set #sql='
select *
into #tempTable
from #DBName.Invoices
where InvoiceId = 5'
---one option is to use global temp tables
declare #dbname varchar(1000)
set #dbname=db_name()
declare #sql nvarchar(4000)
set #sql='select *
into ##tempTable
from '+#DBName+'.dbo.test_Delete '
exec(#sql)
select * from ##temptable
But be carefull with above approach,since above temp table have global scope..
You also can use Openrowset ,some thing like below
select * into #temp from openrowset
('SQLNCLI','Server=yourinstancename;Trusted_Connection=yes;', 'select * form table')

How to access a database given a string of its name

Alright so say I have code that looks like this.
CREATE Table database_info
(
DBName NVARCHAR (MAX)
);
INSERT INTO database_info (DBName)
VALUES ('db1')
SELECT * FROM database_info
DECLARE #temp nvarchar(MAX)
SET #temp = (SELECT DBName FROM database_info where database_info.DBName = 'db1')
--How I want it to work SELECT * FROM #temp
Is there any kind of operation I could do on this temporary variable to have the string act as a regular SQL command?
Thanks
You may execute a dynamic sql using EXEC. Now, declaring the #sql variable would be quite too much in this case, but it is useful when you are not sure of the length of the statement you will pass to it.
DECLARE #sql AS VARCHAR(MAX)
SET #sql = 'SELECT * FROM ' + #temp
EXEC(#sql)

How to use a temporary table variable (e.g. #temp) for holding the result of sp_msforeachdb

I am basically trying to find out all the table of all the databases present in the SQL SERVER by using sp_msforeachdb.
If I write exec sp_msforeachdb 'select "?" AS DatabaseNames,* from [?].sys.tables'
I will get the result well but for every Database, a seperate record set will be created.
Now if I use
CREATE TABLE #DBINFO
(
DbName NVARCHAR(255)
,ObjectID NVARCHAR(255)
)
INSERT INTO #DBINFO
exec sp_msforeachdb 'select "?" AS DatabaseNames,ObjectID from [?].sys.tables'
SELECT * FROM #DBINFO
This works fine.
However, if I do
Declare #DBINFO Table(DbName NVARCHAR(255),ObjectID NVARCHAR(255))
INSERT INTO #DBINFO
exec sp_msforeachdb 'select "?" AS DatabaseNames,ObjectID from [?].sys.tables'
SELECT * FROM #DBINFO
It does not accept
Moreover, If I do
;With CTE AS
(
exec sp_msforeachdb 'select "?" AS DatabaseNames,* from [?].sys.tables'
)
Select * from CTE
, it throws error ( Presently I donot remember that).
Question is
1) Is it possible to do the same stuff using a table variable
2) Is it possible to get the same thing done using CTE?
SQL SERVER 2005.
Thanks
1) Yes, you just need to use the proper names for your columns (object_id, not ObjectID):
Declare #DBINFO Table(DbName NVARCHAR(255),ObjectID NVARCHAR(255))
INSERT INTO #DBINFO
exec sp_msforeachdb 'select "?" AS DatabaseNames,object_id from [?].sys.tables'
SELECT * FROM #DBINFO
2) No

How to SELECT FROM stored procedure

I have a stored procedure that returns rows:
CREATE PROCEDURE MyProc
AS
BEGIN
SELECT * FROM MyTable
END
My actual procedure is a little more complicated, which is why a stored procedure is necessary.
Is it possible to select the output by calling this procedure?
Something like:
SELECT * FROM (EXEC MyProc) AS TEMP
I need to use SELECT TOP X, ROW_NUMBER, and an additional WHERE clause to page my data, and I don't really want to pass these values as parameters.
You can
create a table variable to hold the
result set from the stored proc and
then
insert the output of the
stored proc into the table variable,
and then
use the table variable
exactly as you would any other
table...
... sql ....
Declare #T Table ([column definitions here])
Insert #T Exec storedProcname params
Select * from #T Where ...
You can use a User-defined function or a view instead of a procedure.
A procedure can return multiple result sets, each with its own schema. It's not suitable for using in a SELECT statement.
You either want a Table-Valued function or insert your EXEC into a temporary table:
INSERT INTO #tab EXEC MyProc
You need to declare a table type which contains the same number of columns your store procedure is returning. Data types of the columns in the table type and the columns returned by the procedures should be same
declare #MyTableType as table
(
FIRSTCOLUMN int
,.....
)
Then you need to insert the result of your stored procedure in your table type you just defined
Insert into #MyTableType
EXEC [dbo].[MyStoredProcedure]
In the end just select from your table type
Select * from #MyTableType
You must read about OPENROWSET and OPENQUERY
SELECT *
INTO #tmp FROM
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc #parameters')
It is not necessary use a temporary table.
This is my solution
SELECT * FROM
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc #parameters')
WHERE somefield = anyvalue
You can copy output from sp to temporaty table.
CREATE TABLE #GetVersionValues
(
[Index] int,
[Name] sysname,
Internal_value int,
Character_Value sysname
)
INSERT #GetVersionValues EXEC master.dbo.xp_msver 'WindowsVersion'
SELECT * FROM #GetVersionValues
drop TABLE #GetVersionValues
Try converting your procedure in to an Inline Function which returns a table as follows:
CREATE FUNCTION MyProc()
RETURNS TABLE AS
RETURN (SELECT * FROM MyTable)
And then you can call it as
SELECT * FROM MyProc()
You also have the option of passing parameters to the function as follows:
CREATE FUNCTION FuncName (#para1 para1_type, #para2 para2_type , ... )
And call it
SELECT * FROM FuncName ( #para1 , #para2 )
You can cheat a little with OPENROWSET :
SELECT ...fieldlist...
FROM OPENROWSET('SQLNCLI', 'connection string', 'name of sp')
WHERE ...
This would still run the entire SP every time, of course.
If 'DATA ACCESS' false,
EXEC sp_serveroption 'SQLSERVERNAME', 'DATA ACCESS', TRUE
after,
SELECT * FROM OPENQUERY(SQLSERVERNAME, 'EXEC DBNAME..MyProc #parameters')
it works.
Use OPENQUERY, and before execute set SET FMTONLY OFF; SET NOCOUNT ON;
Try this sample code:
SELECT top(1)*
FROM
OPENQUERY( [Server], 'SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE [database].[dbo].[storedprocedure] value,value ')
If you get the error 'Server is not configured for DATA ACCESS',
use this:
EXEC sp_serveroption 'YourServer', 'DATA ACCESS', TRUE
For the sake of simplicity and to make it re-runnable, I have used a system StoredProcedure "sp_readerrorlog" to get data:
-----USING Table Variable
DECLARE #tblVar TABLE (
LogDate DATETIME,
ProcessInfo NVARCHAR(MAX),
[Text] NVARCHAR(MAX)
)
INSERT INTO #tblVar Exec sp_readerrorlog
SELECT LogDate as DateOccured, ProcessInfo as pInfo, [Text] as Message FROM #tblVar
-----(OR): Using Temp Table
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp;
CREATE TABLE #temp (
LogDate DATETIME,
ProcessInfo NVARCHAR(55),
Text NVARCHAR(MAX)
)
INSERT INTO #temp EXEC sp_readerrorlog
SELECT * FROM #temp
It sounds like you might just need to use a view. A view allows a query to be represented as a table so it, the view, can be queried.
If your server is called SERVERX for example, this is how I did it...
EXEC sp_serveroption 'SERVERX', 'DATA ACCESS', TRUE;
DECLARE #CMD VARCHAR(1000);
DECLARE #StudentID CHAR(10);
SET #StudentID = 'STUDENT01';
SET #CMD = 'SELECT * FROM OPENQUERY([SERVERX], ''SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE MYDATABASE.dbo.MYSTOREDPROC ' + #StudentID + ''') WHERE SOMEFIELD = SOMEVALUE';
EXEC (#CMD);
To check this worked, I commented out the EXEC() command line and replaced it with SELECT #CMD to review the command before trying to execute it! That was to make sure all the correct number of single-quotes were in the right place. :-)
I hope that helps someone.