This is My code
create proc TEMP
AS
BEGIN
DECLARE #SQL nvarchar(4000)
IF OBJECT_ID(N'tempdb..#TEMP1') IS NOT NULL
DROP TABLE #TEMP1;
SET #SQL ='SELECT CUSTOMERS,AREA,HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL +'INTO #TEMP1'+CHAR(10)
SET #SQL = #SQL +'FROM NEW'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
IF OBJECT_ID(N'tempdb..#TEMP2') IS NOT NULL
DROP TABLE #TEMP2;
SET #SQL ='SELECT CUSTOMERS,AREA,VEHICELS'+CHAR(10)
SET #SQL = #SQL +'INTO #TEMP2'+CHAR(10)
SET #SQL = #SQL +'FROM OLD'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
IF OBJECT_ID(N'tempdb..#TEMP3') IS NOT NULL
DROP TABLE #TEMP3;
SET #SQL ='SELECT 0.VEHICELS,C.HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL +'INTO #TEMP3'+CHAR(10)
SET #SQL = #SQL +'FROM #TEMP1 C'+CHAR(10)
SET #SQL = #SQL +'INNER JOIN #TEMP2 O '+CHAR(10)
SET #SQL = #SQL +'on C.CUSTOMERS=O.CUSTOMERS'+CHAR(10)
SET #SQL = #SQL +'AND C.AREA=O.AREA'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
END
My error:
Msg 208, Level 16, State 0, Line 1
Invalid object name '#TEMP1'.
First TEMP1 and TEMP2 are working well, but when it comes to TEMP3 it doesn't access TEMP1 where the data is present
Can you guys check this confusing problem ???
DECLARE #sql varchar(max)
SET #sql = 'CREATE TABLE ##T1 (Col1 varchar(20))'
EXEC(#sql)
INSERT INTO ##T1 (Col1) VALUES ('This will work.')
SELECT * FROM ##T1
DO WE GET ANY PROBLEMS IN FUTURE IF WE USE GLOBALTEMPORARY TABLES???
once the exec finishes executing the #temp table is deleted
maybe if you try using a wider scope, it could succeed, I don't know.
try something like this.
create proc TEMP
AS
BEGIN
DECLARE #now datetime;
DECLARE #TempTableTableSuffix sysname
SET #now = GETDATE()
select #TempTableTableSuffix = CONVERT(VARCHAR, CONVERT(int,RAND(DATEPART(MILLISECOND,#now)+1000*(DATEPART(SECOND,#now)+60*(DATEPART(MINUTE,#now)+60*DATEPART(HOUR,#now)))) * 100000000))
DECLARE #SQL nvarchar(4000)
SET #SQL ='SELECT CUSTOMERS,AREA,HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL +'INTO ##TEMP1' + #TempTableTableSuffix + CHAR(10)
SET #SQL = #SQL +'FROM NEW'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
SET #SQL ='SELECT CUSTOMERS,AREA,VEHICELS'+CHAR(10)
SET #SQL = #SQL +'INTO ##TEMP2' + #TempTableTableSuffix + CHAR(10)
SET #SQL = #SQL +'FROM OLD'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
SET #SQL ='SELECT 0.VEHICELS,C.HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL +'INTO ##TEMP3'+CHAR(10)
SET #SQL = #SQL +'FROM ##TEMP1' + + #TempTableTableSuffix + ' C'+CHAR(10)
SET #SQL = #SQL +'INNER JOIN #TEMP2'+ #TempTableTableSuffix + ' O '+CHAR(10)
SET #SQL = #SQL +'on C.CUSTOMERS=O.CUSTOMERS'+CHAR(10)
SET #SQL = #SQL +'AND C.AREA=O.AREA'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
END
anyway, I think you don't need dynamic SQL for this.
Use single EXEC -
DECLARE #SQL nvarchar(MAX)
IF OBJECT_ID(N'tempdb..#TEMP1') IS NOT NULL
DROP TABLE #TEMP1;
IF OBJECT_ID(N'tempdb..#TEMP2') IS NOT NULL
DROP TABLE #TEMP2;
IF OBJECT_ID(N'tempdb..#TEMP3') IS NOT NULL
DROP TABLE #TEMP3;
SET #SQL = ' SELECT CUSTOMERS,AREA,HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL + ' INTO #TEMP1'+CHAR(10)
SET #SQL = #SQL + ' FROM NEW'+CHAR(10)
SET #SQL = #SQL + ' SELECT CUSTOMERS,AREA,VEHICELS'+CHAR(10)
SET #SQL = #SQL + ' INTO #TEMP2'+CHAR(10)
SET #SQL = #SQL + ' FROM OLD'+CHAR(10)
SET #SQL = #SQL + ' SELECT 0.VEHICELS,C.HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL + ' INTO #TEMP3'+CHAR(10)
SET #SQL = #SQL + ' FROM #TEMP1 C'+CHAR(10)
SET #SQL = #SQL + ' INNER JOIN #TEMP2 O '+CHAR(10)
SET #SQL = #SQL + ' on C.CUSTOMERS=O.CUSTOMERS'+CHAR(10)
SET #SQL = #SQL + ' AND C.AREA=O.AREA'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
Related
Not sure if this has an easy answer, but I'm basically trying to do this:
select id
from (select table_name from information_schema.columns where column_name = 'id')
where id = 1234
So passing in a list of tables into the FROM.
I'm trying to check all tables where this column exists if they have a matching value for 1234.
And without typing 31 times, select from table1, select from table2, etc etc
And without doing a bunch of joins.
possible?
I wrote this stored procedure.
It SUCKS I know, I've never written anything in tsql (teesquill?) before, and my goal was just to get something that works.
// find all occurrences of value in DB
USE [your db here]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[usp_query] (
#value NVARCHAR(128),
#colName NVARCHAR(MAX)
)
AS
BEGIN
DECLARE #sql NVARCHAR(MAX);
-- DECLARE #tables NVARCHAR(MAX);
DECLARE #tabName NVARCHAR(MAX);
-- DECLARE #colName NVARCHAR(MAX);
DECLARE #count INT;
-- construct SQL
--SET #tables = N'SELECT Table_name FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME LIKE "yourcollumn"'
DECLARE tabs CURSOR FOR SELECT table_name FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME LIKE 'yourcollumn'
OPEN tabs
FETCH NEXT FROM tabs INTO #tabName
WHILE ##fetch_status = 0
BEGIN
--SET #count = N'SELECT count ( ' + #colName + ' ) FROM ' + #tabName + ' where ' + #colName + ' = ' + #value
DECLARE #SQLString NVARCHAR(500);
DECLARE #ParmDefinition NVARCHAR(500);
DECLARE #varOut NVARCHAR(25);
SET #SQLString = N'SELECT #count = count ( ' + #colName + ' ) FROM ' + #tabName + ' where ' + #colName + ' = ' + #value;
SET #ParmDefinition = N'#count NVARCHAR(25) OUTPUT';
EXECUTE sp_executesql #SQLString
,#ParmDefinition
,#count = #varOut OUTPUT;
SET #sql = N'SELECT ' + #colName + ' FROM ' + #tabName + ' where yourcollumn = ' + #value;
IF #varOut > 0
SELECT #tabName AS 'value found in table'
--EXEC sp_executesql #sql
FETCH NEXT FROM tabs INTO #tabName
END
CLOSE tabs
END;
I need to select form a variable table name, which seems to not work in SQL Server (see example nr 2).
I tried making an intermediate step that creates a string with my variable table name as static text (see example nr3), but that failed too, probably because I have nested variables.
Can anyone help me fix it?
------------Example Nr 1--------------
-- Working query without variable Table
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = 'SELECT ';
SELECT #Sql = #Sql +'['+[Modell Pset (S1 Slab)]+']'+ ' AS ''' +''+[C3D Pset (S1 Slab)]+''', ' FROM [MTO_Psets_S1_Slab]
PRINT #sql
--Result of "print #sql": SELECT [c3d:abschnitt] AS 'Abschnitt', [ALL] AS 'Eigenschaft_1', [ALL] AS 'Eigenschaft_2', [Geschoss] AS 'Geschoss', [ALL] AS 'Ist_Aussen', [ALL] AS 'Material_1', [ALL] AS 'Material_2', [ALL] AS 'Objekt', [c3d:teilprojekt] AS 'Teilprojekt',
SET #Sql = (SELECT LEFT(#Sql, LEN(#Sql)-1));
SET #Sql = #Sql + ' FROM [modell_properties_slab]';
EXEC sp_executesql #Sql;
------------Example Nr 2--------------
-- When I replace table with a variable, the query doesn't work anymore
DECLARE #Sql NVARCHAR(MAX);
DECLARE #Table NVARCHAR(MAX);
SET #table = '[MTO_Psets_S1_Slab]'
SET #Sql = 'SELECT ';
SELECT #Sql = #Sql +'['+[Modell Pset (S1 Slab)]+']'+ ' AS ''' +''+[C3D Pset (S1 Slab)]+''', ' FROM #table
SET #Sql = (SELECT LEFT(#Sql, LEN(#Sql)-1));
SET #Sql = #Sql + ' FROM [modell_properties_slab]';
EXEC sp_executesql #Sql
-- Error message:
-- Msg 1087, Level 16, State 1, Line 24
-- Must declare the table variable "#Table".
------------Example Nr 3--------------
-- When I rewrite the query to have the table inside the apostrophes,
-- it doesn't work (compare the result of "print #sql" with the example nr1)
declare #slab nvarchar(MAX) ='slab'
DECLARE #intermediate_step nvarchar(MAX);
set #intermediate_step = '''[''[Modell Pset (S1 Slab)]+'']''+ '' AS '''''' +''''+[C3D Pset (S1 Slab)]+'''''', '' FROM [MTO_Psets_S1_'+#Slab+']'
print #intermediate_step
--Result of "print #intermediate_step": '['[Modell Pset (S1 Slab)]+']'+ ' AS ''' +''+[C3D Pset (S1 Slab)]+''', ' FROM [MTO_Psets_S1_slab]
DECLARE #Sql nvarchar(MAX);
SET #Sql = 'SELECT ';
SELECT #Sql = #Sql + #intermediate_step
print #sql
--Result of "print #sql": SELECT '['[Modell Pset (S1 Slab)]+']'+ ' AS ''' +''+[C3D Pset (S1 Slab)]+''', ' FROM [MTO_Psets_S1_slab]
SET #Sql = (SELECT LEFT(#Sql, LEN(#Sql)-1));
SET #Sql = #Sql + ' FROM [modell_properties_slab]';
EXEC sp_executesql #Sql;
I'll attach the tables i used in the query and the result table from the working query "example nr 1" as JPG: MTO_Psets_S1_Slab, modell_properties_slab, Result query
MTO_Psets_S1_Slab
modell_properties_slab
Result query
I rewrote the query like this and it works:
exec('
declare #t as table ([C3D Pset (S1 '+#slab+')] nvarchar (100), [Modell Pset (S1 '+#slab+')] nvarchar (100));
DECLARE #Sql nvarchar(MAX);
insert #t ([C3D Pset (S1 '+#slab+')] , [Modell Pset (S1 '+#slab+')] )
select * from [MTO_Psets_S1_'+#slab+']
SET #Sql = ''SELECT '';
SELECT #Sql = #Sql +''[''+[Modell Pset (S1 Slab)]+'']''+ '' AS '''''' +''''+[C3D Pset (S1 Slab)]+'''''', '' FROM #t
SET #Sql = (SELECT LEFT(#Sql, LEN(#Sql)-1));
SET #Sql = #Sql + '' FROM [modell_properties_'+#slab+']'';
EXEC sp_executesql #Sql
')
i am usginf this but getting error can u provide a solution.
DECLARE #TableName VARCHAR(500);
SET #TableName = N'CREATE TABLE businessmaster_'+
CONVERT(VARCHAR(10),GetDate()-1,112)+
N' ( contentid int,Businessname varchar(50) )';
print #TableName
declare #sql varchar(100)
SET #sql = 'INSERT INTO'+ #TableName+' (contentid,Businessname) SELECT top 10 contentid,Businessname FROM businessmaster';
EXEC (#sql);
You did not create the table, it should look like this
DECLARE #TableName VARCHAR(500);
SET #TableName = N'businessmaster_'+CONVERT(VARCHAR(10),GetDate()-1,112);
EXEC (N'CREATE TABLE '+#TableName +' ( contentid int,Businessname varchar(50) )')
print #TableName
declare #sql varchar(100)
SET #sql = 'INSERT INTO '+ #TableName+' (contentid,Businessname) SELECT top 10 contentid,Businessname FROM businessmaster';
EXEC (#sql)
You did not create your table, how can you insert data to table not exist:
DECLARE #TableName VARCHAR(MAX);
DECLARE #SQL NVARCHAR(MAX);
SET #TableName = N'businessmaster_'+
CONVERT(VARCHAR(10),GetDate()-1,112);
SET #SQL = N' CREATE TABLE '+#TableName + N' ( contentid int,Businessname varchar(50) )';
EXECUTE (#SQL);
SET #SQL = 'INSERT INTO '+ #TableName+' (contentid,Businessname) SELECT top 10 contentid,Businessname FROM businessmaster';
EXECUTE (#SQL);
Demo.
I am trying to execute this query:
declare #tablename varchar(50)
set #tablename = 'test'
select * from #tablename
This produces the following error:
Msg 1087, Level 16, State 1, Line 5
Must declare the table variable "#tablename".
What's the right way to have the table name populated dynamically?
For static queries, like the one in your question, table names and column names need to be static.
For dynamic queries, you should generate the full SQL dynamically, and use sp_executesql to execute it.
Here is an example of a script used to compare data between the same tables of different databases:
Static query:
SELECT * FROM [DB_ONE].[dbo].[ACTY]
EXCEPT
SELECT * FROM [DB_TWO].[dbo].[ACTY]
Since I want to easily change the name of table and schema, I have created this dynamic query:
declare #schema sysname;
declare #table sysname;
declare #query nvarchar(max);
set #schema = 'dbo'
set #table = 'ACTY'
set #query = '
SELECT * FROM [DB_ONE].' + QUOTENAME(#schema) + '.' + QUOTENAME(#table) + '
EXCEPT
SELECT * FROM [DB_TWO].' + QUOTENAME(#schema) + '.' + QUOTENAME(#table);
EXEC sp_executesql #query
Since dynamic queries have many details that need to be considered and they are hard to maintain, I recommend that you read: The curse and blessings of dynamic SQL
Change your last statement to this:
EXEC('SELECT * FROM ' + #tablename)
This is how I do mine in a stored procedure. The first block will declare the variable, and set the table name based on the current year and month name, in this case TEST_2012OCTOBER. I then check if it exists in the database already, and remove if it does. Then the next block will use a SELECT INTO statement to create the table and populate it with records from another table with parameters.
--DECLARE TABLE NAME VARIABLE DYNAMICALLY
DECLARE #table_name varchar(max)
SET #table_name =
(SELECT 'TEST_'
+ DATENAME(YEAR,GETDATE())
+ UPPER(DATENAME(MONTH,GETDATE())) )
--DROP THE TABLE IF IT ALREADY EXISTS
IF EXISTS(SELECT name
FROM sysobjects
WHERE name = #table_name AND xtype = 'U')
BEGIN
EXEC('drop table ' + #table_name)
END
--CREATES TABLE FROM DYNAMIC VARIABLE AND INSERTS ROWS FROM ANOTHER TABLE
EXEC('SELECT * INTO ' + #table_name + ' FROM dbo.MASTER WHERE STATUS_CD = ''A''')
Use:
CREATE PROCEDURE [dbo].[GetByName]
#TableName NVARCHAR(100)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #sSQL nvarchar(500);
SELECT #sSQL = N'SELECT * FROM' + QUOTENAME(#TableName);
EXEC sp_executesql #sSQL
END
You can't use a table name for a variable. You'd have to do this instead:
DECLARE #sqlCommand varchar(1000)
SET #sqlCommand = 'SELECT * from yourtable'
EXEC (#sqlCommand)
You'll need to generate the SQL content dynamically:
declare #tablename varchar(50)
set #tablename = 'test'
declare #sql varchar(500)
set #sql = 'select * from ' + #tablename
exec (#sql)
Use sp_executesql to execute any SQL, e.g.
DECLARE #tbl sysname,
#sql nvarchar(4000),
#params nvarchar(4000),
#count int
DECLARE tblcur CURSOR STATIC LOCAL FOR
SELECT object_name(id) FROM syscolumns WHERE name = 'LastUpdated'
ORDER BY 1
OPEN tblcur
WHILE 1 = 1
BEGIN
FETCH tblcur INTO #tbl
IF ##fetch_status <> 0
BREAK
SELECT #sql =
N' SELECT #cnt = COUNT(*) FROM dbo.' + quotename(#tbl) +
N' WHERE LastUpdated BETWEEN #fromdate AND ' +
N' coalesce(#todate, ''99991231'')'
SELECT #params = N'#fromdate datetime, ' +
N'#todate datetime = NULL, ' +
N'#cnt int OUTPUT'
EXEC sp_executesql #sql, #params, '20060101', #cnt = #count OUTPUT
PRINT #tbl + ': ' + convert(varchar(10), #count) + ' modified rows.'
END
DEALLOCATE tblcur
You need to use the SQL Server dynamic SQL:
DECLARE #table NVARCHAR(128),
#sql NVARCHAR(MAX);
SET #table = N'tableName';
SET #sql = N'SELECT * FROM ' + #table;
Use EXEC to execute any SQL:
EXEC (#sql)
Use EXEC sp_executesql to execute any SQL:
EXEC sp_executesql #sql;
Use EXECUTE sp_executesql to execute any SQL:
EXECUTE sp_executesql #sql
Declare #tablename varchar(50)
set #tablename = 'Your table Name'
EXEC('select * from ' + #tablename)
Also, you can use this...
DECLARE #SeqID varchar(150);
DECLARE #TableName varchar(150);
SET #TableName = (Select TableName from Table);
SET #SeqID = 'SELECT NEXT VALUE FOR ' + #TableName + '_Data'
exec (#SeqID)
Declare #fs_e int, #C_Tables CURSOR, #Table varchar(50)
SET #C_Tables = CURSOR FOR
select name from sysobjects where OBJECTPROPERTY(id, N'IsUserTable') = 1 AND name like 'TR_%'
OPEN #C_Tables
FETCH #C_Tables INTO #Table
SELECT #fs_e = sdec.fetch_Status FROM sys.dm_exec_cursors(0) as sdec where sdec.name = '#C_Tables'
WHILE ( #fs_e <> -1)
BEGIN
exec('Select * from ' + #Table)
FETCH #C_Tables INTO #Table
SELECT #fs_e = sdec.fetch_Status FROM sys.dm_exec_cursors(0) as sdec where sdec.name = '#C_Tables'
END
I have a stored procedure which I have to rewrite using sp_executesql. I want to use sp_executesql instead of exec because of performance issue on my SQL Server instance.
Here is my code:
ALTER PROCEDURE [dbo].[sp_TestSp1]
#Type1 VARCHAR(256)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sqlCommand varchar(2000) = ''
DECLARE #columnList varchar(1000) = ''
DECLARE #dynamicSql varchar(1000) = ''
IF (#Type1 IS NOT NULL )
BEGIN
SET #dynamicSql = #dynamicSql + 'AND tbl1.DTypeID IN ( '+ #Type1+ ' )'
END
SET #columnList = 'SELECT DISTINCT tbl2.ID, Name AS PName '
SET #sqlCommand = #columnList
+ ' FROM tbl1 '
+ ' INNER JOIN tbl3 ON tbl1.NID= tbl3.NID '
+ ' INNER JOIN tbl4 ON tbl3.DID = tbl4.DID '
+ ' WHERE TT=1 AND IsActive=1 AND tbl1.DTypeID IN (1,3,5)'
+ #dynamicSql
EXEC (#sqlCommand)
Replace your EXEC (#sqlCommand) statement with the following.
EXECUTE sp_executesql #sqlCommand
TechNet Link