SQL Server - Dynamic Table Name as Variable - sql-server

I have been having problems trying to create tables with dynamic name. I keep getting these errors:
Msg 102, Level 15, State 1, Procedure SP_SearchTables, Line 159
Incorrect syntax near '#tablename'.
Msg 1087, Level 15, State 2, Procedure SP_SearchTables, Line 165
Must declare the table variable "#tablename".
Msg 1087, Level 15, State 2, Procedure SP_SearchTables, Line 171
Must declare the table variable "#tablename".
As you can see in the stored procedure, before this changes I had SearchTMP instead #tablename, but I don't want to give a fixed name, I want to give a dynamic name. With that in mind, I gave a name and some random numbers, but it keeps giving me the errors I showed previously, could you please help me?
I will post my stored procedure.
ALTER PROCEDURE [dbo].[SearchTables]
#SearchStr NVARCHAR(60),
#GenerateSQLOnly BIT = 0,
#SchemaNames VARCHAR(500) ='%'
AS
SET NOCOUNT ON
DECLARE #MatchFound BIT
SELECT #MatchFound = 0
DECLARE #CheckTableNames TABLE (Schemaname sysname, Tablename sysname)
DECLARE #SearchStringTbl TABLE (SearchString VARCHAR(500))
DECLARE #SQLTbl TABLE
(
Tablename SYSNAME,
WHEREClause VARCHAR(MAX),
SQLStatement VARCHAR(MAX),
Execstatus BIT
)
DECLARE #SQL VARCHAR(MAX)
DECLARE #TableParamSQL VARCHAR(MAX)
DECLARE #SchemaParamSQL VARCHAR(MAX)
DECLARE #TblSQL VARCHAR(MAX)
DECLARE #tmpTblname sysname
DECLARE #ErrMsg VARCHAR(100)
IF LTRIM(RTRIM(#SchemaNames)) =''
BEGIN
SELECT #SchemaNames = '%'
END
IF CHARINDEX(',',#SchemaNames) > 0
SELECT #SchemaParamSQL = 'SELECT ''' + REPLACE(#SchemaNames,',','''as SchemaName UNION SELECT ''') + ''''
ELSE
SELECT #SchemaParamSQL = 'SELECT ''' + #SchemaNames + ''' as SchemaName '
SELECT #TblSQL = 'SELECT SCh.NAME,T.NAME
FROM SYS.TABLES T
JOIN SYS.SCHEMAS SCh ON SCh.SCHEMA_ID = T.SCHEMA_ID
INNER JOIN [DynaForms].[dbo].[Enums_Tables] et ON (et.Id = T.NAME COLLATE Latin1_General_CI_AS) '
INSERT INTO #CheckTableNames (Schemaname, Tablename)
EXEC (#TblSQL)
IF NOT EXISTS(SELECT 1 FROM #CheckTableNames)
BEGIN
SELECT #ErrMsg = 'No tables are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
IF LTRIM(RTRIM(#SearchStr)) =''
BEGIN
SELECT #ErrMsg = 'Please specify the search string in #SearchStr Parameter'
PRINT #ErrMsg
RETURN
END
ELSE
BEGIN
SELECT #SearchStr = REPLACE(#SearchStr,',,,',',#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,',,','#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,'''','''''')
SELECT #SQL = 'SELECT ''' + REPLACE(#SearchStr,',','''as SearchString UNION SELECT ''') + ''''
INSERT INTO #SearchStringTbl (SearchString)
EXEC(#SQL)
UPDATE #SearchStringTbl
SET SearchString = REPLACE(SearchString ,'#DOUBLECOMMA#',',')
END
INSERT INTO #SQLTbl (Tablename, WHEREClause)
SELECT
QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(SELECT '[' + SC.Name + ']' + ' LIKE ''' + REPLACE(SearchSTR.SearchString,'''','''''') + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
CROSS JOIN #SearchStringTbl SearchSTR
WHERE STY.name IN ('varchar', 'char', 'nvarchar', 'nchar', 'text')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM
SYS.tables ST
JOIN
#CheckTableNames chktbls ON chktbls.Tablename = ST.name
JOIN
SYS.schemas SCh ON ST.schema_id = SCh.schema_id
AND Sch.name = chktbls.Schemaname
WHERE
ST.name <> 'SearchTMP'
GROUP BY
ST.object_id, QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME) ;
DECLARE #numbers VARCHAR(MAX)
SET #numbers = CONVERT(NUMERIC(12, 0), RAND() * 899999999999) + 100000000000
DECLARE #tablename VARCHAR(MAX)
SET #tablename = 'SearchTMP' + #numbers
UPDATE #SQLTbl
SET SQLStatement = N'SELECT * INTO ' + #tablename +' FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5)
DELETE FROM #SQLTbl
WHERE WHEREClause IS NULL
DECLARE #output TABLE (Id VARCHAR(50), Name VARCHAR(100))
WHILE EXISTS (SELECT 1 FROM #SQLTbl WHERE ISNULL(Execstatus ,0) = 0)
BEGIN
SELECT TOP 1 #tmpTblname = Tablename , #SQL = SQLStatement
FROM #SQLTbl
WHERE ISNULL(Execstatus ,0) = 0
IF #GenerateSQLOnly = 0
BEGIN
IF OBJECT_ID('#tablename','U') IS NOT NULL
DROP TABLE #tablename
EXEC (#SQL)
IF EXISTS(SELECT 1 FROM #tablename)
BEGIN
--SELECT parsename(#tmpTblname,1) FROM SearchTMP
SELECT #MatchFound = 1
INSERT INTO #output (Id, Name)
SELECT *
FROM [DynaForms].[dbo].[Enums_Tables]
WHERE id IN (SELECT parsename(#tmpTblname, 1) FROM #tablename)
END
END
ELSE
BEGIN
PRINT REPLICATE('-',100)
PRINT #tmpTblname
PRINT REPLICATE('-',100)
PRINT replace(#SQL,'INTO #tablename','')
END
UPDATE #SQLTbl
SET Execstatus = 1
WHERE Tablename = #tmpTblname
END
SELECT * FROM #output
--Select * from #SQLTbl
IF #MatchFound = 0
BEGIN
SELECT #ErrMsg = 'No Matches are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
SET NOCOUNT OFF
Edit
I changed my stored procedure to have dynamic sql but it gives me this error:
Msg 214, Level 16, State 2, Procedure sp_executesql, Line 1
Procedure expects parameter '#statement' of type 'ntext/nchar/nvarchar'.
I believe the problem is in my subquery, but I can't seen to make it work, could you please help me? The subquery is here:
DECLARE #SQLSUBQUERY VARCHAR(max);
SELECT #SQLSUBQUERY = 'SELECT * FROM [DynaForms].[dbo].[Enums_Tables] ';
SELECT #SQLSUBQUERY = #SQLSUBQUERY + 'WHERE id IN (SELECT parsename(#tmpTblname,1) FROM #tablename)';
INSERT INTO #output (Id, Name)
EXEC sp_executesql #SQLSUBQUERY
Full code here:
ALTER PROCEDURE [dbo].[SP_SearchTables]
#SearchStr NVARCHAR(60),
#GenerateSQLOnly Bit = 0,
#SchemaNames VARCHAR(500) ='%'
AS
SET NOCOUNT ON
DECLARE #MatchFound BIT
SELECT #MatchFound = 0
DECLARE #CheckTableNames TABLE (Schemaname sysname, Tablename sysname)
DECLARE #SearchStringTbl TABLE (SearchString VARCHAR(500))
DECLARE #SQLTbl TABLE (Tablename SYSNAME,
WHEREClause VARCHAR(MAX),
SQLStatement VARCHAR(MAX),
Execstatus BIT)
DECLARE #SQL VARCHAR(MAX)
DECLARE #TableParamSQL VARCHAR(MAX)
DECLARE #SchemaParamSQL VARCHAR(MAX)
DECLARE #TblSQL VARCHAR(MAX)
DECLARE #tmpTblname sysname
DECLARE #ErrMsg VARCHAR(100)
IF LTRIM(RTRIM(#SchemaNames)) =''
BEGIN
SELECT #SchemaNames = '%'
END
IF CHARINDEX(',',#SchemaNames) > 0
SELECT #SchemaParamSQL = 'SELECT ''' + REPLACE(#SchemaNames,',','''as SchemaName UNION SELECT ''') + ''''
ELSE
SELECT #SchemaParamSQL = 'SELECT ''' + #SchemaNames + ''' as SchemaName '
SELECT #TblSQL = 'SELECT SCh.NAME,T.NAME
FROM SYS.TABLES T
JOIN SYS.SCHEMAS SCh
ON SCh.SCHEMA_ID = T.SCHEMA_ID
INNER JOIN [DynaForms].[dbo].[Enums_Tables] et on
(et.Id = T.NAME COLLATE Latin1_General_CI_AS) '
INSERT INTO #CheckTableNames (Schemaname, Tablename)
EXEC(#TblSQL)
IF NOT EXISTS(SELECT 1 FROM #CheckTableNames)
BEGIN
SELECT #ErrMsg = 'No tables are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
IF LTRIM(RTRIM(#SearchStr)) =''
BEGIN
SELECT #ErrMsg = 'Please specify the search string in #SearchStr Parameter'
PRINT #ErrMsg
RETURN
END
ELSE
BEGIN
SELECT #SearchStr = REPLACE(#SearchStr,',,,',',#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,',,','#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,'''','''''')
SELECT #SQL = 'SELECT ''' + REPLACE(#SearchStr,',','''as SearchString UNION SELECT ''') + ''''
INSERT INTO #SearchStringTbl
(SearchString)
EXEC(#SQL)
UPDATE #SearchStringTbl
SET SearchString = REPLACE(SearchString ,'#DOUBLECOMMA#',',')
END
INSERT INTO #SQLTbl (Tablename, WHEREClause)
SELECT
QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(SELECT '[' + SC.Name + ']' + ' LIKE ''' + REPLACE(SearchSTR.SearchString,'''','''''') + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
CROSS JOIN #SearchStringTbl SearchSTR
WHERE
STY.name in ('varchar','char','nvarchar','nchar','text')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM SYS.tables ST
JOIN #CheckTableNames chktbls
ON chktbls.Tablename = ST.name
JOIN SYS.schemas SCh
ON ST.schema_id = SCh.schema_id
AND Sch.name = chktbls.Schemaname
WHERE ST.name <> 'SearchTMP'
GROUP BY ST.object_id, QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME) ;
declare #numbers varchar(MAx)
set #numbers = convert(numeric(12,0),rand() * 899999999999) + 100000000000
declare #tablename varchar(MAX)
set #tablename = 'SearchTMP' + #numbers
UPDATE #SQLTbl
SET SQLStatement = N'SELECT * INTO ' + #tablename +' FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5)
DELETE FROM #SQLTbl
WHERE WHEREClause IS NULL
DECLARE #output TABLE (Id VARCHAR(50), Name VARCHAR(100))
WHILE EXISTS (SELECT 1 FROM #SQLTbl WHERE ISNULL(Execstatus ,0) = 0)
BEGIN
SELECT TOP 1 #tmpTblname = Tablename , #SQL = SQLStatement
FROM #SQLTbl
WHERE ISNULL(Execstatus ,0) = 0
IF #GenerateSQLOnly = 0
BEGIN
DECLARE #SQLs NVARCHAR(MAX)
SELECT #SQLs = 'DROP TABLE dbo.' + QUOTENAME(#tablename) + '';
IF OBJECT_ID(''+#tablename+'','U') IS NOT NULL
EXEC sp_executesql #SQLs;
EXEC (#SQL)
--IF EXISTS(SELECT 1 FROM #tablename)
BEGIN
--SELECT parsename(#tmpTblname,1) FROM SearchTMP
SELECT #MatchFound = 1
DECLARE #SQLSUBQUERY VARCHAR(max);
SELECT #SQLSUBQUERY = 'SELECT * FROM [DynaForms].[dbo].[Enums_Tables] ';
SELECT #SQLSUBQUERY = #SQLSUBQUERY + 'WHERE id IN (SELECT parsename(#tmpTblname,1) FROM #tablename)';
INSERT INTO #output (Id, Name)
EXEC sp_executesql #SQLSUBQUERY
--Select * from [DynaForms].[dbo].[Enums_Tables] where id in (SELECT parsename(#tmpTblname,1) FROM #tablename)
END
END
ELSE
BEGIN
PRINT REPLICATE('-',100)
PRINT #tmpTblname
PRINT REPLICATE('-',100)
PRINT replace(#SQL,'INTO #tablename','')
END
UPDATE #SQLTbl
SET Execstatus = 1
WHERE Tablename = #tmpTblname
END
SELECT * FROM #output
--Select * from #SQLTbl
IF #MatchFound = 0
BEGIN
SELECT #ErrMsg = 'No Matches are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
SET NOCOUNT OFF

There are at least these errors:
IF OBJECT_ID('#tablename','U') IS NOT NULL
This is wrong because check for a table with the name #tablename
IF EXISTS(SELECT 1 FROM #tablename)
This produce the error you've got.
DROP TABLE does not accept variable, use dynamic sql to to your drop

Related

How to create a temptable for this query

I would like to create a temptable that will hold the result of this query:
set #sql = 'use ' + #dbname + '; select db_name() , name from sys.tables where is_ms_shipped = 0 and type_desc = ''USER_TABLE'' '
exec (#sql)
Here is the full query I have:
declare #minx int = 0
declare #maxx int = (select max(id) from #DBS)
declare #sql nvarchar(1000)
declare #dbname varchar (130)
declare #count int
Select *
from #DBS
while (#count is not null
and #count <= #maxx)
begin
select #dbname = dbname
from #DBS where id = #count
print 'id = ' + convert (varchar, #count) + ' dbname = ' + #dbname
set #sql = 'use ' + #dbname + '; select db_name() , name from sys.tables where is_ms_shipped = 0 and type_desc = ''USER_TABLE'' '
exec (#sql)
set #count = #count + 1
break
end;
I have tried so many things and always getting error messages.
Anybody could give me an insight?
Not sure how you populate #DBS but:
CREATE TABLE #tables(db sysname, table_name sysname);
DECLARE #dbs cursor,
#context nvarchar(1000),
#sql nvarchar(max);
SET #sql = N'INSERT #tables(db, table_name)
SELECT DB_NAME(), name
FROM sys.tables
WHERE type = ''U'' AND is_ms_shipped = 0;';
SET #dbs = CURSOR FOR SELECT QUOTENAME(dbname)
+ N'.sys.sp_executesql' FROM #DBS;
OPEN #dbs;
FETCH NEXT FROM #dbs INTO #context;
WHILE ##FETCH_STATUS = 0
BEGIN
EXECUTE #context #sql;
FETCH NEXT FROM #dbs INTO #context;
END
SELECT db, table_name FROM #tables;
Also see this related question.

Change Nested Cursor stored procedure to Nested loop

I have a stored procedure which is currently using nested cursors to build up views using database, table, column parameters. I need this to be changed to a while loop query instead. I understand the results are the same but we just prefer not to use cursors.
This seem very tricky due to the dynamic SQL.
ALTER PROCEDURE [dbo].[spReCreateCommonViews_AK]
AS
DECLARE #Exec INT = 1, #Print INT = 2
-- DECLARE #debug INT = #Exec
DECLARE #debug INT = #Print
DECLARE #Sql VARCHAR(MAX),
#SourceName VARCHAR(100),
#DatabaseName VARCHAR(100),
#CompanyName VARCHAR(100),
#ColumnCursor VARCHAR(800),
#TableId INT,
#TableName VARCHAR(100),
#ColumnType INT,
#ColumnName VARCHAR(100),
#ColumnList VARCHAR(MAX) = '',
#CreateViewSQL VARCHAR(MAX)
/** COMPANIES ********/
DECLARE CompaniesCursor CURSOR FOR
SELECT
[Database],
REPLACE(REPLACE(REPLACE([Name], '.', '_'), '/', '_'), '''', '_') AS [Name],
CASE
WHEN RIGHT([Source], 7) = '_SOURCE'
THEN '[' + [Source] + '].[' + [Database] + ']'
ELSE '[' + [Database] + ']'
END AS [Source]
FROM
Company
OPEN CompaniesCursor
FETCH NEXT FROM CompaniesCursor INTO #DatabaseName, #CompanyName, #SourceName
WHILE ##fetch_status = 0
BEGIN
/** TABLES ***********/
SELECT #Sql = 'DECLARE TablesCursor CURSOR FOR
select
o.[id] as TableId,
o.[name] as TableName
from '+#SourceName+'.dbo.sysobjects o
inner join '+#SourceName+'.dbo.[Object] t
on o.[name] = replace(replace(replace(t.[Name],''.'',''_''),''/'',''_''),'''''''',''_'')
and t.[Company Name] = ''''
and t.[Type] = 0
where o.[name] <> ''Company''
and o.[name] not like ''' + #CompanyName + '$%''
and o.type = ''U''
order by o.[name]
'
exec(#Sql)
open TablesCursor
fetch next from TablesCursor into #TableId, #TableName
while ##fetch_status = 0
begin
/** COLUMNS ************************************************************/
select #ColumnCursor =
'
declare ColumnsCursor cursor
for
select ''['' + [name] + '']'' as ColumnName, xtype as ColumnType
from '+#SourceName+'.dbo.syscolumns
where [id] = ' + convert(varchar, #TableId) + '
order by colid
'
exec(#ColumnCursor)
open ColumnsCursor
fetch next from ColumnsCursor into #ColumnName, #ColumnType
while ##fetch_status = 0
begin
select #ColumnList = #ColumnList + #ColumnName + case when #ColumnType in (35, 99, 167, 175, 231, 239) then ' collate database_default as ' + #ColumnName + ', ' else ', ' end
-----------------------------
fetch next from ColumnsCursor into #ColumnName, #ColumnType
end
close ColumnsCursor
deallocate ColumnsCursor
-----------------------------
select #CreateViewSQL= 'if object_id(N'''+#CompanyName+'$' + #TableName + ''', N''V'') is not null drop view ['+#CompanyName+'$' + #TableName + ']'
if #debug & #Print = #Print print(#CreateViewSQL)
if #debug & #Exec = #Exec exec (#CreateViewSQL)
select #CreateViewSQL= 'create view ['+#CompanyName+'$' + #TableName + '] as select ' + left(#ColumnList,len(#ColumnList)-1) + ' from ' + #SourceName + '.dbo.[' + #TableName + ']'
if #debug & #Print = #Print print(#CreateViewSQL)
if #debug & #Exec = #Exec exec (#CreateViewSQL)
select #ColumnList = ''
-----------------------------
fetch next from TablesCursor into #TableId, #TableName
end
close TablesCursor
deallocate TablesCursor
------------------------------
select #Sql = '
insert into [Object] (
[Type],
[Company Name],
[ID],
[Name],
[Modified],
[Compiled],
[BLOB Reference],
[BLOB Size],
[DBM Table No_],
[Date],
[Time],
[Version List]
)
select
o.[Type],
'''+#CompanyName+''' as [Company Name],
o.[ID],
o.[Name] collate database_default,
o.[Modified],
o.[Compiled],
o.[BLOB Reference],
o.[BLOB Size],
o.[DBM Table No_],
o.[Date],
o.[Time],
o.[Version List] collate database_default
from '+#SourceName+'.dbo.Object o
where o.[Name] <> ''Company''
and o.[Company Name] = ''''
and o.[Type] = 0
and not exists (
select c.*
from [Object] c
where c.[Name] = o.[Name] collate database_default
and c.[Company Name] = '''+#CompanyName+'''
and c.[Type] = 0
and c.[ID] = o.[ID]
)
'
if #debug & #Print = #Print
print(#Sql)
if #debug & #Exec = #Exec
exec (#Sql)
-----------------------------
fetch next from CompaniesCursor into #DatabaseName, #CompanyName, #SourceName
end
close CompaniesCursor
deallocate CompaniesCursor
-----------------------------

Invalid Object Name - #temptable

This stored procedure creates a table in the database when I make the select * into, and because of that, when there is more than one user, an error appears and says SearchTMP table already exists, this happens even if I make a drop of that table. So I decided to make a temporary table, as the following code shows:
INSERT INTO #SQLTbl(Tablename, WHEREClause)
SELECT QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(
SELECT '[' + SC.Name + ']' + ' LIKE ''' + REPLACE(SearchSTR.SearchString,'''','''''') + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy
ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
CROSS JOIN #SearchStringTbl SearchSTR
WHERE STY.name in ('varchar','char','nvarchar','nchar','text')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM SYS.tables ST
JOIN #CheckTableNames chktbls
ON chktbls.Tablename = ST.name
JOIN SYS.schemas SCh
ON ST.schema_id = SCh.schema_id
AND Sch.name = chktbls.Schemaname
WHERE ST.name <> '#MyTempTable' -- it was SearchTMP
GROUP BY ST.object_id, QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME);
UPDATE #SQLTbl SET SQLStatement = 'SELECT * INTO #MyTempTable FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5)
Since I didn't want to declare or create the table previously, the temptable will be created in the select * into. But when I try to run the procedure by filling the parameters it says:
>Msg 208, Level 16, State 0, Procedure SP_SearchTables_TEST, Line 265, Invalid object name #MyTempTable
The entire stored procedure:
ALTER PROCEDURE [dbo].[SearchTables_TEST] #SearchStr NVARCHAR(60) ,#GenerateSQLOnly Bit = 0 ,#SchemaNames VARCHAR(500) ='%' AS
SET NOCOUNT ON
DECLARE #MatchFound BIT
SELECT #MatchFound = 0
DECLARE #CheckTableNames Table
(
Schemaname sysname
,Tablename sysname
)
DECLARE #SearchStringTbl TABLE
(
SearchString VARCHAR(500)
)
DECLARE #SQLTbl TABLE
(
Tablename SYSNAME
,WHEREClause VARCHAR(MAX)
,SQLStatement VARCHAR(MAX)
,Execstatus BIT
)
DECLARE #SQL VARCHAR(MAX)
DECLARE #TableParamSQL VARCHAR(MAX)
DECLARE #SchemaParamSQL VARCHAR(MAX)
DECLARE #TblSQL VARCHAR(MAX)
DECLARE #tmpTblname sysname
DECLARE #ErrMsg VARCHAR(100)
IF LTRIM(RTRIM(#SchemaNames)) =''
BEGIN
SELECT #SchemaNames = '%'
END
IF CHARINDEX(',',#SchemaNames) > 0
SELECT #SchemaParamSQL = 'SELECT ''' + REPLACE(#SchemaNames,',','''as SchemaName UNION SELECT ''') + ''''
ELSE
SELECT #SchemaParamSQL = 'SELECT ''' + #SchemaNames + ''' as SchemaName '
SELECT #TblSQL = 'SELECT SCh.NAME,T.NAME
FROM SYS.TABLES T
JOIN SYS.SCHEMAS SCh
ON SCh.SCHEMA_ID = T.SCHEMA_ID
INNER JOIN [DynaForms].[dbo].[Enums_Tables] et on
(et.Id = T.NAME COLLATE Latin1_General_CI_AS) '
INSERT INTO #CheckTableNames
(Schemaname,Tablename)
EXEC(#TblSQL)
IF NOT EXISTS(SELECT 1 FROM #CheckTableNames)
BEGIN
SELECT #ErrMsg = 'No tables are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
IF LTRIM(RTRIM(#SearchStr)) =''
BEGIN
SELECT #ErrMsg = 'Please specify the search string in #SearchStr Parameter'
PRINT #ErrMsg
RETURN
END
ELSE
BEGIN
SELECT #SearchStr = REPLACE(#SearchStr,',,,',',#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,',,','#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,'''','''''')
SELECT #SQL = 'SELECT ''' + REPLACE(#SearchStr,',','''as SearchString UNION SELECT ''') + ''''
INSERT INTO #SearchStringTbl
(SearchString)
EXEC(#SQL)
UPDATE #SearchStringTbl
SET SearchString = REPLACE(SearchString ,'#DOUBLECOMMA#',',')
END
INSERT INTO #SQLTbl(Tablename,WHEREClause)
SELECT QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(
SELECT '[' + SC.Name + ']' + ' LIKE ''' + REPLACE(SearchSTR.SearchString,'''','''''') + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy
ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
CROSS JOIN #SearchStringTbl SearchSTR
WHERE STY.name in ('varchar','char','nvarchar','nchar','text')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM SYS.tables ST
JOIN #CheckTableNames chktbls
ON chktbls.Tablename = ST.name
JOIN SYS.schemas SCh
ON ST.schema_id = SCh.schema_id
AND Sch.name = chktbls.Schemaname
WHERE ST.name <> '#MyTempTable' -- it was SearchTMP
GROUP BY ST.object_id, QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME);
UPDATE #SQLTbl SET SQLStatement = 'SELECT * INTO #MyTempTable FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5)
DELETE FROM #SQLTbl
WHERE WHEREClause IS NULL
DECLARE #output TABLE (Id VARCHAR(50), Name VARCHAR(100))
WHILE EXISTS (SELECT 1 FROM #SQLTbl WHERE ISNULL(Execstatus ,0) = 0)
BEGIN
SELECT TOP 1 #tmpTblname = Tablename , #SQL = SQLStatement
FROM #SQLTbl
WHERE ISNULL(Execstatus ,0) = 0
IF #GenerateSQLOnly = 0
BEGIN
IF OBJECT_ID('#MyTempTable','U') IS NOT NULL -- this line was uncomment
DROP TABLE #MyTempTable -- this line was uncomment
EXEC (#SQL)
IF EXISTS(SELECT 1 FROM #MyTempTable) -- It was like this: SearchTMP
BEGIN
SELECT #MatchFound = 1
INSERT INTO #output (Id, Name)
Select * from [DynaForms].[dbo].[Enums_Tables] where id in (SELECT parsename(#tmpTblname,1) FROM #MyTempTable) -- It was like this: SearchTMP
END
END
ELSE
BEGIN
PRINT REPLICATE('-',100)
PRINT #tmpTblname
PRINT REPLICATE('-',100)
PRINT replace(#SQL,'INTO #MyTempTable','')
END
UPDATE #SQLTbl
SET Execstatus = 1
WHERE Tablename = #tmpTblname
END
SELECT * FROM #output
IF #MatchFound = 0
BEGIN
SELECT #ErrMsg = 'No Matches are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
SET NOCOUNT OFF
OK, so a quick test actually answered this, and i can't believe I missed this (/facepalm). you can't use a INTO clause with dynamic SQL and a Temporary table and reference it afterwards; you need to CREATE the table. Consider the following:
DECLARE #SQL varchar(max);
SET #SQL = 'SELECT 1 AS A, 2 AS B INTO #test;';
EXEC (#SQL);
SELECT *
FROM #test;
DROP TABLE #test;
This returns the error:
Msg 208, Level 16, State 0, Line 5
Invalid object name '#test'.
And now, for the correct way:
DECLARE #SQL varchar(max);
CREATE TABLE #test (A int, B int);
SET #SQL = 'INSERT INTO #test SELECT 1 AS A, 2 AS B';
EXEC (#SQL);
SELECT *
FROM #test;
DROP TABLE #test;
This works fine. Thus, you need to CREATE your temporary table, not use an INTO clause.
Instead of
Object_Id('#MyTempTable','U')
You need to use
Object_Id('tempdb..#MyTempTable','U')
To get the object_id of the temporary table to check if it exists or not.
Temp tables are created in TempDB system database

Temp Table - Temporary table is empty - SQL Server

I know this question I'm about to ask is quite common, but I haven't been able to use other examples to my own.
I have a stored procedure that uses a table Enum_Tables (this table has other table names) to search the entire database for a specific string. The results are stored in a table which gives me the specific rows of Enum_Tables that I want.
Currently the stored is working properly, but right now it is creating SearchTMP in the Database. And I don't want that, What I want is creating a temporary table like #SearchTMP. I created the temporary table, I tried to populated it, but It is empty.
The part I'm talking about is inside the while logic (WHILE EXISTS (SELECT 1 FROM #SQLTbl WHERE ISNULL(Execstatus ,0) = 0) ).
It's checking if there is values in SearchTMP, and since it's not a temporary table, it's creating one in the database. I want to change it to a #SearchTMP. I I created the table, but I'm not being able to populated it, since I wan't being able to do it, I deleted that code. I know I need to do an insert, but how can I do it without changing to much code, and maintain the same logic.
This is my stored procedure code:
ALTER PROCEDURE [dbo].[SearchTables_TEST]
--#Tablenames VARCHAR(500)
#SearchStr NVARCHAR(60),
#GenerateSQLOnly Bit = 0,
#SchemaNames VARCHAR(500) ='%'
AS
SET NOCOUNT ON
DECLARE #MatchFound BIT
SELECT #MatchFound = 0
DECLARE #CheckTableNames Table (Schemaname sysname, Tablename sysname)
DECLARE #SearchStringTbl TABLE (SearchString VARCHAR(500))
DECLARE #SQLTbl TABLE (Tablename SYSNAME,
WHEREClause VARCHAR(MAX),
SQLStatement VARCHAR(MAX),
Execstatus BIT
)
DECLARE #SQL VARCHAR(MAX)
DECLARE #TableParamSQL VARCHAR(MAX)
DECLARE #SchemaParamSQL VARCHAR(MAX)
DECLARE #TblSQL VARCHAR(MAX)
DECLARE #tmpTblname sysname
DECLARE #ErrMsg VARCHAR(100)
IF LTRIM(RTRIM(#SchemaNames)) =''
BEGIN
SELECT #SchemaNames = '%'
END
--IF CHARINDEX(',',#Tablenames) > 0
-- SELECT #TableParamSQL = 'SELECT ''' + REPLACE(#Tablenames,',','''as TblName UNION SELECT ''') + ''''
--ELSE
-- SELECT #TableParamSQL = 'SELECT ''' + #Tablenames + ''' as TblName '
IF CHARINDEX(',',#SchemaNames) > 0
SELECT #SchemaParamSQL = 'SELECT ''' + REPLACE(#SchemaNames,',','''as SchemaName UNION SELECT ''') + ''''
ELSE
SELECT #SchemaParamSQL = 'SELECT ''' + #SchemaNames + ''' as SchemaName '
SELECT #TblSQL = 'SELECT SCh.NAME,T.NAME
FROM SYS.TABLES T
JOIN SYS.SCHEMAS SCh
ON SCh.SCHEMA_ID = T.SCHEMA_ID
INNER JOIN [DynaForms].[dbo].[Enums_Tables] et on
(et.Id = T.NAME COLLATE Latin1_General_CI_AS) '
INSERT INTO #CheckTableNames
(Schemaname,Tablename)
EXEC(#TblSQL)
IF NOT EXISTS(SELECT 1 FROM #CheckTableNames)
BEGIN
SELECT #ErrMsg = 'No tables are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
IF LTRIM(RTRIM(#SearchStr)) =''
BEGIN
SELECT #ErrMsg = 'Please specify the search string in #SearchStr Parameter'
PRINT #ErrMsg
RETURN
END
ELSE
BEGIN
SELECT #SearchStr = REPLACE(#SearchStr,',,,',',#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,',,','#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,'''','''''')
SELECT #SQL = 'SELECT ''' + REPLACE(#SearchStr,',','''as SearchString UNION SELECT ''') + ''''
INSERT INTO #SearchStringTbl
(SearchString)
EXEC(#SQL)
UPDATE #SearchStringTbl
SET SearchString = REPLACE(SearchString ,'#DOUBLECOMMA#',',')
END
INSERT INTO #SQLTbl
( Tablename,WHEREClause)
SELECT QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(
SELECT '[' + SC.Name + ']' + ' LIKE ''' + REPLACE(SearchSTR.SearchString,'''','''''') + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy
ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
CROSS JOIN #SearchStringTbl SearchSTR
WHERE STY.name in ('varchar','char','nvarchar','nchar','text')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM SYS.tables ST
JOIN #CheckTableNames chktbls
ON chktbls.Tablename = ST.name
JOIN SYS.schemas SCh
ON ST.schema_id = SCh.schema_id
AND Sch.name = chktbls.Schemaname
WHERE ST.name <> 'SearchTMP'
GROUP BY ST.object_id, QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME) ;
UPDATE #SQLTbl SET SQLStatement = 'SELECT * INTO SearchTMP FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5) -- this line was uncomment
DELETE FROM #SQLTbl
WHERE WHEREClause IS NULL
DECLARE #output TABLE (Id VARCHAR(50), Name VARCHAR(100))
Create Table #SearchTMP (searchparameter varchar(200))
WHILE EXISTS (SELECT 1 FROM #SQLTbl WHERE ISNULL(Execstatus ,0) = 0)
BEGIN
SELECT TOP 1 #tmpTblname = Tablename , #SQL = SQLStatement
FROM #SQLTbl
WHERE ISNULL(Execstatus ,0) = 0
IF #GenerateSQLOnly = 0
BEGIN
IF OBJECT_ID('SearchTMP','U') IS NOT NULL -- this line was uncomment
DROP TABLE SearchTMP -- this line was uncomment
EXEC (#SQL)
IF EXISTS(SELECT 1 FROM SearchTMP)
BEGIN
--SELECT parsename(#tmpTblname,1) FROM SearchTMP
SELECT #MatchFound = 1
INSERT INTO #output (Id, Name)
Select * from [DynaForms].[dbo].[Enums_Tables] where id in (SELECT parsename(#tmpTblname,1) FROM SearchTMP)
END
END
ELSE
BEGIN
PRINT REPLICATE('-',100)
PRINT #tmpTblname
PRINT REPLICATE('-',100)
PRINT replace(#SQL,'INTO SearchTMP','')
END
UPDATE #SQLTbl
SET Execstatus = 1
WHERE Tablename = #tmpTblname
END
SELECT * FROM #output
IF #MatchFound = 0
BEGIN
SELECT #ErrMsg = 'No Matches are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
SET NOCOUNT OFF
When you want to use a temp table in a dynamic query, you have to create said temp table first, then populate it in the dynamic query.
CREATE TABLE #MyTempTable (ID INT NOT NULL);
DECLARE #STMT NVARCHAR(MAX) = N'INSERT INTO #MyTempTable (ID) SELECT ID FROM MyTable;';
EXEC sp_executesql
#stmt = #STMT
;
SELECT ID FROM #MyTempTable;
Since the temp table is created in the stored procedure, it is scoped to that stored procedure and will be dropped automatically when the SP finishes.
If you want to use said temp table outside of the SP, you have to create it outside of the SP. (If it is part of the batch, the temp table will be dropped when the connection is closed or you can drop it explicitly).

Can you return the results a query from table and Fields returned in a query

The following is the results of a query used to Search Columns
DECLARE #Temp TABLE (
[CoreTable] VARCHAR(250),
[CoreTableDecription] VARCHAR(250),
[FieldName] VARCHAR(250),
[cnt] VARCHAR(250)
)
declare #Keyword1 VARCHAR(100) = '%Prob%'
declare #Keyword2 VARCHAR(100) = '%Prob%'
--------------------------------------------------------------
INSERT INTO #Temp (CoreTable, CoreTableDecription, FieldName, cnt)
VALUES
('PRO','PROTOS_PersonalInformation','AnyCommunicationProblem','1'),
('PRO','PROTOS_PersonalInformation','SightProblems','1'),
('PRO','PROTOS_PersonalInformation','SpeechProblems','1'),
('PRO','PROTOSMODEL_Antenatal_Status','Other_Antenatal_Problems','1'),
('PRO','PROTOSMODEL_Antenatal_Status','Other_Antenatal_Problems_Text','1'),
('PRO','PROTOSMODEL_Baby_Details','Neonatal_medical_problems','1'),
('PRO','PROTOSMODEL_Baby_Details','Neonatal_medical_problems_Text','1'),
('PRO','PROTOSMODEL_Baby_Postnatal','Any_skin_problems_detected','1'),
('PRO','PROTOSMODEL_Baby_Postnatal','Any_skin_problems_detected_Bruising','1'),
('PRO','PROTOSMODEL_Baby_Postnatal','Any_skin_problems_detected_Naevus','1'),
('PRO','PROTOSMODEL_Baby_Postnatal','Any_skin_problems_detected_Rash','1'),
('PRO','PROTOSMODEL_Baby_Postnatal','Any_skin_problems_detected_Text','1')
Select * from #Temp
This is great for finding/search and the query used is below
declare #Keyword1 VARCHAR(100) = '%Prob%'
declare #Keyword2 VARCHAR(100) = '%Prob%'
select
LEFT(o.name,3) CoreTable,
o.name CoreTableDesc,
--o.name AS TableName,
c.name AS FieldName
,COUNT(c.name) cnt
from sys.columns c
inner join sys.objects o on c.object_id=o.object_id
where c.name LIKE #Keyword1
and LEFT(o.name,3) in ('PRO')
and c.name LIKE #Keyword2
GROUP BY c.name, LEFT(o.name,3), o.name
-- order by LEFT(o.name,3), c.name
However what I then need to do is run a manual query to determine the values in the columns/tables (see below):
select AnyCommunicationProblem, count(*) cnt
from PROTOS_PersonalInformation
GROUP BY AnyCommunicationProblem
This returns simplythe rows NULL - 2682, No - 87687, Yes - 135478
I'm wondering if there is a way to do this automatically from the results of the first query which display the Table name and Column names
Thanks all the answer was below but I was unsure how to get the count if the data items in
DECLARE
#TABLENAME VARCHAR(255),
#FIELDNAME VARCHAR(255),
#SQL VARCHAR(MAX),
#FieldNamePart1 as varchar(50),
#FieldNamePart2 as varchar(50)
SET #SQL = ''
SET #FieldNamePart1 = 'Type'
SET #FieldNamePart2 = 'Method'
IF #FieldNamepart2 = ''
DECLARE CRS CURSOR FOR
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE CHARINDEX('PROTOSMODEL',TABLE_NAME) <> 0
AND CHARINDEX(#FieldNamePart1, COLUMN_NAME) <> 0
-- AND CHARINDEX('DATE', COLUMN_NAME) = 0
-- AND CHARINDEX('TIME', COLUMN_NAME) = 0
ELSE
DECLARE CRS CURSOR FOR
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE CHARINDEX('PROTOSMODEL',TABLE_NAME) <> 0
AND CHARINDEX(#FieldNamePart1, COLUMN_NAME) <> 0
AND CHARINDEX(#FieldNamePart2, COLUMN_NAME) <> 0
-- AND CHARINDEX('DATE', COLUMN_NAME) = 0
-- AND CHARINDEX('TIME', COLUMN_NAME) = 0
OPEN CRS
FETCH NEXT FROM CRS INTO #TABLENAME, #FIELDNAME
WHILE ##FETCH_STATUS = 0
BEGIN
-- SET #SQL = #SQL + CAST('SELECT DISTINCT ''' AS VARCHAR(MAX)) + CAST(#TABLENAME AS VARCHAR(MAX)) + CAST(''' AS PROTOSMODEL_TABLE, ''' AS VARCHAR(MAX)) + CAST(#FIELDNAME AS VARCHAR(MAX)) + CAST(''' AS PROTOSMODEL_FIELD, ' AS VARCHAR(MAX)) + CAST(#FIELDNAME AS VARCHAR(MAX)) + CAST(' AS FIELD_VALUE FROM ' AS VARCHAR(MAX)) + CAST(#TABLENAME AS VARCHAR(MAX)) + CAST(' UNION ALL ' AS VARCHAR(MAX))
SET #SQL = #SQL + 'SELECT DISTINCT ''' + #TABLENAME + ''' AS PROTOSMODEL_TABLE, ''' + #FIELDNAME + ''' AS PROTOSMODEL_FIELD, [' + #FIELDNAME + '] AS FIELD_VALUE FROM ' + #TABLENAME + ' UNION ALL '
FETCH NEXT FROM CRS INTO #TABLENAME, #FIELDNAME
END
CLOSE CRS
DEALLOCATE CRS
SET #SQL = SUBSTRING(#SQL, 1, LEN(#SQL) - 10)
EXEC (#SQL)
GO

Resources