16

数百のテーブルと数千の列を持つ巨大なスキーマがあります。特定のIPアドレスがこのデータベースのいくつかの場所に保存されていることは知っていますが、それが保存されているテーブルまたは列はわかりません。基本的に、これがどこにでもあることを見つけようとしていますIP アドレスは DB に保存されるため、すべての場所で新しい値に更新できます。

これは、部分文字列 10.15.13 を含むデータベース内のすべてのテキスト列に対して、テーブルと列の名前、および値を出力する T-SQL ステートメントの最初のクラックです。

さて、これはうまくいきます。問題は、Management Studio で実行すると、sp_executesql を呼び出すと、実際には何も返さないすべてのクエリからすべての空の結果が返され (つまり、列にその部分文字列のレコードがない)、結果ウィンドウがいっぱいになることです。その最大まで、実際に何かが印刷されたかどうかはわかりません。

このクエリを記述するより良い方法はありますか? または、この部分文字列が存在するテーブルと列のみを表示するように、別の方法で実行できますか?

DECLARE
    @SchemaName VARCHAR(50),
    @TableName VARCHAR(50),
    @ColumnName VARCHAR(50);
BEGIN
    DECLARE textColumns CURSOR FOR
    SELECT s.Name, tab.Name, c.Name
    FROM Sys.Columns c, Sys.Types t, Sys.Tables tab, Sys.Schemas s
    WHERE s.schema_id = tab.schema_id AND tab.object_id = c.object_id AND c.user_type_id = t.user_type_id
    AND t.Name in ('TEXT','NTEXT','VARCHAR','CHAR','NVARCHAR','NCHAR');

    OPEN textColumns

    FETCH NEXT FROM textColumns
    INTO @SchemaName, @TableName, @ColumnName

    WHILE @@FETCH_STATUS = 0
    BEGIN
        DECLARE @sql NVARCHAR(MAX),
                @ParamDef NVARCHAR(MAX),
                @result NVARCHAR(MAX);              
        SET @sql = N'SELECT ' + @ColumnName + ' FROM ' + @SchemaName + '.' + @TableName + ' WHERE ' + @ColumnName + ' LIKE ''%10.15.13%''';
        SET @ParamDef = N'@resultOut NVARCHAR(MAX) OUTPUT';

        EXEC sp_executesql @sql, @ParamDef, @resultOut = @result OUTPUT;

        PRINT 'Column = ' + @TableName + '.' + @ColumnName + ', Value = ' + @result;
        FETCH NEXT FROM textColumns
        INTO @SchemaName, @TableName, @ColumnName       
    END
    CLOSE textColumns;
    DEALLOCATE textColumns;
END

部分文字列が見つかったテーブル/列と、その列の完全な値を示すこのような結果を表示したいと思います...

Column = SomeTable.SomeTextColumn, Value = 'https://10.15.13.210/foo'
Column = SomeTable.SomeOtherColumn, Value = '10.15.13.210'

4

3 に答える 3

0

これを試してみてください。制限が32を超えるというエラーは発生しません

alter PROC SearchAllTables
(
    @SearchStr nvarchar(100)
)
AS
BEGIN



    CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))

    SET NOCOUNT ON

    DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
    SET  @TableName = ''
    SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')

    WHILE @TableName IS NOT NULL
    BEGIN
        SET @ColumnName = ''
        SET @TableName = 
        (
            SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
            FROM    INFORMATION_SCHEMA.TABLES
            WHERE       TABLE_TYPE = 'BASE TABLE'
                AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
                AND OBJECTPROPERTY(
                        OBJECT_ID(
                            QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
                             ), 'IsMSShipped'
                               ) = 0
        )

        WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
        BEGIN
            SET @ColumnName =
            (
                SELECT MIN(QUOTENAME(COLUMN_NAME))
                FROM    INFORMATION_SCHEMA.COLUMNS
                WHERE       TABLE_SCHEMA    = PARSENAME(@TableName, 2)
                    AND TABLE_NAME  = PARSENAME(@TableName, 1)
                    AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
                    AND QUOTENAME(COLUMN_NAME) > @ColumnName
            )

            IF @ColumnName IS NOT NULL
            BEGIN
                INSERT INTO #Results
                EXEC
                (
                    'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
                    FROM ' + @TableName + ' (NOLOCK) ' +
                    ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
                )
            END
        END 
    END

    SELECT ColumnName, ColumnValue FROM #Results
END

それが役に立てば幸い

于 2014-08-28T07:38:42.590 に答える