<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/2.2.2" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
	<title>Comments on: A bug in Microsoft SQL Server&#8217;s replace() function</title>
	<link>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/</link>
	<description>Stay curious!</description>
	<pubDate>Fri, 29 Aug 2008 19:20:54 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2.2</generator>

	<item>
		<title>By: Anon</title>
		<link>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/#comment-7336</link>
		<author>Anon</author>
		<pubDate>Thu, 17 May 2007 17:20:51 +0000</pubDate>
		<guid>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/#comment-7336</guid>
		<description>This solved the problem for me...

select replace(fld, N'  ', N' ')
from table

This would help when fld is an nvarchar instead of varchar.</description>
		<content:encoded><![CDATA[<p>This solved the problem for me&#8230;</p>
<p>select replace(fld, N&#8217;  &#8216;, N&#8217; &#8216;)<br />
from table</p>
<p>This would help when fld is an nvarchar instead of varchar.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Phred</title>
		<link>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/#comment-112</link>
		<author>Phred</author>
		<pubDate>Wed, 22 Mar 2006 03:32:48 +0000</pubDate>
		<guid>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/#comment-112</guid>
		<description>&lt;p&gt;I tripped over this bug too when trying to "unabbreviate" data in a view. The following failed because of the bug:&lt;/p&gt;

&lt;pre&gt;SELECT DISTINCT 
     REPLACE(REPLACE(department, 'sch of ', 'School of '), 'sch ', 'School of ') AS  deptExpanded, [position]
FROM         vWebDirectory
ORDER BY deptExpanded, [Position]&lt;/pre&gt;

&lt;p&gt;All instances of 'sch' were replaced by 'School of', including within 'School' etc.&lt;/p&gt;

&lt;p&gt;An ugly workaround was developed that may be useful in similar circumstances, see below;&lt;/p&gt;

&lt;pre&gt;SELECT DISTINCT 
                      CASE WHEN charindex('sch of ', department)  0 THEN replace(department, 'sch of ', 'School of ') WHEN charindex('sch ', department) 
                       0 THEN replace(department, 'sch ', 'School of ') ELSE department END AS deptExpanded, [position]
FROM         vWebDirectory
ORDER BY deptExpanded, [Position]&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>I tripped over this bug too when trying to &#8220;unabbreviate&#8221; data in a view. The following failed because of the bug:</p>
<pre>SELECT DISTINCT
     REPLACE(REPLACE(department, 'sch of ', 'School of '), 'sch ', 'School of ') AS  deptExpanded, [position]
FROM         vWebDirectory
ORDER BY deptExpanded, [Position]</pre>
<p>All instances of &#8217;sch&#8217; were replaced by &#8216;School of&#8217;, including within &#8216;School&#8217; etc.</p>
<p>An ugly workaround was developed that may be useful in similar circumstances, see below;</p>
<pre>SELECT DISTINCT
                      CASE WHEN charindex('sch of ', department)  0 THEN replace(department, 'sch of ', 'School of ') WHEN charindex('sch ', department)
                       0 THEN replace(department, 'sch ', 'School of ') ELSE department END AS deptExpanded, [position]
FROM         vWebDirectory
ORDER BY deptExpanded, [Position]</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Xaprb</title>
		<link>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/#comment-21</link>
		<author>Xaprb</author>
		<pubDate>Thu, 15 Dec 2005 21:41:41 +0000</pubDate>
		<guid>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/#comment-21</guid>
		<description>&lt;p&gt;Microsoft's Abdy Iman has responded to tell me someone is looking into the bug.  They've confirmed it and that it is still present in SQL Server 2005.&lt;/p&gt;</description>
		<content:encoded><![CDATA[<p>Microsoft&#8217;s Abdy Iman has responded to tell me someone is looking into the bug.  They&#8217;ve confirmed it and that it is still present in SQL Server 2005.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Xaprb</title>
		<link>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/#comment-8</link>
		<author>Xaprb</author>
		<pubDate>Wed, 23 Nov 2005 17:40:15 +0000</pubDate>
		<guid>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/#comment-8</guid>
		<description>&lt;p&gt;The documentation for &lt;code&gt;space&lt;/code&gt; states the return type is &lt;code&gt;char&lt;/code&gt; but the following still succeeds:&lt;/p&gt;

&lt;pre&gt;if replace('two  spaces', space(2), space(1)) = 'two spaces'
    print 'Replacement worked'
else
    print 'Replacement failed'&lt;/pre&gt;

&lt;p&gt;Apparently the return value of the function is either not as stated, or the input to the &lt;code&gt;replace&lt;/code&gt; function isn't where it's being trimmed.&lt;/p&gt;</description>
		<content:encoded><![CDATA[<p>The documentation for <code>space</code> states the return type is <code>char</code> but the following still succeeds:</p>
<pre>if replace('two  spaces', space(2), space(1)) = 'two spaces'
    print 'Replacement worked'
else
    print 'Replacement failed'</pre>
<p>Apparently the return value of the function is either not as stated, or the input to the <code>replace</code> function isn&#8217;t where it&#8217;s being trimmed.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: John Miller</title>
		<link>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/#comment-6</link>
		<author>John Miller</author>
		<pubDate>Mon, 21 Nov 2005 04:26:32 +0000</pubDate>
		<guid>http://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/#comment-6</guid>
		<description>&lt;p&gt;I did a bit more testing on this and it appears to be a problem with the replace function trimming char variables.  Changing the section&lt;/p&gt;

&lt;pre&gt;set @replace = ' ' &lt;/pre&gt;

&lt;p&gt;to&lt;/p&gt;

&lt;pre&gt;set @replace = '*'&lt;/pre&gt;

&lt;p&gt;and outputting the replace exhibits the extent of the problem.  The result is:&lt;/p&gt;

&lt;pre&gt;hi**there&lt;/pre&gt;

&lt;p&gt;Furthermore, changing &lt;code&gt;@string&lt;/code&gt; to &lt;code&gt;'This  is  a  test'&lt;/code&gt; and &lt;code&gt;@find = 's&#160;'&lt;/code&gt; with &lt;code&gt;@replace = '*'&lt;/code&gt; results in:&lt;/p&gt;

&lt;pre&gt;Thi*  i* a te*t&lt;/pre&gt;

&lt;p&gt;Note that the &lt;code&gt;'s'&lt;/code&gt; in &lt;code&gt;'test'&lt;/code&gt; has been changed although it has no spaces anywhere around it.  This is the strongest evidence that trimming is going on.&lt;/p&gt;

&lt;p&gt;Leading spaces are not affected.  The more complex &lt;code&gt;@string&lt;/code&gt; with &lt;code&gt;@find = ' i'&lt;/code&gt; results in:&lt;/p&gt;

&lt;pre&gt;This *s  a  test&lt;/pre&gt;

&lt;p&gt;as expected.&lt;/p&gt;

&lt;p&gt;The replicate inside the replace works because replicate returns a varchar and so actually falls into the first case you mentioned which, as you noted, works correctly.&lt;/p&gt;

&lt;p&gt;Finally, it is not a problem with char variables in general, because the following code honors the ANSI_PADDING setting while the replace issue does not:&lt;/p&gt;

&lt;pre&gt;set ansi_padding on/off
declare @string char(2), @string2 varchar(2)
set @string = 's '
set @string2 = @string
select '-' + @string2 + '-'&lt;/pre&gt;

&lt;p&gt;In my work with extended procedures I have found that string constants appear to be passed as varchars and the string functions also return varchars, so unless you are reading the values from a table (in which case the variable should match the column definition) using varchars for string variables might be a good practice anyway by matching the source type (don't even get me started on the implicit type conversions.  Oh, for a strongly typed language...)  At worst even if the constant string completely fills the varchar variable the extra two (or four) bytes of storage are only two bytes, not gigabytes as it would be in a billion row table.&lt;/p&gt;</description>
		<content:encoded><![CDATA[<p>I did a bit more testing on this and it appears to be a problem with the replace function trimming char variables.  Changing the section</p>
<pre>set @replace = ' ' </pre>
<p>to</p>
<pre>set @replace = '*'</pre>
<p>and outputting the replace exhibits the extent of the problem.  The result is:</p>
<pre>hi**there</pre>
<p>Furthermore, changing <code>@string</code> to <code>'This  is  a  test'</code> and <code>@find = 's&nbsp;'</code> with <code>@replace = '*'</code> results in:</p>
<pre>Thi*  i* a te*t</pre>
<p>Note that the <code>'s'</code> in <code>'test'</code> has been changed although it has no spaces anywhere around it.  This is the strongest evidence that trimming is going on.</p>
<p>Leading spaces are not affected.  The more complex <code>@string</code> with <code>@find = ' i'</code> results in:</p>
<pre>This *s  a  test</pre>
<p>as expected.</p>
<p>The replicate inside the replace works because replicate returns a varchar and so actually falls into the first case you mentioned which, as you noted, works correctly.</p>
<p>Finally, it is not a problem with char variables in general, because the following code honors the ANSI_PADDING setting while the replace issue does not:</p>
<pre>set ansi_padding on/off
declare @string char(2), @string2 varchar(2)
set @string = 's '
set @string2 = @string
select '-' + @string2 + '-'</pre>
<p>In my work with extended procedures I have found that string constants appear to be passed as varchars and the string functions also return varchars, so unless you are reading the values from a table (in which case the variable should match the column definition) using varchars for string variables might be a good practice anyway by matching the source type (don&#8217;t even get me started on the implicit type conversions.  Oh, for a strongly typed language&#8230;)  At worst even if the constant string completely fills the varchar variable the extra two (or four) bytes of storage are only two bytes, not gigabytes as it would be in a billion row table.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
