SELECT REPLACE('<strong>100</strong><b>.00 GB', '%^(^-?\d*\.{0,1}\d+$)%', '');
我想用上面的正則表達式替換數字的兩個部分之間的任何標記,但它似乎不工作。我不確定這是不是正則表達式語法,因爲我嘗試了一個簡單的例如'%[^0-9]%'
只是爲了測試,但它也沒有工作。有誰知道我怎麼能做到這一點?SQL中的正則表達式模式替換函數?
SELECT REPLACE('<strong>100</strong><b>.00 GB', '%^(^-?\d*\.{0,1}\d+$)%', '');
我想用上面的正則表達式替換數字的兩個部分之間的任何標記,但它似乎不工作。我不確定這是不是正則表達式語法,因爲我嘗試了一個簡單的例如'%[^0-9]%'
只是爲了測試,但它也沒有工作。有誰知道我怎麼能做到這一點?SQL中的正則表達式模式替換函數?
您可以使用PATINDEX 查找模式(字符串)出現的第一個索引。然後使用STUFF將另一個字符串填充到匹配的模式(字符串)中。
循環遍歷每一行。用你想要的替換每個非法字符。在你的情況下,用空白替換非數字。內循環是如果在循環的當前單元中有多個非法字符。
DECLARE @counter int
SET @counter = 0
WHILE(@counter < (SELECT MAX(ID_COLUMN) FROM Table))
BEGIN
WHILE 1 = 1
BEGIN
DECLARE @RetVal varchar(50)
SET @RetVal = (SELECT Column = STUFF(Column, PATINDEX('%[^0-9.]%', Column),1, '')
FROM Table
WHERE ID_COLUMN = @counter)
IF(@RetVal IS NOT NULL)
UPDATE Table SET
Column = @RetVal
WHERE ID_COLUMN = @counter
ELSE
break
END
SET @counter = @counter + 1
END
注意:這雖然很慢!有一個varchar列可能會影響。所以使用LTRIM RTRIM可能會有所幫助。無論如何,這是緩慢的。
積分爲this StackOverFlow答案。
編輯 信用此亦@srutzky
編輯(由@Tmdean) 不是一次做一排,這個答案可以適應更基於集合的解決方案。它仍然在單行中迭代非數字字符的數量的最大值,所以它並不理想,但我認爲在大多數情況下它應該是可以接受的。
WHILE 1 = 1 BEGIN
WITH q AS
(SELECT ID_Column, PATINDEX('%[^0-9.]%', Column) AS n
FROM Table)
UPDATE Table
SET Column = STUFF(Column, q.n, 1, '')
FROM q
WHERE Table.ID_Column = q.ID_Column AND q.n != 0;
IF @@ROWCOUNT = 0 BREAK;
END;
如果您在表格中保留指示字段是否已被清理的位列,您也可以提高效率。 (NULL代表我的例子「未知」,並應列缺省值。)
DECLARE @done bit = 0;
WHILE @done = 0 BEGIN
WITH q AS
(SELECT ID_Column, PATINDEX('%[^0-9.]%', Column) AS n
FROM Table
WHERE COALESCE(Scrubbed_Column, 0) = 0)
UPDATE Table
SET Column = STUFF(Column, q.n, 1, ''),
Scrubbed_Column = 0
FROM q
WHERE Table.ID_Column = q.ID_Column AND q.n != 0;
IF @@ROWCOUNT = 0 SET @done = 1;
-- if Scrubbed_Column is still NULL, then the PATINDEX
-- must have given 0
UPDATE table
SET Scrubbed_Column = CASE
WHEN Scrubbed_Column IS NULL THEN 1
ELSE NULLIF(Scrubbed_Column, 0)
END;
END;
如果你不想改變你的模式,這是很容易適應存儲在一個表值變量中間結果其中最後應用於實際表格。
而不是剝離找到的字符的唯一位置,使用Replace(Column, BadFoundCharacter, '')
可能會大大加快。此外,不是隻替換每個列中下一個找到的錯誤字符,而是替換所有找到的字符。
WHILE 1 = 1 BEGIN
UPDATE dbo.YourTable
SET Column = Replace(Column, Substring(Column, PatIndex('%[^0-9.-]%', Column), 1), '')
WHERE Column LIKE '%[^0-9.-]%'
If @@RowCount = 0 BREAK;
END;
我相信這會比接受的答案更好,如果僅僅因爲它的操作更少。還有其他方法可能會更快,但我現在沒有時間去探索這些方法。
如果您想重複使用,將解決方案包裝在SQL函數中可能會很有用。 我甚至做它在細胞水平上,那爲什麼我把這個在一個不同的答案:
CREATE FUNCTION [dbo].[fnReplaceInvalidChars] (@string VARCHAR(300))
RETURNS VARCHAR(300)
BEGIN
DECLARE @str VARCHAR(300) = @string;
DECLARE @Pattern VARCHAR (20) = '%[^a-zA-Z0-9]%';
DECLARE @Len INT;
SELECT @Len = LEN(@String);
WHILE @Len > 0
BEGIN
SET @Len = @Len - 1;
IF (PATINDEX(@Pattern,@str) > 0)
BEGIN
SELECT @str = STUFF(@str, PATINDEX(@Pattern,@str),1,'');
END
ELSE
BEGIN
BREAK;
END
END
RETURN @str
END
如果你這樣做只是爲了進入存儲過程的參數,你可以使用以下命令:
while PatIndex('%[^0-9]%', @Param) > 0
select @Param = Replace(@Param, Substring(@Param, PatIndex('%[^0-9]%', @Param), 1), '')
這裏是我寫的基於以前的答案完成這個遞歸函數。
CREATE FUNCTION dbo.RecursiveReplace
(
@P_String VARCHAR(MAX),
@P_Pattern VARCHAR(MAX),
@P_ReplaceString VARCHAR(MAX),
@P_ReplaceLength INT = 1
)
RETURNS VARCHAR(MAX)
BEGIN
DECLARE @Index INT;
-- Get starting point of pattern
SET @Index = PATINDEX(@P_Pattern, @P_String);
IF @Index > 0
BEGIN
-- Perform the replace
SET @P_String = STUFF(@P_String, PATINDEX(@P_Pattern, @P_String), @P_ReplaceLength, @P_ReplaceString);
-- Recurse
SET @P_String = dbo.RecursiveReplace(@P_String, @P_Pattern, @P_ReplaceString, @P_ReplaceLength);
END;
RETURN @P_String;
END;
我碰到這個職位跌跌撞撞尋找別的東西,但想我會提到一個解決方案,我使用的是更爲高效 - 與使用時確實應該是任何函數的默認實現一個基於集合的查詢 - 這是使用交叉應用表函數。似乎該主題仍然活躍,所以希望這對某人有用。
基於運行基於遞歸集合的查詢或標量函數,基於1m行測試集從一個隨機newid中移除字符,到WHILE循環示例的範圍從34s到2m05s,從1m3s到{forever}用於函數示例。
在交叉應用中使用表函數在10s中實現了相同的目標。您可能需要調整它以適應您的需求,例如它處理的最大長度。
功能:
CREATE FUNCTION [dbo].[RemoveChars](@InputUnit VARCHAR(40))
RETURNS TABLE
AS
RETURN
(
WITH Numbers_prep(Number) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,Numbers(Number) AS
(
SELECT TOP (ISNULL(LEN(@InputUnit),0))
row_number() OVER (ORDER BY (SELECT NULL))
FROM Numbers_prep a
CROSS JOIN Numbers_prep b
)
SELECT
OutputUnit
FROM
(
SELECT
substring(@InputUnit,Number,1)
FROM Numbers
WHERE substring(@InputUnit,Number,1) like '%[0-9]%'
ORDER BY Number
FOR XML PATH('')
) Sub(OutputUnit)
)
用法:
UPDATE t
SET column = o.OutputUnit
FROM ##t t
CROSS APPLY [dbo].[RemoveChars](t.column) o
你可能想重溫了答案。 – Mukus
你想要最終的結果是什麼?你期望'100.00'還是'100.00 GB'?是否還有格式化數字的其他示例不符合標記模式,只能在小數點左邊的部分左右?標記可以圍繞整個數字,例如'100 .00 GB'?在右邊總是有兩個字符的貨幣代碼? –
@srutzky我想要小數點的數字,如果有的話,並不是所有的值都有它們,也沒有這些模式,因爲它是第三方的html生成器。有時貨幣有時在數字後面,有時候是符號 - 美元,有時代碼 - 美元,沒有空格..等等。只是非常垃圾的數據 – johnyTee