MsSQL'de basit bir "Bul ve Değiştir" i nasıl yaparım?


89

Soru oldukça açıklayıcı. Veritabanımın bir sütunundaki veriler üzerinde bir metin düzenleyicide yaptığınız gibi basit bir bul ve değiştir yapmak istiyorum (MS Windows Server 2003'teki MsSQL'dir)

Yanıtlar:


162

Aşağıdaki sorgu, her abir bkarakteri bir karakterle değiştirir.

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

Bu, SQL server 2003'te çalışmayacaktır.


Bunu denediğinizde sütun türüyle ilgili bir hata alırsanız, Sütun1'i gereken türe dönüştürmek için "cast" kullanan bmoeskau'nun aşağıdaki yanıtına bakın.
Johnathan Elmore

2
İhtiyacımız var WHEREmı?
Anders Lindén

18

böyle:

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

Örnek: Javascript güvenlik açıklarını ortadan kaldırmak için <script ... 'i <a ... ile değiştirir

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

Aslında bunu üretimde kullanmayı planlıyorsanız, kapsamlı bağlamsız dizi ikamelerinin istenmeyen yan etkilerinden yararlanın.

hayır bu bir 'sql enjeksiyon saldırısını düzeltmek için bir kez çalıştır' türü bir şeydi ... şimdi güçleri sunucu tarafı kimlik doğrulamasına ihtiyacımız olduğuna ikna etmeliyim. Javascript kimlik doğrulaması kimlik doğrulama DEĞİLDİR haha
Jiaaro

Veya etiketleri veya kötü niyetli öznitelikler veya öznitelikler <script>gibi bir etiket gerektirmeyen çok sayıda enjeksiyon yöntemi olduğunu unutmayın . <style><object>srconerror
mbomb007

8

Bu beni doğru yöne işaret etti, ancak MSSQL 2000'den kaynaklanan bir DB'ye sahibim ve hala ntextdeğiştirdiğim sütun için veri türünü kullanıyor . Bu türde DEĞİŞTİR'i çalıştırmayı denediğinizde şu hatayı alıyorsunuz:

Bağımsız değişken veri türü ntext, değiştirme işlevinin 1. bağımsız değişkeni için geçersiz.

Sütun verileriniz uygunsa, en basit düzeltme, nvarchardeğiştirme sırasında sütunu dönüştürmektir. Kodu kabul edilen cevaptan ödünç almak :

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

Bu benim için mükemmel çalıştı. Düzeltme için bulduğum bu forum gönderisine teşekkürler . Umarım bu başka birine yardımcı olur!


Köşemi nvarchar olarak kullanmam gerektiğini biliyordum, ancak nvarchar (max) hakkında bir bilgim yoktu ... çok kullanışlı!
Johnathan Elmore

3

Aşağıdakiler, bağlı olduğunuz örnekteki her tablodaki her veritabanında (sistem veritabanları hariç) bir dize bulur ve değiştirir:

Basitçe 'Search String', aradığınız şeye ve 'Replace String'onu değiştirmek istediğiniz şeye değiştirin.

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

Not: Bu ideal değildir ve optimize edilmemiştir


0

SQL Server 2005 veya sonraki bir sürümüyle çalışıyorsanız, http://www.sqlsharp.com/ adresinde , biriminize ve veri türünüze bağlı olarak dize ve RegEx işlevlerinin .NET uygulamalarını sağlayan bir CLR kitaplığı da vardır. kullanımı daha kolaydır ve bazı durumlarda .NET dize işleme işlevleri T-SQL işlevlerinden daha verimli olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.