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
Related
I have a big query which works and I want to write a stored procedure for it.
I'm getting this error:
the OLE DB provider SQLNCLI11" for linked server "theServer" does not contain the table ""#dbName"."dbo"."tableName"
What I am trying to do:
create PROCEDURE [sys.sp_myProcedure]
(
#dbName varchar(30) output,
#rid varchar (10) output,
#mdate output
)
AS
BEGIN
declare #prt varchar(12)
declare #pid int
declare #cid int
--declare #rid int
declare #aid int
SET NOCOUNT ON;
set #cid= (select CID from theServer.[#dbName].dbo.tableName where RID= #rid)
set #pid= (select PID from theServer.[#dbName].dbo.tableName where RID= #rid)
set #aid= (select aid from theServer.[#dbName].dbo.tableName where RID= #rid)
--then my query begins
theServer.[#dbName].dbo.tablename is a linked server.
What I want to do is:
execute [sys.sp_myProcedure] 'someDbname', '123', '2012-03-03'
and the parameters passed here would set/update the variables #dbName, #rid, #mdate at runtime. ( #mdate I have it further away in the query, it's too big to adapt it with myTable and to change all the sensitive data).
How can I do this ?? (using SQL Server 2012)
edit (based on the comments and answers):
so, it's #thatString = '--insert the query here ' . Then, in my case how can i set those variables according to the parameters inside the query? Should i do it with replace? like this: set #thatString= replace(#thatString, dbName, #dbname) ?
**
edit 2
**
set #sql = '
use [someDbName];
use [123];
use [2012-03-03];
select ... '
set #sql = replace (#sql, 'someDbName', #dbName)
set #sql = replace (#sql, '123', #rid)
set #sql = replace (#sql, '2012-03-03', #mdate)
execute #sql
end
Did i get it right? is the execute #sql in the right place?
I'm asking cause it doesnt work. i'm getting the name ' --part of my query here' is not a valid identifier
Names of databases or other objects cannot be specified dynamically from variables. The workaround is to compose a dynamic SQL query in a string, into which you concatenate the required names, and then execute (#thatString).
(You might think you can employ use, but it is scoped such that you would have to include the rest of your query within the same executed string.)
--
Edit with more info as requested. You can compose the string however you like. If you need any more guidance, there are plenty of pages that discuss dynamic T-SQL. But hey, two ideas:
set #myDynamicQuery =
'
use [' + #myDynamicDatabase + '];
select BLAH from WHOM where DATA = ''what'';
';
or if you will be using the name a lot, you could reduce the hassle caused by breaking in and out of single quotes as follows - though I personally never use this as I don't like how it looks:
set #myDynamicQuery =
'
use [A_RARE_PLACEHOLDER];
select BLAH from WHOM where DATA = ''what'';
-- lots more uses of A_RARE_PLACEHOLDER
';
set #myDynamicQuery = replace(
#myDynamicQuery,
'A_RARE_PLACEHOLDER',
#myDynamicDatabase
);
Then execute (#myDynamicQuery);
I would like to dynamically replace the value of an XML Element, in selected XML value(s) being retrieved from a table. This replacement needs to be performed by a function that I would like to call. I can't even begin to find any clues to point me in the right direction...
I have the follow code snippet (incomplete) that I believe is the correct structure for using XPath to get to the element I want, and to qualify by XPath which records I am interested in (one or more), from there I have no idea how to take the result of the called function, and ideally place the result in a sql:column:
UPDATE [database].[dbo].[table_with_xml]
SET table_with_xml.modify('replace value of (//PrimaryApplicant/FName/text())[1] with sql:column("")')
FROM [database].[dbo].[table_with_xml] AS [XML_Table]
WHERE [XML_Table].XML_Field.value('(//HeaderData/CountryCode/text())[1]', 'varchar(100)') = '123'
First of all, if you want to update table data from a function, you aren't allowed to do it. You can use a stored proc though. You can send 'replace value of' statement (from you syntax above) to it dynamically and send the value with which you want to replace. Here's some code to demonstrate what I'm trying to say:
Create PROC changeXML
#xmlPath nvarchar(max), -- the statement 'replace value of'
#value nvarchar(max) -- the new value
AS
BEGIN
DECLARE #pathString nvarchar(max), #sql NVARCHAR(MAX);
-- create full statement dynamically
SET #pathString = 'replace value of ('+#xmlPath+'text())[1] with ("'+#value+'")';
SELECT #pathString;
-- create dynamic sql and pass pathstring to it.
SET #sql = 'UPDATE [dbo].[tableWithXmlData] SET a.modify(''#p'')';
-- execute dynamic sql
EXEC sp_executesql #sql, N'#p nvarchar(max)', #p = #pathString
END
Then run proc something like this:
EXEC [dbo].[chnageXML] #xmlPath = N'path to your xml value',
#value = N'new value'
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
I am trying to store the results of an SQL query into a variable.The query simply detects the datatype of a column, hence the returned result is a single varchar.
SET #SQL =
'declare ##x varchar(max) SET ##x = (select DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS
WHERE Table_name = ' +char(39)+#TabName+char(39) +
' AND column_name = ' +char(39)+#colName+char(39) + ')'
EXECUTE (#SQL)
Anything within the 'SET declaration' cannot access any variables outside of it and vice versa, so I am stuck on how to store the results of this query in a varchar variable to be accessed by other parts of the stored procedure.
You dont need a dynamic query to achieve what you want, below query will give the same result as yours.
declare #x varchar(max)
declare #tableName varchar(100), #ColumnName varchar(50)
set #tableName = 'Employee'
set #ColumnName = 'ID'
select #x = DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS
where
Table_Name = #tableName
and column_name = #ColumnName
select #x
All user-defined variables in T-SQL have private local-scope only. They cannot be seen by any other execution context, not even nested ones (unlike #temp tables, which can be seen by nested scopes). Using "##" to try to trick it into making a global-variable doesn't work.
If you want to execute dynamic SQL and return information there are several ways to do it:
Use sp_ExecuteSQL and make one of the parameters an OUTPUT parameter (recommended for single values).
Make a #Temp table before calling the dynamic SQL and then have the Dynamic SQL write to the same #Temp table (recommended for multiple values/rows).
Use the INSERT..EXEC statement to execute your dynamic SQL which returns its information as the output of a SELECT statement. If the INSERT table has the same format as the dynamic SQL's SELECT output, then the data output will be inserted into your table.
If you want to return only an integer value, you can do this through the RETURN statement in dynamic SQL, and receive it via #val = EXEC('...').
Use the Session context-info buffer (not recommended).
However, as others have pointed out, you shouldn't actually need dynamic SQL for what you are showing us here. You can do just this with:
SET #x = ( SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS
WHERE Table_name = #TabName
AND column_name = #colName )
You may want to consider using the sp_executesql stored procedure for dynamic sql.
The following link provides a good usage example of sp_executesql procedure with output parameters:
http://support.microsoft.com/kb/262499
I am trying to use some dynamic sql. I have generated over 100 parameters, and to speed things up I am trying to use dynamic sql to only insert values into a table that I have to based off of information retrieved from other tables. I have tried many things like adding a cast etc.
Example of what I mean:
DECLARE #var1 NVARCHAR(MAX)
-- Loop through and add various values
SET #var1 = #var1 + #parameterName
-- The parameter name is retrieved from a table that holds this information
the problem is that when I add the parameter name which would be like "#myFirstParameter" into my final expression so something like this:
DECLARE #finalString NVARCHAR(MAX)
SET #finalString = 'INSERT INTO myTableName ([myFirstParameter]) VALUES (#myFirstParameter)'
EXEC(#finalString)
The "#myFirstParameter" does not get replaced by it's value and I get the following error:
Must declare the scalar variable "#myFirstParameter".
Does anyone know of a way to go from the string name of a parameter to the actual value? I am trying to avoid hardcoding all the values and any work around I have attempted has failed and given me errors which appear to be much worse than what I have stated above.
The first way is to add the parameter's value, instead of its name, to the SQL string:
SET #finalString = 'INSERT INTO myTableName ([myFirstParameter]) VALUES (' +
#myFirstParameter + ')'
This assumes the parameter has a string value. If not, you have to cast it, like cast(#myFirstParameter as varchar(128)).
The second way is to use sp_executesql instead of exec:
exec sp_executesql
N'INSERT INTO myTableName ([myFirstParameter]) VALUES (#myFirstParameter)',
N'#myFirstParameter varchar(128)',
#myFirstParameter = #myFirstParameter;