1

ユーザーは検索キーワードを 1 つ以上のデータベースに渡し、複数のテーブルで各単語を検索し、単語が見つかった行数を数えます。

だから私がしたことはここにあります..単語配列から各単語をループし、この単語を各テーブルにパスワード付けて、行数を取得していました。複数のキーワードと 590 をテーブルで検索しているときに、ここでタイムアウト エラーが発生します。キーワードをループし、テーブルを複数回呼び出すためです。私のコードを見てください。

VB.NET コード

 For Each keyword As String In keywords
    For Each lstOfSelectedTable As String In lstOfSelectedTables
        Dim words As List(Of String) = lstOfSelectedTable.Split("."c).ToList()
            If words.Count > 1 Then
               dbName = words(0)
               schema = words(1)
               tableName = words(2)
               If strKeywords.Length > 0 Then
                  dtExcel = FillData(keyword, schema, tableName, serverName, dbName)
                  If dtExcel.Rows.Count > 0 Then
                     If CType(dtExcel.Rows(0).Item(3), Integer) > 0 Then
                        ds.Tables.Add(dtExcel)
                     End If
                  End If

               End If
        End If
 Next

ストアド プロシージャ

ALTER PROCEDURE [dbo].[sp_FindStringInTable] @stringToFind VARCHAR(100), @schema sysname, @table sysname, @dbname varchar(100)
AS 


DECLARE @sqlCommand NVARCHAR(Max) 
DECLARE @where NVARCHAR(Max)
DECLARE @columnName sysname 
DECLARE @cursor VARCHAR(8000) 


BEGIN TRY 
   SET @sqlCommand = 'SELECT '''+ @stringToFind +''' as ''Keyword'','''+@dbname +''' As ''Database'', '''+ @table +''' as ''Table'',count(*) as Count FROM [' + @dbname + '].[' + @schema + '].[' + @table + '] WHERE' 
   SET @where = '' 


   SET @cursor = 'DECLARE col_cursor CURSOR FOR SELECT COLUMN_NAME 
   FROM ' + @dbname + '.INFORMATION_SCHEMA.COLUMNS 
   WHERE TABLE_SCHEMA = ''' + @schema + ''' 
   AND TABLE_NAME = ''' + @table + ''' 
   AND DATA_TYPE IN (''char'',''nchar'',''ntext'',''nvarchar'',''text'',''varchar'')' 


  PRINT @cursor
   EXEC (@cursor) 

   OPEN col_cursor    
   FETCH NEXT FROM col_cursor INTO @columnName    

   WHILE @@FETCH_STATUS = 0    
   BEGIN    
       IF @where <> '' 
           SET @where = @where + ' OR'

       SET @where = @where + ' [' + @columnName + '] LIKE ''%' + @stringToFind + '%''' 
       FETCH NEXT FROM col_cursor INTO @columnName 
       PRINT @columnName   
   END    


   CLOSE col_cursor    
   DEALLOCATE col_cursor  


   SET @sqlCommand = @sqlCommand + @where 
   PRINT @sqlCommand 
    IF @where <> '' 
        EXEC (@sqlCommand)  
    ELSE
        RETURN 

END TRY 
BEGIN CATCH 
 SELECT 
        ERROR_NUMBER() AS ErrorNumber
        ,ERROR_MESSAGE() AS ErrorMessage;
   PRINT 'There was an error. Check to make sure object exists.' 
   IF CURSOR_STATUS('variable', 'col_cursor') <> -3 
   BEGIN 
       CLOSE col_cursor    
       DEALLOCATE col_cursor  
   END 
END CATCH

こんな感じで通ります。

 exec sp_FindStringInTable 'Application','dbo','BAK_tbl_Timeline_032112','Sui_WIP'  
 exec sp_FindStringInTable 'Application','dbo','tbl_SampleList','Sui_WIP' 
 exec sp_FindStringInTable 'Insurance','dbo','BAK_tbl_Timeline_032112','Sui_WIP'  
 exec sp_FindStringInTable 'Insurance','dbo','tbl_SampleList','Sui_WIP' 
 exec sp_FindStringInTable 'Reduced','dbo','BAK_tbl_Timeline_032112','Sui_WIP'  
 exec sp_FindStringInTable 'Reduced','dbo','tbl_SampleList','Sui_WIP'

約600テーブル継続。ここで、ストア プロシージャを最適化します。

exec sp_FindStringInTable 'Application;Insurance;Reduced','dbo','BAK_tbl_Timeline_032112','Sui_WIP'
exec sp_FindStringInTable 'Application;Insurance;Reduced','Person','Person','AdventureWorks'

このspを変更して効率的に実行するのを手伝ってください。

注: ユーザーは、サーバー内の複数の DB (または) すべてのデータベースを選択し、データベース上の複数のテーブル (または) すべてのテーブルを選択することで、複数の単語を渡すことができます。

4

1 に答える 1

1

このクエリは、テキスト フィールドを持つテーブルを持つすべてのデータベースの部分文字列を検索します。スクリプトを試してみてください。役に立つかもしれません。

DECLARE @phrase NVARCHAR(100)
SELECT @phrase = 'str'

DECLARE 
      @db_name SYSNAME
    , @output NVARCHAR(200)

DECLARE db CURSOR READ_ONLY FAST_FORWARD LOCAL FOR 
    SELECT d.name
    FROM sys.databases d
    WHERE d.state_desc = 'ONLINE'
        AND d.name NOT IN ('tempdb', 'model', 'msdb', 'master')
    ORDER BY d.name

OPEN db

FETCH NEXT FROM db INTO @db_name

WHILE @@FETCH_STATUS = 0 BEGIN

    SELECT @output = CONVERT(NVARCHAR(15), GETDATE(), 114) + ': Find in ' + QUOTENAME(@db_name) + ':'
    RAISERROR(@output, 0, 1) WITH NOWAIT

    DECLARE @tsql NVARCHAR(MAX) = '
    USE [' + @db_name + ']; 
    DECLARE @sql NVARCHAR(MAX)
    SELECT @sql = ''USE [' + @db_name + '];'' + (
        SELECT 
            CHAR(13) + 
                ''IF EXISTS(SELECT 1 FROM '' + 
                QUOTENAME(s.name) + ''.'' + QUOTENAME(o.name) + 
                '' WHERE'' + b.cols + '') PRINT ''''['' + 
                s.name + ''].['' + o.name + '']'''';'' 
        FROM sys.objects o
        JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
        JOIN (
            SELECT DISTINCT p.[object_id] 
            FROM sys.partitions p
            WHERE p.[rows] > 0
        ) p ON p.[object_id] = o.[object_id]
        OUTER APPLY (
            SELECT cols = STUFF((
                SELECT ''OR CHARINDEX(''''' + @phrase + ''''', '' + QUOTENAME(c.name) + '') > 0 '' 
                FROM sys.columns c
                JOIN sys.types t ON c.user_type_id = t.user_type_id
                WHERE t.name IN (''char'', ''nchar'', ''ntext'', ''nvarchar'', ''text'', ''varchar'')
                    AND c.[object_id] = o.[object_id]
                ORDER BY c.column_id
                FOR XML PATH(''''), TYPE, ROOT).value(''root[1]'', ''NVARCHAR(MAX)''), 1, 2, '''')
        ) b
        WHERE o.[type] = ''U''
            AND b.cols IS NOT NULL
        FOR XML PATH(''''), TYPE, ROOT).value(''root[1]'', ''NVARCHAR(MAX)'') 

        EXEC sys.sp_executesql @sql
    '

    EXEC sys.sp_executesql @tsql
    PRINT REPLICATE('-', 100) + CHAR(13)

    FETCH NEXT FROM db INTO @db_name

END

CLOSE db
DEALLOCATE db

またはこれを試してください -

DECLARE @char NVARCHAR(50)
SELECT @char = 'str'

DECLARE @sql NVARCHAR(MAX)
SELECT @sql = (
    SELECT CHAR(13) + 
        'IF EXISTS(SELECT 1 FROM ' + 
            QUOTENAME(s.name) + '.' + QUOTENAME(o.name) + 
            ' WHERE' + b.cols + ')  
        SELECT table_name = ''[' + s.name + '].[' + o.name + ']'' ' + c.cols +' FROM ' + 
            QUOTENAME(s.name) + '.' + QUOTENAME(o.name) + 
            ' WHERE' + b.cols + ';' 
    FROM sys.objects o
    JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
    JOIN (
        SELECT DISTINCT p.[object_id] 
        FROM sys.partitions p
        WHERE p.[rows] > 0
    ) p ON p.[object_id] = o.[object_id]
    OUTER APPLY (
        SELECT cols = STUFF((
            SELECT 'OR CHARINDEX(''' + @char + ''', ' + QUOTENAME(c.name) + ') > 0 ' 
            FROM sys.columns c
            JOIN sys.types t ON c.user_type_id = t.user_type_id
            WHERE t.name IN ('char', 'nchar', 'ntext', 'nvarchar', 'text', 'varchar')
                AND c.[object_id] = o.[object_id]
            ORDER BY c.column_id
            FOR XML PATH(''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)'), 1, 2, '')
    ) b
    OUTER APPLY (
        SELECT cols = (
            SELECT ', ' + QUOTENAME(c.name) + ' ' 
            FROM sys.columns c
            JOIN sys.types t ON c.user_type_id = t.user_type_id
            WHERE t.name IN ('char', 'nchar', 'ntext', 'nvarchar', 'text', 'varchar')
                AND c.[object_id] = o.[object_id]
            ORDER BY c.column_id
            FOR XML PATH(''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)')
    ) c
    WHERE o.[type] = 'U'
        AND b.cols IS NOT NULL
    FOR XML PATH(''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)') 

    EXEC sys.sp_executesql @sql
于 2013-04-04T10:03:46.460 に答える