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:
Truy vấn sau đây thay thế mỗi và mọi a
ký tự bằng một b
ký 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.
WHERE
không?
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;
<script>
thẻ, chẳng hạn như sử dụng <style>
hoặc <object>
thẻ, hoặc độc hại src
thuộc tính hoặc onerror
các thuộc tính.
Đ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 ntext
kiể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!
Đơ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
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.