【问题标题】:How do I do a simple 'Find and Replace" in MsSQL?如何在 MsSQL 中进行简单的“查找和替换”?
【发布时间】:2010-09-08 17:05:32
【问题描述】:

问题很容易解释。我想做一个简单的查找和替换,就像你在我的数据库列中的数据上的文本编辑器中一样(这是 MS Windows server 2003 上的 MsSQL)

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    以下查询将每个 a 字符替换为 b 字符。

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

    这不适用于 SQL Server 2003。

    【讨论】:

    • 如果您在尝试此操作时收到有关列类型的错误,请参阅下面来自 bmoeskau 的答案,该答案使用“cast”将 Column1 转换为所需的类型。
    • 我们需要WHERE吗?
    【解决方案2】:

    像这样:

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

    示例:将

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

    【讨论】:

    • 如果您真的打算在生产中使用它,请享受彻底的无上下文字符串替换带来的意外副作用。
    • 不,这是“运行一次以修复 sql 注入攻击”类型的事情......现在我必须说服我们需要服务器端身份验证的权力。 Javascript认证不是认证哈哈
    • 请注意,有很多注入方法不需要<script>标签,例如使用<style><object>标签,或恶意src属性或onerror属性.
    【解决方案3】:

    如果您使用的是 SQL Server 2005 或更高版本,http://www.sqlsharp.com/ 还提供了一个 CLR 库,它提供了字符串和 RegEx 函数的 .NET 实现,根据您的数据量和数据类型,这些函数可能更易于使用和在某些情况下,.NET 字符串操作函数可能比 T-SQL 更有效。

    【讨论】:

      【解决方案4】:

      这为我指明了正确的方向,但我有一个源自 MSSQL 2000 的数据库,并且仍在为我要替换的列使用 ntext 数据类型。当您尝试在该类型上运行 REPLACE 时,您会收到以下错误:

      replace 的参数 1 的参数数据类型 ntext 无效 函数。

      如果您的列数据适合nvarchar,最简单的解决方法是在替换期间强制转换列。借用accepted answer的代码:

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

      这对我来说非常有效。感谢this forum post 我找到了修复。希望这对其他人有帮助!

      【讨论】:

      • 我知道我必须将我的专栏转换为 nvarchar,但不知道 nvarchar(max)...非常有用!
      【解决方案5】:

      以下内容将在您连接到的实例的每个表上的每个数据库(不包括系统数据库)中查找并替换字符串:

      只需将'Search String' 更改为您想要的任何内容,并将'Replace String' 更改为您想要替换的任何内容。

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

      注意:这并不理想,也没有优化

      【讨论】:

        猜你喜欢
        • 2011-08-07
        • 1970-01-01
        • 2011-08-24
        • 1970-01-01
        • 1970-01-01
        • 2013-07-24
        • 2013-01-02
        • 2019-04-13
        • 1970-01-01
        相关资源
        最近更新 更多