Update: You can download the sql file here: http://cid-8e9963932ac1f048.skydrive.live.com/self.aspx/%C3%96ffentlich/STRING|_REPLACER|_V1.2.sql (saves you cleaning up the copy-pasted code from below… oh and hello experts-exchange-users)
Have you ever been asked to write something where you knew from the start that it could possibly wreak havok? Well I did today and since I haven’t posted in a while I thought I’d quickly share. Don’t worry I’ll be back blogging Sync, MVC and more soon (and hopefully tell you why I was gone).
Without talking too much about the real scenario that this was needed for, let me just say there is a large database that stores configuration data including a set of connection strings in multiple places spread across numerous tables. And our admins moved the database but didn’t know where exactly to change these config strings. I was the only dev left in the office at the time and they turned to me asking me if I could write a script that “replaced all occurrences of stringA with stringB throughout the whole database”.
Yikes. It sounds like trouble, you know it’s gonna hurt and I don’t want to be anywhere nearby when they press F5 to run the script. Ok, nevertheless I put together a little script that did just that, sent it to them and let’s see what happens next week. They have backups so even if everything goes wrong we can quickly restore things.
Here’s what I came up with. It’s not rocket science, but does the job. Use the script at your own risk (I didn’t find anything comparable on the web so maybe it will come in handy to someone). It shows some interesting usage of the system tables that I use now and again for things like this (when I don’t have my beloved SQLSMO). Have fun and use with caution (I can’t say that enough!)
------------------------------------------------------------ -- Name: STRING REPLACER -- Author: ADUGGLEBY -- Version: 20.05.2008 (1.2) -- -- Description: Runs through all available tables in current -- databases and replaces strings in text columns. ------------------------------------------------------------ -- PREPARE SET NOCOUNT ON -- VARIABLES DECLARE @tblName NVARCHAR(150) DECLARE @colName NVARCHAR(150) DECLARE @tblID int DECLARE @first bit DECLARE @lookFor nvarchar(250) DECLARE @replaceWith nvarchar(250) -- CHANGE PARAMETERS SET @lookFor = 'virtual2' SET @replaceWith = 'virtual3' -- TEXT VALUE DATA TYPES DECLARE @supportedTypes TABLE ( xtype NVARCHAR(20) ) INSERT INTO @supportedTypes SELECT XTYPE FROM SYSTYPES WHERE NAME IN ('varchar','char','nvarchar','nchar','xml') -- ALL USER TABLES DECLARE cur_tables CURSOR FOR SELECT SO.name, SO.id FROM SYSOBJECTS SO WHERE XTYPE='U' OPEN cur_tables FETCH NEXT FROM cur_tables INTO @tblName, @tblID WHILE @@FETCH_STATUS = 0 BEGIN ------------------------------------------------------------------------------------------- -- START INNER LOOP - All text columns, generate statement ------------------------------------------------------------------------------------------- DECLARE @temp NVARCHAR(4000) DECLARE @count INT SELECT @count = COUNT(name) FROM SYSCOLUMNS WHERE ID = @tblID AND XTYPE IN (SELECT xtype FROM @supportedTypes) IF @count > 0 BEGIN -- fetch supported columns for table DECLARE cur_columns CURSOR FOR SELECT name FROM SYSCOLUMNS WHERE ID = @tblID AND XTYPE IN (SELECT xtype FROM @supportedTypes) OPEN cur_columns FETCH NEXT FROM cur_columns INTO @colName -- generate opening UPDATE cmd SET @temp = ' PRINT ''Replacing ' + @tblName + ''' UPDATE ' + @tblName + ' SET ' SET @first = 1 -- loop through columns and create replaces WHILE @@FETCH_STATUS = 0 BEGIN IF (@first=0) SET @temp = @temp + ', ' SET @temp = @temp + @colName SET @temp = @temp + ' = REPLACE(' + @colName + ',''' SET @temp = @temp + @lookFor SET @temp = @temp + ''',''' SET @temp = @temp + @replaceWith SET @temp = @temp + ''')' SET @first = 0 FETCH NEXT FROM cur_columns INTO @colName END PRINT @temp CLOSE cur_columns DEALLOCATE cur_columns END ------------------------------------------------------------------------------------------- -- END INNER ------------------------------------------------------------------------------------------- FETCH NEXT FROM cur_tables INTO @tblName, @tblID END CLOSE cur_tables DEALLOCATE cur_tables
Thanks for posting the script!
I had to change line 69 to remove the quotes around the column as the first parameter to the Replace function:
SET @temp = @temp + ‘ = REPLACE(‘ + @colName + ‘,”’
Otherwise the column name would show up in the field after running the proc.
I also found out out that the output of the script for one of my tables was being truncated… probably a limitation of the NVARCHAR(4000) size. Because I only needed to update specific columns, I was able to manually edit the script.
Hi Mike,
thanks, you are absolutely right. Must have crept into the script while making it ‘bloggable’ :)
The 4000 is a bit of a limit, but if I remember right I can’t concat nvarchar(max) values, so I had to do it that way.
Thanks,
Alex
Did not work for me. I was trying to replace a script tag that came in from somewhere and though I got no errors after running the script, the string I required to replace was not replaced.
Hi Raj,
is it possible that the field you are using is a NTEXT or TEXT field? The script will not work on those…
(same goes for any NVARCHAR(MAX) or fields > 4000 length)
Bye,
Alex
Hi Alex,
Just wanted to thank you for posting your SQL code. Our database was injected with malicious scripts and your code helped me clean up hundreds of thousands of records.
You saved my day! :)
Anja
Alex,
This is awesome! Thanks so much for helping me finish my cleanup, I did the really important stuff semi-manually yesterday. Finding this was a life/time saver.
Experts-Exchange should throw you some dough, this is the best solution.
-Scott