Làm cách nào để thực hiện 'Tìm và Thay thế' đơn giản trong MsSQL?


89

Câu hỏi là khá tự giải thích. Tôi muốn thực hiện một tìm kiếm và thay thế đơn giản, giống như bạn làm trong trình soạn thảo văn bản trên dữ liệu trong một cột của cơ sở dữ liệu của tôi (là MsSQL trên MS Windows server 2003)

Câu trả lời:


162

Truy vấn sau đây thay thế mỗi và mọi aký tự bằng một bký tự.

UPDATE 
    YourTable
SET 
    Column1 = REPLACE(Column1,'a','b')
WHERE 
    Column1 LIKE '%a%'

Điều này sẽ không hoạt động trên máy chủ SQL 2003.


Nếu bạn gặp lỗi về loại cột khi thử điều này, hãy xem câu trả lời bên dưới từ bmoeskau sử dụng "ép kiểu" để chuyển Column1 thành kiểu bắt buộc.
Johnathan Elmore

1
Chúng ta có cần WHEREkhông?
Anders Lindén

18

như vậy:

BEGIN TRANSACTION; 
UPDATE table_name
  SET column_name=REPLACE(column_name,'text_to_find','replace_with_this'); 
COMMIT TRANSACTION;

Ví dụ: Thay thế <script ... bằng <a ... để loại bỏ các lỗ hổng javascript

BEGIN TRANSACTION; UPDATE testdb
SET title=REPLACE(title,'script','a'); COMMIT TRANSACTION;

Nếu bạn thực sự định sử dụng nó trong sản xuất, hãy tận hưởng tác dụng phụ không mong muốn của bạn khi thay thế chuỗi không theo ngữ cảnh.

không, đó là kiểu 'chạy một lần này để khắc phục một cuộc tấn công tiêm sql' ... bây giờ tôi phải thuyết phục các quyền hạn rằng chúng ta cần xác thực phía máy chủ. Xác thực Javascript KHÔNG phải là xác thực haha
Jiaaro 14/09/08

Lưu ý rằng có rất nhiều phương pháp tiêm mà không đòi hỏi phải có <script>thẻ, chẳng hạn như sử dụng <style>hoặc <object>thẻ, hoặc độc hại srcthuộc tính hoặc onerrorcác thuộc tính.
mbomb007

8

Điều này đã chỉ cho tôi đúng hướng, nhưng tôi có một DB có nguồn gốc từ MSSQL 2000 và vẫn đang sử dụng ntextkiểu dữ liệu cho cột mà tôi đã thay thế. Khi bạn cố gắng chạy REPLACE trên loại đó, bạn gặp lỗi sau:

Kiểu dữ liệu đối số ntext không hợp lệ cho đối số 1 của hàm thay thế.

Cách khắc phục đơn giản nhất, nếu dữ liệu cột của bạn phù hợp nvarchar, là truyền cột trong quá trình thay thế. Mượn mã từ câu trả lời được chấp nhận :

UPDATE YourTable
SET Column1 = REPLACE(cast(Column1 as nvarchar(max)),'a','b')
WHERE Column1 LIKE '%a%'

Điều này đã làm việc hoàn hảo cho tôi. Cảm ơn bài đăng trên diễn đàn này, tôi đã tìm thấy bản sửa lỗi. Hy vọng rằng điều này sẽ giúp người khác!


Tôi biết tôi phải ép cột của mình là nvarchar, nhưng không biết về nvarchar (max) ... rất hữu ích!
Johnathan Elmore

3

Phần sau sẽ tìm và thay thế một chuỗi trong mọi cơ sở dữ liệu (không bao gồm cơ sở dữ liệu hệ thống) trên mọi bảng trên phiên bản mà bạn được kết nối:

Đơn giản chỉ cần thay đổi 'Search String'bất kỳ thứ gì bạn tìm kiếm và 'Replace String'bất kỳ thứ gì bạn muốn thay thế nó.

--Getting all the databases and making a cursor
DECLARE db_cursor CURSOR FOR  
SELECT name 
FROM master.dbo.sysdatabases 
WHERE name NOT IN ('master','model','msdb','tempdb')  -- exclude these databases

DECLARE @databaseName nvarchar(1000)
--opening the cursor to move over the databases in this instance
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @databaseName   

WHILE @@FETCH_STATUS = 0   
BEGIN
    PRINT @databaseName
    --Setting up temp table for the results of our search
    DECLARE @Results TABLE(TableName nvarchar(370), RealColumnName nvarchar(370), ColumnName nvarchar(370), ColumnValue nvarchar(3630))

    SET NOCOUNT ON

    DECLARE @SearchStr nvarchar(100), @ReplaceStr nvarchar(100), @SearchStr2 nvarchar(110)
    SET @SearchStr = 'Search String'
    SET @ReplaceStr = 'Replace String'
    SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')

    DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128)
    SET  @TableName = ''

    --Looping over all the tables in the database
    WHILE @TableName IS NOT NULL
    BEGIN
        DECLARE @SQL nvarchar(2000)
        SET @ColumnName = ''
        DECLARE @result NVARCHAR(256)
        SET @SQL = 'USE ' + @databaseName + '
            SELECT @result = MIN(QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME))
            FROM    [' + @databaseName + '].INFORMATION_SCHEMA.TABLES
            WHERE       TABLE_TYPE = ''BASE TABLE'' AND TABLE_CATALOG = ''' + @databaseName + '''
                AND QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME) > ''' + @TableName + '''
                AND OBJECTPROPERTY(
                        OBJECT_ID(
                            QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME)
                                ), ''IsMSShipped''
                                ) = 0'
        EXEC master..sp_executesql @SQL, N'@result nvarchar(256) out', @result out

        SET @TableName = @result
        PRINT @TableName

        WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
        BEGIN
            DECLARE @ColumnResult NVARCHAR(256)
            SET @SQL = '
                SELECT @ColumnResult = MIN(QUOTENAME(COLUMN_NAME))
                FROM    [' + @databaseName + '].INFORMATION_SCHEMA.COLUMNS
                WHERE       TABLE_SCHEMA    = PARSENAME(''[' + @databaseName + '].' + @TableName + ''', 2)
                    AND TABLE_NAME  = PARSENAME(''[' + @databaseName + '].' + @TableName + ''', 1)
                    AND DATA_TYPE IN (''char'', ''varchar'', ''nchar'', ''nvarchar'')
                    AND TABLE_CATALOG = ''' + @databaseName + '''
                    AND QUOTENAME(COLUMN_NAME) > ''' + @ColumnName + ''''
            PRINT @SQL
            EXEC master..sp_executesql @SQL, N'@ColumnResult nvarchar(256) out', @ColumnResult out
            SET @ColumnName = @ColumnResult 

            PRINT @ColumnName

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

    --Declaring another temporary table
    DECLARE @time_to_update TABLE(TableName nvarchar(370), RealColumnName nvarchar(370))

    INSERT INTO @time_to_update
    SELECT TableName, RealColumnName FROM @Results GROUP BY TableName, RealColumnName

    DECLARE @MyCursor CURSOR;
    BEGIN
        DECLARE @t nvarchar(370)
        DECLARE @c nvarchar(370)
        --Looping over the search results   
        SET @MyCursor = CURSOR FOR
        SELECT TableName, RealColumnName FROM @time_to_update GROUP BY TableName, RealColumnName

        --Getting my variables from the first item
        OPEN @MyCursor 
        FETCH NEXT FROM @MyCursor 
        INTO @t, @c

        WHILE @@FETCH_STATUS = 0
        BEGIN
            -- Updating the old values with the new value
            DECLARE @sqlCommand varchar(1000)
            SET @sqlCommand = '
                USE ' + @databaseName + '
                UPDATE [' + @databaseName + '].' + @t + ' SET ' + @c + ' = REPLACE(' + @c + ', ''' + @SearchStr + ''', ''' + @ReplaceStr + ''') 
                WHERE ' + @c + ' LIKE ''' + @SearchStr2 + ''''
            PRINT @sqlCommand
            BEGIN TRY
                EXEC (@sqlCommand)
            END TRY
            BEGIN CATCH
                PRINT ERROR_MESSAGE()
            END CATCH

            --Getting next row values
            FETCH NEXT FROM @MyCursor 
            INTO @t, @c 
        END;

        CLOSE @MyCursor ;
        DEALLOCATE @MyCursor;
    END;

    DELETE FROM @time_to_update
    DELETE FROM @Results

    FETCH NEXT FROM db_cursor INTO @databaseName
END   

CLOSE db_cursor   
DEALLOCATE db_cursor

Lưu ý: điều này không lý tưởng, cũng không phải là tối ưu hóa


0

Nếu bạn đang làm việc với SQL Server 2005 trở lên, cũng có một thư viện CLR có sẵn tại http://www.sqlsharp.com/ cung cấp các triển khai .NET của chuỗi và các hàm RegEx, tùy thuộc vào khối lượng và loại dữ liệu của bạn. dễ sử dụng hơn và trong một số trường hợp, các hàm thao tác chuỗi .NET có thể hiệu quả hơn các hàm T-SQL.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.