Bagaimana cara melakukan 'Temukan dan Ganti "sederhana di MsSQL?

89

Pertanyaannya cukup jelas. Saya ingin melakukan pencarian dan penggantian sederhana, seperti yang Anda lakukan di editor teks pada data di kolom database saya (yaitu MsSQL di MS Windows server 2003)

Jiaaro
sumber

Jawaban:

162

Kueri berikut mengganti setiap akarakter dengan bkarakter.

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

Ini tidak akan berfungsi di SQL server 2003.

SQLMenace
sumber
Jika Anda mendapatkan kesalahan tentang jenis kolom saat Anda mencoba ini, lihat jawaban di bawah ini dari bmoeskau yang menggunakan "cast" untuk mengubah Kolom1 menjadi jenis yang diperlukan.
Johnathan Elmore
1
Apakah kita membutuhkan WHERE?
Anders Lindén
18

seperti ini:

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

Contoh: Mengganti <script ... dengan <a ... untuk menghilangkan kerentanan javascript

BEGIN TRANSACTION; UPDATE testdb
SET title=REPLACE(title,'script','a'); COMMIT TRANSACTION;
Jiaaro
sumber
Jika Anda benar-benar berencana menggunakannya dalam produksi, nikmati efek samping yang tidak diinginkan dari penggantian string tanpa konteks.
bukan itu adalah 'jalankan satu kali ini untuk memperbaiki serangan injeksi sql' ... sekarang saya harus meyakinkan kekuatan bahwa kita memerlukan otentikasi sisi server. Otentikasi Javascript BUKAN otentikasi haha
Jiaaro
Perhatikan bahwa ada banyak metode injeksi yang tidak memerlukan <script>tag, seperti menggunakan <style>atau <object>tag, atau srcatribut atau atribut berbahaya onerror.
mbomb007
8

Ini mengarahkan saya ke arah yang benar, tetapi saya memiliki DB yang berasal dari MSSQL 2000 dan masih menggunakan ntexttipe data untuk kolom yang saya ganti. Saat Anda mencoba menjalankan REPLACE pada jenis itu, Anda mendapatkan kesalahan ini:

Tipe data argumen ntext tidak valid untuk argumen 1 dari fungsi pengganti.

Perbaikan paling sederhana, jika data kolom Anda cocok nvarchar, adalah dengan mentransmisikan kolom selama penggantian. Meminjam kode dari jawaban yang diterima :

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

Ini bekerja dengan sempurna untuk saya. Berkat posting forum ini saya menemukan untuk memperbaikinya. Semoga ini membantu orang lain!

Brian Moeskau
sumber
Saya tahu saya harus memasukkan kolom saya sebagai nvarchar, tetapi tidak tahu tentang nvarchar (max) ... sangat berguna!
Johnathan Elmore
3

Berikut ini akan menemukan dan mengganti string di setiap database (tidak termasuk database sistem) di setiap tabel pada instance yang Anda sambungkan:

Cukup ubah 'Search String'ke apa pun yang Anda cari dan 'Replace String'dengan apa pun yang ingin Anda gantikan.

--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

Catatan: ini tidak ideal, juga tidak dioptimalkan

abc123
sumber
0

Jika Anda bekerja dengan SQL Server 2005 atau yang lebih baru, ada juga pustaka CLR yang tersedia di http://www.sqlsharp.com/ yang menyediakan implementasi .NET dari fungsi string dan RegEx yang, bergantung pada volume dan jenis data Anda mungkin lebih mudah digunakan dan dalam beberapa kasus fungsi manipulasi string .NET bisa lebih efisien daripada yang T-SQL.

Joe Kuemerle
sumber