Wie mache ich ein einfaches "Suchen und Ersetzen" in MsSQL?

88

Die Frage ist ziemlich selbsterklärend. Ich möchte ein einfaches Suchen und Ersetzen durchführen, wie Sie es in einem Texteditor für die Daten in einer Spalte meiner Datenbank tun würden (MsSQL unter MS Windows Server 2003).

Jiaaro
quelle

Antworten:

160

Die folgende Abfrage ersetzt jedes einzelne aZeichen durch ein bZeichen.

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

Dies funktioniert unter SQL Server 2003 nicht.

SQLMenace
quelle
Wenn Sie beim Versuch eine Fehlermeldung zum Spaltentyp erhalten, lesen Sie die Antwort von bmoeskau, die "cast" verwendet, um Column1 in den erforderlichen Typ zu konvertieren.
Johnathan Elmore
1
Haben wir das brauchen WHERE?
Anders Lindén
18

wie so:

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

Beispiel: Ersetzt <script ... durch <a ..., um Javascript-Schwachstellen zu beseitigen

BEGIN TRANSACTION; UPDATE testdb
SET title=REPLACE(title,'script','a'); COMMIT TRANSACTION;
Jiaaro
quelle
Wenn Sie tatsächlich vorhaben, dies in der Produktion zu verwenden, genießen Sie Ihre unbeabsichtigten Nebenwirkungen, wenn Sie kontextlose Zeichenfolgenersetzungen durchführen.
Nein, es war eine Art "diesmal ausführen, um einen SQL-Injection-Angriff zu beheben". Jetzt muss ich die Mächte davon überzeugen, dass wir eine serverseitige Authentifizierung benötigen. Javascript Authentifizierung ist NICHT Authentifizierung haha
Jiaaro
Beachten Sie, dass es viele Injektionsmethoden gibt, für die kein <script>Tag erforderlich ist , z. B. using <style>oder <object>tags oder böswillige srcAttribute oder onerrorAttribute.
mbomb007
8

Dies hat mich in die richtige Richtung gelenkt, aber ich habe eine ntextDatenbank , die aus MSSQL 2000 stammt und immer noch den Datentyp für die Spalte verwendet, für die ich ersetzt habe. Wenn Sie versuchen, REPLACE für diesen Typ auszuführen, wird folgende Fehlermeldung angezeigt:

Der Argumentdatentyp ntext ist für Argument 1 der Ersetzungsfunktion ungültig.

Die einfachste Lösung, wenn Ihre Spaltendaten passen nvarchar, besteht darin, die Spalte beim Ersetzen umzuwandeln. Ausleihen des Codes aus der akzeptierten Antwort :

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

Das hat bei mir perfekt funktioniert. Dank dieses Forumsbeitrags habe ich das Update gefunden. Hoffentlich hilft das jemand anderem!

Brian Moeskau
quelle
Ich wusste, dass ich meine Kolumne als nvarchar besetzen musste, wusste aber nichts über nvarchar (max) ... sehr nützlich!
Johnathan Elmore
3

Im Folgenden wird in jeder Datenbank (mit Ausnahme von Systemdatenbanken) in jeder Tabelle der Instanz, mit der Sie verbunden sind, eine Zeichenfolge gefunden und ersetzt:

Wechseln 'Search String'Sie einfach zu dem, was Sie suchen und 'Replace String'durch das, durch das Sie es ersetzen möchten.

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

Hinweis: Dies ist weder ideal noch optimiert

abc123
quelle
0

Wenn Sie mit SQL Server 2005 oder höher arbeiten, steht unter http://www.sqlsharp.com/ auch eine CLR-Bibliothek zur Verfügung , die .NET-Implementierungen von Zeichenfolgen- und RegEx-Funktionen bereitstellt, die je nach Datenträger und Datentyp möglicherweise vorhanden sind einfacher zu verwenden und in einigen Fällen können die .NET-Zeichenfolgenmanipulationsfunktionen effizienter sein als die von T-SQL.

Joe Kuemerle
quelle