Is it possible to execute a sql statement containing variable? - sql

Is it possible to execute a sql statement containing variable?
DECLARE #SCHEMA varchar(40)
set #SCHEMA='X_SLF'
select * from #SCHEMA..Acc_tblCompany --// anyway to use this type of statement?
--below statement works
select * from X_SLF..Acc_tblCompany
--I don't want to do this following solution:
DECLARE #Sql nvarchar(80)
set #Sql=' select * from '+#SCHEMA+'..Acc_tblCompany'
Execute sp_executesql #Sql

Perhaps you could implement this as a case statement. It's not quite what you're asking for, but at least you can create the illusion to the caller that it's parameterized wrt schema

Related

query inside the variable

Is it possible in SQL to use a variable to store query.
For example to save time when subquery is used multiple times inside the main query.
Example:
DECLARE #my_query as varchar(250) = select x from my_table where my_table = y.your_table
SELECT
a,b,c,(#my_query),d,e,f
FROM my_table_1
Is it possible in SQL to use a variable to store query.
Depend on your definition of "query". If you mean store the text which we use to execute the command, then the answer is YES. If you mean an object type query, then the answer is not - since there is no data type that fit this.
What I mean is that a variable can store a value which is string. The string can be any query command that you want. Therefore, you can store for example the text "select col1,col2 from table1".
Next you need to ask how can we use this text in order to execute it as part of a query, which is done using dynamic query.
We can execute a text of a query using the build-in stored procedure sp_executesql, which is build for such needs.
For example:
-- DECLARE VARIABLE
DECLARE #MyQuery NVARCHAR(MAX)
-- SET the value of the variable
SET #MyQuery = 'SELECT ''Yes I can'''
-- Executing a dynamic query
EXECUTE sp_executesql #MyQuery
Here is another example which look more close to your question:
-- First let's create a table
CREATE TABLE T(ID INT)
INSERT T(ID) VALUES (1),(2)
GO
-- And here is what you sked about:
-- DECLARE VARIABLE
DECLARE #MyQuery NVARCHAR(MAX)
-- SET the value of the variable
SET #MyQuery = 'select ID from T where ID = ''1'''
-- Let's combine the text to a full query now
DECLARE #FullQuery NVARCHAR(MAX)
SET #FullQuery = '
SELECT
ID,(' + #MyQuery + ')
FROM T
'
PRINT #FullQuery
-- Executing a dynamic query
EXECUTE sp_executesql #FullQuery
NOTE! Your specific sample of query will return error, which is not related to the question "Is it possible in SQL to use a variable to store query". This is a result of the "query" is not well formatted.
Important! It is HIGHLY recommended to read the document about this stored procedure and learn a bit more of the options it provides us.
https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql?view=sql-server-ver15

Can we do dynamic SQL in From Clause in a Select Query?

Can the select query inside a from clause be a dynamic sql?
For example
DECLARE #sql NVARCHAR(MAX)
SET #sql='SELECT * table'
SELECT t.*, a+b AS total_sum
FROM
(
EXEC (#sql)
) t
If the above is not possible, how can we achieve this functionality?
Of course the above query result in Error when run in sql server.
Thank you for the help.
In order to use dynamic table in from clause , you must run command EXEC(#sql) outside :
In your above example :
DECLARE #sql NVARCHAR(MAX)
DECLARE #dynamicSql NVARCHAR(MAX)
SET #sql='SELECT * table'
SET #dynamicSql ='SELECT t.*, a+b AS total_sum
FROM
(
'+#sql+'
) t'
EXECUTE sp_executesql #dynamicSql
In SQL Server, a SQL statement is compiled the first time the database sees it. This means that anything that can change the code being generated can't be a parameter. Which in turn means that you can't use parameters for...
table names
join expressions
column names
where clauses
order by clause
In fact, you could say that you are more or less limited to using parameters for...
Literal values in comparisons MyColumn = #Param1
Literal values in select statements SELECT #Param2
Literal values in insert/update statements SET Column = #Param3
Top, limit, and fetch clauses SELECT TOP #Param4
As mentioned elsewhere, the work-around is to create your SQL as a string and then pass that string to sp_executesql.
Deep notes:
SQL is normally compiled into an intermediate language. This intermediate language can be viewed as XML. See "execution plans" for more information.
In SQL Server 2014, stored procedures can be converted into C++ code and then compiled to machine language. There are a lot of restrictions when doing this that are too much to discus here.

SQL SELECT results INTO temp table using query string

I am trying to write some dynamic SQL queries that select results into a temp table with a query string. It looks like follows:
DECLARE #SQL Varchar(4000)
SET #SQL = 'SELECT * INTO #tmp_tab FROM dbo.sometable'
EXEC(#SQL)
It doesn't give any error to run the code, but when I want to select from #tmp_tab, it says the table doesn't exist.
So I am wondering if there is any special syntax for it, or dynamic SQL doesn't support such operation?
Many thanks.
Maybe it has something to do with access. If you create a global temp table, it will work.
DECLARE #SQL Varchar(4000)
SET #SQL = 'SELECT * INTO ##tmp_tab FROM dbo.batch'
EXEC(#SQL)
SELECT * FROM ##tmp_tab

sql server - fill results from executed query string in a temp table dynamically

I'm writing a stored procedure. I have a string which contains an sql query. For example:
DECLARE #sql nvarchar(max)
SET #sql = (N'SELECT pkOrderID FROM Orders')
(Just to note: this isn't what the select statement looks like. This is just an example of what I mean) I then want to execute the string and put the result in a temporary table E.g. #tempTable. I know EXEC(#sql) exists but not sure if it will do me any good in this situation. The other twist is that I do not know the names of all the columns in the returned #sql so the temp table #tempTable needs to be created dyanmically based off the return from #sql. Thanks for any help.
I think you could use SELECT INTO to do what you want but it would mean updating your string:
DECLARE #sql nvarchar(max)
SET #sql = (N'SELECT frompkOrderID INTO #tmporders FROM Orders')
then you should be able to run EXEC #sql to create the table
more information about SELECT INTO here : http://msdn.microsoft.com/en-au/library/ms188029.aspx
There is no simple way to do this. The problem with #JanR's solution is that the #tmporders table will be out of scope to the script that calls your stored procedure (ie It will produce an error like "Invalid object name '#rtmporders'"
One alternative is to use a global temp table (eg ##tmporders).
So your SP might look like this:
CREATE PROCEDURE TestSP
AS
BEGIN
SELECT pkOrderID INTO ##tmporders FROM Orders
END
GO
And the calling script might be like:
EXEC TestSP
SELECT * FROM ##temporders

Is there a better way to execute dynamic SQL that doesn't use a cursor?

I have dynamic SQL stored in a SQL table that I have to execute under certain conditions. Currently, we use cursors to handle that for us, but I was always told to avoid cursors when possible as they aren't the most efficient way of doing things. So, my question is: how do I execute dynamic SQL without them (if there's a way)? The entire system is built around this dynamic SQL mess, so there is no changing it.
For this, just assume the table has Id AS IDENTITY and SQL AS VARCHAR fields, where the SQL field contains the SQL to be executed (obviously).
EDIT:
Basically, I want to loop through the table and execute the SQL in the SQL column.
So, a row in the table will basically look like this:
ID SQL
-- ----------------------
1 SELECT * FROM RECORD
2 SELECT * FROM PERSON
3 SELECT * FROM LOCATION
I haven't written any code because what I'd write is a cursor to traverse through the table and execute it. I just don't know of any other ways of looping a table and executing that string as a SQL query other than something like:
DECLARE #sql VARCHAR(MAX)
DECLARE _cursor CURSOR
FOR
SELECT [SQL]
FROM #tmp2
OPEN _cursor
FETCH NEXT FROM _cursor INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT ( #sql )
END
CLOSE _cursor
DEALLOCATE _cursor
You can use any number of concatenation tricks to make one big batch without using a cursor, I personally use the FOR XML trick a lot.
Here's an overview:
http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/
However, the cursor (while generally a code smell) isn't going to contribute a terrible amount to the non-performance of this. And you will have an opportunity to handle errors etc a lot easier than with a single batch.
In addition, if you have DDL in some of those statements which has to be the first statement in a batch, then you would need to submit them in separate batches. EXEC or sp_executesql doesn't implement any batch splitting like SSMS has the GO batch separator.
Ignoring the fundamental flaws in this whole schema....
declare #sql nvarchar(max)
select #sql = ''
select #sql = #sql + SQL + ';' from #tmp2
exec sp_executesql #sql
At least we've got rid of your cursor now :)
EDIT: Code that is working for me...
create table #tmp2 (sql nvarchar(100))
insert #tmp2 values ('select * from sysobjects')
insert #tmp2 values ('Select * from sysColumns')
declare #sql nvarchar(max)
select #sql = ''
select #sql = #sql + SQL + ';' from #tmp2
exec sp_executesql #sql
drop table #tmp2