SQL Server - 从表中传递Id并检查数据库

时间:2017-11-09 11:01:56

标签: c# sql-server stored-procedures

我正在尝试编写一个存储过程来搜索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中原始存储过程的问题。

1 个答案:

答案 0 :(得分:0)

您链接到的存储过程已经具有检查数据库中的表名的逻辑,并使用要检查的表列表填充表变量。只需将此逻辑更改为从ENUM_TABLES表中选择。如果您愿意,这可以基于@Id的输入参数...

简单来说:

  1. 从存储过程中删除参数@TableNames
  2. (可选)将参数替换为@ENUM_TABLE_ID或其他内容
  3. 更改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

  4. 更像这样的事情:

    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降价处理器真的不喜欢那些东西,但希望可读。如果有人想尝试编辑它来改进它,那就是我的客。)