我正在尝试编写一个存储过程来搜索SQL Server数据库的所有表中的字符串。我能够找到一个很好的存储过程for this purpose
但是,我不想手动放置@Tablenames
,我希望它转到名为Enums_Tables
的具有ID的表,并将该ID用作@Tablenames
。
我一直在考虑解决这个问题:
我可以编写另一个存储过程来从Enums_Tables
中选择所有Id并执行第一个存储过程like in here
我也可以在C#中传递参数,因为我将把它用作搜索文本框。但理想的是制作一个存储过程。
你能帮帮我吗?
修改
感谢 GPW ,我已经能够解决这个问题。我也遇到了整理问题,但我也解决了。以下是最终存储过程。
USE [DynaForms]
GO
/****** Object: stored procedure [dbo].[SP_SearchTables] Script Date: 09/11/2017 14:59:15 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_SearchTables]
--@Tablenames VARCHAR(500)
@SearchStr NVARCHAR(60)
,@GenerateSQLOnly Bit = 0
,@SchemaNames VARCHAR(500) ='%'
AS
/*
Parameters and usage
@Tablenames -- Provide a single table name or multiple table name with comma seperated.
If left blank , it will check for all the tables in the database
Provide wild card tables names with comma seperated
EX :'%tbl%,Dim%' -- This will search the table having names comtains "tbl" and starts with "Dim"
@SearchStr -- Provide the search string. Use the '%' to coin the search. Also can provide multiple search with comma seperated
EX : X%--- will give data staring with X
%X--- will give data ending with X
%X%--- will give data containig X
%X%,Y%--- will give data containig X or starting with Y
%X%,%,,% -- Use a double comma to search comma in the data
@GenerateSQLOnly -- Provide 1 if you only want to generate the SQL statements without seraching the database.
By default it is 0 and it will search.
@@SchemaNames -- Provide a single Schema name or multiple Schema name with comma seperated.
If left blank , it will check for all the tables in the database
Provide wild card Schema names with comma seperated
EX :'%dbo%,Sales%' -- This will search the Schema having names comtains "dbo" and starts with "Sales"
Samples :
1. To search data in a table
EXEC SP_SearchTables @Tablenames = 'T1'
,@SearchStr = '%TEST%'
The above sample searches in table T1 with string containing TEST.
2. To search in a multiple table
EXEC SP_SearchTables @Tablenames = 'T2'
,@SearchStr = '%TEST%'
The above sample searches in tables T1 & T2 with string containing TEST.
3. To search in a all table
EXEC SP_SearchTables @Tablenames = '%'
,@SearchStr = '%TEST%'
The above sample searches in all table with string containing TEST.
4. Generate the SQL for the Select statements
EXEC SP_SearchTables @Tablenames = 'T1'
,@SearchStr = '%TEST%'
,@GenerateSQLOnly = 1
5. To Search in tables with specfic name
EXEC SP_SearchTables @Tablenames = '%T1%'
,@SearchStr = '%TEST%'
,@GenerateSQLOnly = 0
6. To Search in multiple tables with specfic names
EXEC SP_SearchTables @Tablenames = '%T1%,Dim%'
,@SearchStr = '%TEST%'
,@GenerateSQLOnly = 0
7. To specify multiple search strings
EXEC SP_SearchTables @Tablenames = '%T1%,Dim%'
,@SearchStr = '%TEST%,TEST1%,%TEST2'
,@GenerateSQLOnly = 0
8. To search comma itself in the tables use double comma ",,"
EXEC SP_SearchTables @Tablenames = '%T1%,Dim%'
,@SearchStr = '%,,%'
,@GenerateSQLOnly = 0
EXEC SP_SearchTables @Tablenames = '%T1%,Dim%'
,@SearchStr = '%with,,comma%'
,@GenerateSQLOnly = 0
9. To Search by SchemaName
EXEC SP_SearchTables @Tablenames = '%T1%,Dim%'
,@SearchStr = '%,,%'
,@GenerateSQLOnly = 0
,@SchemaNames = '%dbo%,Sales%'
*/
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(@Tablenames)) IN ('' ,'%')
BEGIN
INSERT INTO @CheckTableNames
SELECT Name
FROM sys.tables
END
ELSE
BEGIN
IF CHARINDEX(',',@Tablenames) > 0
SELECT @SQL = 'SELECT ''' + REPLACE(@Tablenames,',','''as TblName UNION SELECT ''') + ''''
ELSE
SELECT @SQL = 'SELECT ''' + @Tablenames + ''' as TblName '
SELECT @TblSQL = 'SELECT T.NAME
FROM SYS.TABLES T
JOIN (' + @SQL + ') tblsrc
ON T.name LIKE tblsrc.tblname '
INSERT INTO @CheckTableNames
EXEC(@TblSQL)
END
*/
--IF LTRIM(RTRIM(@Tablenames)) = ''
--BEGIN
-- SELECT @Tablenames = '%'
--END
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)
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
对于奇怪的格式提前抱歉,我不能把它更具可读性。我希望它对某人有帮助。我还想赞扬here中原始存储过程的问题。
答案 0 :(得分:0)
您链接到的存储过程已经具有检查数据库中的表名的逻辑,并使用要检查的表列表填充表变量。只需将此逻辑更改为从ENUM_TABLES
表中选择。如果您愿意,这可以基于@Id
的输入参数...
简单来说:
@TableNames
@ENUM_TABLE_ID
或其他内容更改SP中的代码如下所示:
IF LTRIM(RTRIM(@Tablenames)) = ''
/* Removed a load of lines looking at @TableNames...... */
....
SELECT @TblSQL = 'SELECT SCh.NAME,T.NAME
FROM SYS.TABLES T
JOIN SYS.SCHEMAS SCh
ON SCh.SCHEMA_ID = T.SCHEMA_ID
JOIN (' + @TableParamSQL + ') tblsrc
ON T.name LIKE tblsrc.tblname
JOIN (' + @SchemaParamSQL + ') schemasrc
ON SCh.name LIKE schemasrc.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 ENUM_TABLES et on
(et.TABLENAME=T.NAME)
and (et.Id='+@ENUM_TABLE_ID+')'
然后我认为它会做你想要的(根据传入存储过程的ID从另一个表中查找表的列表)
(对于上面SQL的稍微奇怪的格式化道歉;由于某种原因,SO降价处理器真的不喜欢那些东西,但希望可读。如果有人想尝试编辑它来改进它,那就是我的客。)