EXEC with an EXEC - sql

Is it possible to have an EXEC within an EXEC in SQL?
e.g. EXEC('EXEC ...')

In SQL Server, yes. try:
EXEC ('EXEC sp_helpdb')
or
EXEC ('EXEC (''EXEC sp_helpdb'')')

Yes. With an exec statement you can call any statement you could write into a Management Studio query batch including another exec statement.

Related

Using openrowset in SQL Server 2014

I have the below SQL statement that I was using to get data from a stored procedure into a temp table
SET #sql = N'SELECT * INTO #CustomTable3HTML
FROM
OPENROWSET(''SQLNCLI'',''Server='+ ##SERVERNAME +';UID='+#UserName+';PWD='+#Password+';Database=SalesDeals'',
''SET NOCOUNT ON;SET FMTONLY OFF;EXEC dbo.prGetDealProposalDetail ''''' + #DealID + ''''',''''' + #FeeType +''''''')
'
EXEC sp_executesql #sql
This was working fine in SQL Server 2008, but after the server got upgraded to SQL Server 2014, I started getting this error:
The metadata could not be determined because statement 'Insert #TempDetail exec prExcelCalculations_GetPricingSummary #Dealno,'FSA'' in procedure 'prGetDealProposalDetail' uses a temp table.
Which is because in the stored procedure I call in the Openrowset calls another procedure and uses temp tables..The columns are dynamic.
Can someone please let me know what can I do to fix it?

How to use 'use' command across all database to execute certain script in sql

I have a certain script which I need to execute across all databases in SQL Server. I have used the following logic to loop through all database excluding the system databases.
declare #DBName varchar(500)
DECLARE #Database_id int
DECLARE #Query varchar(MAX)
select #Database_id = MIN(database_id) from sys.databases where database_id>4
while #Database_id is not null
begin
select #DBName=name from sys.databases where database_id=#Database_id
set #Query = 'Use'+#DBName
--some script
Print ''+#DBName+''
exec (#Query)
select #Database_id = MIN(database_id) from sys.databases where database_id>4 AND database_id>#Database_id
end
But the problem is I can't use the 'Use' command with a variable. Is there any other way to make use of 'Use' command to hit the database?
And I don't want to use sp_MSforeachdb command as my query is too long.
Any help would be appreciated!
There is an undocumented function doing this. You can use the question mark in the place of the db's name:
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; EXEC sp_spaceused'
Find this example and more explanations here: http://weblogs.sqlteam.com/joew/archive/2008/08/27/60700.aspx
EDIT: From your comments above I find, that you do not want to includ the system dbs into your run. It seems to be q bit tricky to detect, whether a db is a system db or not but you could go like this:
DECLARE #cmd VARCHAR(1000)='USE [?];IF DB_ID(DB_NAME())<=4 RETURN;EXEC sp_spaceused;'
EXECUTE master.sys.sp_MSforeachdb #cmd;
GO
Read about the flaws here (about SQL Server 2005!): SQL Server: How to tell if a database is a system database?
If you don't like this <=4 you could simply do it like
IF DB_NAME() IN('master','model',... any more names here ... ) RETURN;
The only real restriction I know of is, that sp_MSforeachdb does not like "GO".

Error with OPENQUERY

I have this proble.
I should to call a Function at a LinkedServer database. So this database not show me a Function.
For this I use this code:
BEGIN
DECLARE #TSQL varchar(8000)
DECLARE #Data as DATE
SET #Data = GETDATE()
SET #TSQL = 'SELECT PIPPO FROM OPENQUERY([SQLIMELTC\IMELTCPROD],''SELECT [FlexNet].[dbo].[AF_GetUTCToLocal] (''''' +CAST(#Data AS NVARCHAR(100))+ ''''') AS PIPPO'' )'
EXEC #TSQL
END
I have this error:
Msg 203, Level 16, State 2, Line 10
The name 'SELECT PIPPO FROM OPENQUERY([SQLIMELTC\IMELTCPROD],'SELECT [FlexNet].[dbo].[AF_GetUTCToLocal] (''2015-01-08'') AS PIPPO' )' is not a valid identifier.
But, if I try to use this code before the instruction
EXEC #TSQL
and use it:
SELECT #TSQL
And after the execute I select in output box the result and execute it, it works.
What is my problem?
Look at the EXECUTE (Transact-SQL) syntax. When you use the variable you should use it in brackets.
Try this:
EXEC (#TSQL)
You need to put parenthesis around #TSQL, e.g.
EXEC (#TSQL);
EXEC without parenthesis is for executing stored procedures. e.g.
DECLARE #TSQL VARCHAR(8000) = 'sp_lock';
EXEC #TSQL;
Will execute the stored procedure sp_lock
Better still use sp_executesql, thus avoiding ambiguity:
EXECUTE sp_executesql #TSQL;

Table doesn't exist error when execuitng dynamic sql with sp_executesql

If I open a connection to a database, for example, with SSMS, and I run a query like this:
SELECT * FROM MySchema.MyTable
the query is executed without error.
If I run it as dynamic sql like this
declare var #qry nvarchar(200);
set #qry = N'SELECT * FROM MySchema.MyTable'
exec master.sys.sp_executesql #qry
I get an error stating that the table doesn't exist.
If I put the database name prefix before MySchema.MyTable name, i.e. MyDb.MySchema.MyTable the query runs correctly.
How can I avoid the error without specifying the database name in the dyanmic SQL?
try this!
change this
exec master.sys.sp_executesql #qry
to
exec sp_executesql #qry
or
exec #qry
Both answers by Recursive and koushik veldanda work fine, but this gives a deeper insight to the problem:
The problem is that executing a query with
exec master.sys.sp_execute_sql #qry
changes the context to the master database, so MySchema.MyTable is not accesible, because it doesn't belong to master, but to MyDb.
If the query is executed with
exec sys.sp_execute_sql #qry
the context is maintained in the current database, so the table is accesible, and the query runs without problem.
Use
exec #sql
is enough if there are any output parameters then go with
exec sp_executesql

Execute sybase stored procedure as linked server procedure sql server 2008

EDIT
The final goal is to call a stored procedure hosted in sybase with input and output parameters from SQL Server 2008 via Linked Server
I think title is pretty clear.
My goal is to execute a stored procedure hosted in Sybase SQL Anywhere 8 in SQL Server 2008 through the linked server I already created.
Any SQL query made through the linked server is working.
In addition I was able to execute a function but I don't now how to get the return value like that
EXEC ('CALL "dbname"."procedurename"(''param1'', ''param2'', ''param3'')') AT LinkedServerAlias;
Thanks 4 all your help!
Mauro
can you use four part naming convention?
like
exec LinkedServerName.dbname.dbo.procedurename #param1, #param2, #param3
I was finally able to do it by calling
SELECT * FROM OPENQUERY([LinkedServer], 'SELECT "dbname"."spname"(#p1,#p2, #p3)')
I'll add comments and example as soon as I experiment it.
4 part object names are valid only for SQL Server linked servers.
You have to have your EXEC inside an OPENQUERY
SELECT * FROM OPENQUERY([LinkedServer], 'EXEC MyDB.MyScheme.MyProc.spname #p1, #p2, #p3')
Now, you can't parametrise OPENQUERY calls so you have use dynamic SQL
DECLARE #sql nvarchar(4000), #linkedsql nvarchar(4000)
SET #sql = 'EXEC MyDB.MyScheme.MyProc.spname ' + CAST(#p1value as int) + ...
SET #linkedsql = 'SELECT * FROM OPENQUERY(LinkedServer, ''' + #sql + ''')'
EXEC (#linkedsql)