Does REPLACE function in SQL Server accept input from a table for 'string_pattern' parameter?

你离开我真会死。 提交于 2020-01-11 12:32:14

问题


I'm still learning my ropes with SQL Server and maybe this question sounds very naive/ridiculous. Please bear with me on this. :)

I saw a function in SQL Server defined as below:

CREATE FUNCTION [dbo].[fn_CleanNumeric]
    (
    @InputString VARCHAR(500)
    )
RETURNS NVARCHAR(500)
as
BEGIN
    SELECT
        @InputString = REPLACE(@InputString, n.Symbol, '')
    FROM 
        NonNumeric n
    RETURN @InputString
END

NonNumeric is a table with a column named, [Symbol], containing a bunch of non-numeric ASCII characters. From looking at SQL Server documentation for REPLACE, I don't think it (REPLACE) accepts a table's column nor does it seem to accept a cursor. Is it because we are using REPLACE in function context? If someone could point me to a good resource that explains it, I'd greatly appreciate that.

Thank you in advance!


回答1:


This is a hacky trick called Quirky Update

This is slow and in most cases something one should avoid

Some examples:

DECLARE @tbl TABLE(SomeInt INT);
INSERT INTO @tbl VALUES (1),(2),(3);

DECLARE @SumOfInts INT=0
SELECT @SumOfInts = @SumOfInts + SomeInt FROM @tbl;
SELECT @SumOfInts; --SELECT SUM(SomeInt) FROM @tbl is clearly better...)

String concatenation

DECLARE @tbl2 TABLE(SomeText VARCHAR(100));
INSERT INTO @tbl2 VALUES ('a'),('b'),('c');

DECLARE @ConcatString VARCHAR(100)='';
SELECT @ConcatString = @ConcatString + ', ' + SomeText FROM @tbl2;
SELECT @ConcatString;

Better was the usual approach with FOR XML PATH('') and STUFF(), which is a hacky workaround too. (Newer versions will bring a built-in function at last!)

With REPLACE it works!

This Quirky Update is the only way I know to use a table's values for a step-by-step replacement of many values you can maintain in a table dynamically:

Look at this:

DECLARE @ReplaceValues TABLE(this VARCHAR(100),[by] VARCHAR(100));
INSERT INTO @ReplaceValues VALUES('$',' Dollar'),('€',' Euro'),('abbr.','abbreviations');

DECLARE @SomeText VARCHAR(MAX)=
'This text is about 100 $ or 100 € and shows how to replace abbr.!';

SELECT @SomeText=REPLACE(@SomeText,this,[by]) FROM @ReplaceValues;

SELECT @SomeText;

The result

--This text is about 100  Dollar or 100  Euro and shows how to replace abbreviations!



回答2:


In general, yes you can use the value from a column for any place in SQL Server's syntax where a value is expected (as opposed to where a name is expected, such as the first argument to DATEPART).

However, this is broken code - it appears to assume that each row will be evaluated in sequence and each row will be evaluated using values produced from previous rows. However, SQL Server only guarantees to perform one assignment (for the "last" row - however, with no ORDER BY clause, "last" is ill-defined):

If the SELECT statement returns more than one value, the variable is assigned the last value that is returned.

Whether it may appear to work is no guarantee that more than a single assignment will actually take place.




回答3:


Replace accepts the table column, and in this case it will do exactly what you expect it to do. It will do iterations on @InputString variable and exclude all non numeric characters that appear in the NonNumeric table and in the @InputString variable.




回答4:


Actually it will work with the table column and do a replace for each row in your table. But it only work because the @InputString variable is affected each time.

Maybe you could use a local temporary table to store your NonNumeric

Be carefull because you are returning a NVARCHAR value while @InputString is a VARCHAR.




回答5:


A simple code to show you that the REPLACE can accept values from a table

CREATE TABLE dbo.Test
(
RowID INT IDENTITY(1,1),
Test VARCHAR(20)
)

GO

INSERT INTO dbo.Test VALUES ('James')
INSERT INTO dbo.Test VALUES ('John')

GO

ALTER FUNCTION [dbo].[fn_CleanNumeric]
    (
    @InputString VARCHAR(500),
    @Test VARCHAR(500)
    )
RETURNS TABLE
AS
RETURN(
 SELECT
        REPLACE(@InputString, n.Test, '') AS Test
    FROM 
        dbo.Test n WHERE Test = @Test)
GO

SELECT * FROM [dbo].[fn_CleanNumeric] ('TestJohn','John')

Result

Test
--------
TestT

The SELECT takes a random value and will check for that string pattern in the variable @InputString, thus passing a @Test variable ensures to REPLACE the right string pattern



来源:https://stackoverflow.com/questions/44632965/does-replace-function-in-sql-server-accept-input-from-a-table-for-string-patter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!