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
Related
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
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).
I would like to create the stored procedure and generate insert statement for the table dynamically. The input parameters for the stored procedure are supposed to be schema, table name, #col1, #col2, ..., #colN. This stored procedure is supposed to take 1 random record from another server and based on this record is supposed to generate INSERT statement. #col1, #col2, ..., #colN parameters are optional in case you would like to overwrite original value with the one you need.
The insert record is supposed to look like that:
INSERT INTO schema_name.table_name VALUES (
col1,
col2,
...,
colN)
VALUES (
COALESCE(#col1, 'col1_value'),
COALESCE(#col2, 'col2_value'),
...,
COALESCE(#colN, 'colN_value')
);
Currently I can not realize how to take the real data and put it to the statement. What I already did is:
CREATE PROCEDURE dbo.GenerateSampleDataInsertSP
#SchemaName VARCHAR(255),
#TableName VARCHAR(255)
AS
SET NOCOUNT ON;
DECLARE #sql VARCHAR(MAX) = '',
#columns VARCHAR(MAX) = '',
#columnsWithCoalesce VARCHAR(MAX) = '';
SELECT c.name
INTO #column
FROM sys.tables t
JOIN sys.schemas s ON s.schema_id = t.schema_id
JOIN sys.columns c ON c.object_id = t.object_id
JOIN sys.types tt ON c.system_type_id = tt.system_type_id
WHERE t.name = #TableName
AND s.name = #SchemaName
AND tt.name NOT IN ( 'timestamp' );
SET #columns = NULL;
SELECT #columns = ISNULL(#columns + ', ', '') + name
FROM #column;
SET #sql = 'SELECT TOP 1 ' + #columns + ' FROM AnotherDatabase.' + #SchemaName + '.' + #TableName + ' ORDER BY NEWID();';
SET #sql = 'INSERT INTO [' + #SchemaName + '].[' + #TableName + '] (' + #columns + ') VALUES ();';
SELECT #sql;
I do not care about ideal code or solution. I need result and that's it.
UPDATED:
-- Example #1
USE tempdb
GO
/*CREATE PROCEDURE dbo.GenerateSampleDataInsertSP ...*/
CREATE TABLE dbo.Employee (ID INT, EmployeeName VARCHAR(255));
INSERT INTO dbo.Employee VALUES (1, 'John Smith');
EXEC dbo.GenerateSampleDataInsertSP #SchemaName = 'dbo', #TableName = 'Employees';
------------------------ EXPECTED OUTPUT OF THE PROCEDURE (NOT THE ACTION, BUT PLAIN TEXT) ------------------
INSERT INTO dbo.Employee
(
ID,
EmployeeName
)
VALUES
(
COALESCE(#ID, '1'),
COALESCE(#EmployeeName, 'John Smith')
);
-- Example #2
USE tempdb
GO
/*CREATE PROCEDURE dbo.GenerateSampleDataInsertSP ...*/
CREATE TABLE dbo.Orders (ID INT, OrderNbr VARCHAR(10), OrderDate DATE, CustomerID ID);
INSERT INTO dbo.Orders VALUES (7, '12345678', GETDATE(), 1024);
EXEC dbo.GenerateSampleDataInsertSP #SchemaName = 'dbo', #TableName = 'Orders';
------------------------ EXPECTED OUTPUT OF THE PROCEDURE (NOT THE ACTION, BUT PLAIN TEXT) ------------------
INSERT INTO dbo.Orders
(
ID,
OrderNbr,
OrderDate,
CustomerId
)
VALUES
(
COALESCE(#ID, '7'),
COALESCE(#OrderNbr,'12345678'),
COALESCE(#OrderDate, '2015-07-05'),
COALESCE(#CustomerId, '1024')
);
Ok, I'll answer my own question. As I said that I do not care about the code beauty and performance, I just need the result so anyone who would provide more elegant solution would be accepted as solved solution. Here is the code:
CREATE PROCEDURE dbo.GenerateSampleDataInsertSP
#SchemaName VARCHAR(255),
#TableName VARCHAR(255)
AS
SET NOCOUNT ON;
IF EXISTS ( SELECT name
FROM tempdb.sys.tables
WHERE name LIKE '%##record%' )
BEGIN
DROP TABLE ##record;
END;
DECLARE #sql VARCHAR(MAX) = '',
#columns VARCHAR(MAX) = '',
#columnsWithCoalesce VARCHAR(MAX) = '';
SELECT c.name
INTO #column
FROM sys.tables t
JOIN sys.schemas s ON s.schema_id = t.schema_id
JOIN sys.columns c ON c.object_id = t.object_id
JOIN sys.types tt ON c.system_type_id = tt.system_type_id
WHERE t.name = #TableName
AND s.name = #SchemaName
AND tt.name NOT IN ( 'timestamp' );
SET #columns = NULL;
SELECT #columns = ISNULL(#columns + ', ', '') + name
FROM #column;
SET #sql = 'SELECT TOP 1 ' + #columns + ' INTO ##record FROM AnotherDataBase.' + #SchemaName + '.' + #TableName + ' ORDER BY NEWID();';
EXEC (#sql);
SET #sql = 'INSERT INTO [' + #SchemaName + '].[' + #TableName + '] (' + #columns + ') VALUES (';
DECLARE #columnsCur CURSOR, #ColumnName VARCHAR(255), #tmpValue VARCHAR(MAX), #sqlCommand nvarchar(1000);
SET #columnsCur = CURSOR FOR
SELECT name
FROM #column;
OPEN #columnsCur;
FETCH NEXT
FROM #columnsCur INTO #ColumnName;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sqlCommand = 'SELECT #value=CAST(' + #ColumnName + ' AS VARCHAR(MAX)) FROM ##record;'
EXECUTE sp_executesql #sqlCommand, N'#value VARCHAR(MAX) OUTPUT', #value=#tmpValue OUTPUT
SET #sql = #sql + 'COALESCE(#'+ #ColumnName +', ''' + #tmpValue + '''),';
FETCH NEXT
FROM #columnsCur INTO #ColumnName;
END;
CLOSE #columnsCur;
DEALLOCATE #columnsCur;
SET #sql = #sql + ');'
SET #sql = REPLACE(#sql, ',);', ');');
SELECT #sql;
GO
I am trying to search my whole database with a search string. For this I need to check tables, views, stored procedures + all data in all tables.
I am able to scucessfully search all the database objects , however there is a little problem when i need to search a table , i need to search the cells , if the search string exists in that particular cell , i need to show the Table Name , All the columns on that particular Row and Column name of the cell where the search string is found .
i was using code by Sorna Kumar Maduraj to get the whole rows , where i am stuck is on to display the columns for where the search string is found
For example
A Table named Searchtable has the searchstring in i searched for (lets assume it to be AdminCd) in a particular row in 2 different columns (Lets say column names are ColumnA, ColumnB)
My output would be Table Name - Row Data - ColumnNames (ColumnA, ColumnB)
My only issue lies is that suppose in a same table , a row contains the string in 2 columns and a different rows contain the searchstring in 4 columns , i need to show the columns differently as the output
the code i used , ill tie it up below
DECLARE #Tablenames VARCHAR(500)
DECLARE #SearchStr NVARCHAR(60)
DECLARE #GenerateSQLOnly Bit = 0
SET #Tablenames = 'TableName'
SET #SearchStr = '%AdminCd%'
SET NOCOUNT ON
DECLARE #MatchFound BIT -- To check wether any match is found or not
SELECT #MatchFound = 0
DECLARE #CheckTableNames Table -- To check the tables that need to be searched
(
Tablename sysname
)
DECLARE #SQLTbl TABLE -- For Table Name
(
Tablename SYSNAME
,WHEREClause VARCHAR(MAX)
,SQLStatement VARCHAR(MAX)
,Execstatus BIT
)
DECLARE #SQL VARCHAR(MAX)
DECLARE #tmpTblname sysname
DECLARE #ErrMsg VARCHAR(100)
IF LTRIM(RTRIM(#Tablenames)) IN ('' ,'%')
BEGIN
INSERT INTO #CheckTableNames
SELECT Name
FROM sys.tables
END
ELSE
BEGIN
SELECT #SQL = 'SELECT ''' + REPLACE(#Tablenames,',',''' UNION SELECT ''') + ''''
INSERT INTO #CheckTableNames
EXEC(#SQL)
END
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
INSERT INTO #SQLTbl
( Tablename,WHEREClause)
SELECT QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(
SELECT '[' + SC.Name + ']' + ' LIKE ''' + #SearchStr + ''' 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
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
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)
DELETE FROM #SQLTbl
WHERE WHEREClause IS NULL
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
DROP TABLE SearchTMP
EXEC (#SQL)
IF EXISTS(SELECT 1 FROM SearchTMP)
BEGIN
SELECT Tablename=#tmpTblname,* FROM SearchTMP
SELECT #MatchFound = 1
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
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
go
For a given sql 2000 - 2008 server I want to find any table named dbo.[MyTable] on that server. In addition, how do I find all databases that have a table named [dbo].[MyTable] and [AnySchemaName].[MyTable]. Is there a simple sp_ command like spTables MyTable? Or 'sp_AllDatabaseTable [MyTable]'?
I want to print it out like:
ServerName Database SchemaName MyTable Date Created
----------- --------- ----------- --------- -------------
Thx
I really would prefer a solution that does not use either CURSORS nor sp_msforeachdb.
The solution below is gives you an idea, and you can adapt it to your own needs.
USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
BEGIN TRY
SET NOCOUNT ON
SET DATEFORMAT DMY
SET DEADLOCK_PRIORITY NORMAL;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
DECLARE #log NVARCHAR(MAX)
,#vCrlf CHAR(2);
SELECT #log = ''
,#vCrlf = CHAR(13)+CHAR(10);
DECLARE #SQL NVARCHAR(MAX)
BEGIN TRY DROP TABLE #OBJECTS END TRY BEGIN CATCH END CATCH
CREATE TABLE #OBJECTS(
DB_ID INT,
OBJECT_ID INT,
S_NAME SYSNAME,
NAME SYSNAME,
ROW_COUNT INT,
STATISTICS_UPDATED DATETIME)
SELECT #SQL = '
SELECT db_id=db_id(),
o.object_id,
s_name=s.name,
o.name,
ddps.row_count
,[Statistics_Updated]=STATS_DATE(I.OBJECT_ID,I.INDEX_ID)
FROM sys.indexes AS i
INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID
INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID
AND i.index_id = ddps.index_id
WHERE i.index_id < 2
AND o.is_ms_shipped = 0
'
set #SQL = (
SELECT STUFF(
(SELECT N' ' + ' USE ' + QUOTENAME(name) +';' + #vCrlf + #SQL + #vCrlf
FROM SYS.DATABASES SD
WHERE SD.STATE_DESC = 'ONLINE' -->Skips the database if it is not online
AND SD.COMPATIBILITY_LEVEL > 80
AND SD.database_id > 3 -- NO MASTER NOR TEMPDB NOR MODEL
FOR XML PATH(''),TYPE)
.value('text()[1]','nvarchar(max)'),1,2,N'')
)
INSERT INTO #OBJECTS
( [db_id],
[object_id],
[s_name],
[name],
[row_count],
[Statistics_Updated]
)
EXECUTE MASTER.DBO.sp_executesql #SQL
SELECT * FROM #OBJECTS
--WHERE NAME = 'THE NAME THAT I AM LOOKING FOR'
END TRY
BEGIN CATCH
PRINT '--EXCEPTION WAS CAUGHT--' + CHAR(13) +
'THE ERROR NUMBER:' + COALESCE(CAST ( ERROR_NUMBER() AS VARCHAR), 'NO INFO') + CHAR(13)
PRINT 'SEVERITY: ' + COALESCE(CAST ( ERROR_SEVERITY() AS VARCHAR), 'NO INFO') + CHAR(13) +
'STATE: ' + COALESCE(CAST ( ERROR_STATE() AS VARCHAR), 'NO INFO') + CHAR(13)
PRINT 'PROCEDURE: ' + COALESCE(CAST ( COALESCE(ERROR_PROCEDURE(),'NO INFO') AS VARCHAR), 'NO INFO') + CHAR(13) +
'LINE NUMBER: ' + COALESCE(CAST ( ERROR_LINE() AS VARCHAR), 'NO INFO') + CHAR(13)
PRINT 'ERROR MESSAGE: '
PRINT CAST ( COALESCE(ERROR_MESSAGE(),'NO INFO') AS NTEXT)
END CATCH;
I prefer a set based approach:
Declare #TableName as Varchar(255)
Set #TableName = '<MyTableName>'
Declare #SQL as Varchar(max)
Select #SQL = Coalesce(#SQL + '
', '') +
CASE
WHEN Row_Number() Over (Order by Database_ID) = 1
THEN ''
ELSE
'UNION ALL '
END +
'SELECT
''' + d.Name + ''' as DatabaseName
, s.Name as SchemaName
, o.Name as TableName
FROM ' + d.Name +'.Sys.Objects o
INNER JOIN ' + d.Name + '.Sys.Schemas s
ON o.Schema_ID = s.Schema_ID
WHERE o.Name like ''' + #TableName + ''''
FROM sys.databases d
where d.Name not like 'ReportServer%'
and d.Name not like 'SSISPackageRegistry'
Print #SQL
EXEC(#SQL)
Of course, you can use sp_msforeachdb for this purpose but you need to remember that fhis function is neither documented nor officially supported. Also, sometimes it breaks. More about it here Making a more reliable and flexible sp_MSforeachdb
You can use this script to search table by name in all databases.
I took it from Find table in every database of SQL server
DECLARE #TableName VARCHAR(256)
SET #TableName='YOUR_TABLE_NAME'
DECLARE #DBName VARCHAR(256)
DECLARE #varSQL VARCHAR(512)
DECLARE #getDBName CURSOR
SET #getDBName = CURSOR FOR
SELECT name
FROM sys.databases
CREATE TABLE #TmpTable (DBName VARCHAR(256),
SchemaName VARCHAR(256),
TableName VARCHAR(256),
create_date date, modify_date date)
OPEN #getDBName
FETCH NEXT
FROM #getDBName INTO #DBName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #varSQL = 'USE ' + #DBName + ';
INSERT INTO #TmpTable
SELECT '''+ #DBName + ''' AS DBName,
SCHEMA_NAME(schema_id) AS SchemaName,
name AS TableName,
create_date, modify_date
FROM sys.tables
WHERE name LIKE ''%' + #TableName + '%''' --WHERE name = '' + #TableName + ''' /* if you want to search by exact table name*/
EXEC (#varSQL)
FETCH NEXT
FROM #getDBName INTO #DBName
END
CLOSE #getDBName
DEALLOCATE #getDBName
SELECT *
FROM #TmpTable
DROP TABLE #TmpTable
Also, you may want to read this Find table name in all objects of all databases
I'd have said
sp_msforeachdb 'Select * from Sysobjects where name=''MyTable'''
But you don't need to, sysobjects is in the master table and does it for all databases anyway.
You should be able find the other columns easily enough.