SQL 服务器子字符串可变长度 - 长度不一但模式不一致的数字
SQL Server Substring variable length - numerals of varying length with no consistent pattern
我已经检查了这里与可变长度子字符串相关的许多线程 - none 已经回答了我的具体情况 - 请不要标记为可能重复,除非我不知何故错过了它。
蔚蓝 SQL 服务器 2017
我在 table dbo.MyTable
中有一个名为 Name
的 varchar(50)
字段,具有以下类型的值:
1143_RRF-tansTracks
DGGP-45-HAEJTJ_wer
3TTKH_YPreTTR
4534554PostRTE
WERET677ITD
PINT_pilly-er_45321
我正在尝试使用 SUBSTRING
来获得这个:
1143
45
3
4534554
677
45321
我无法理解如何定义 length
参数。
我目前拥有的:
SUBSTRING(Name, (PATINDEX('%[0-9]%',[Name])),7) AS Number
7
只是一个占位符 - 我该如何正确编写 length
参数来实现我的号码提取?
您可以创建这样的函数以从 SQL 服务器中的字符串中获取数字,如下所示。
CREATE FUNCTION dbo.udf_GetNumeric (@strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256)
AS
BEGIN
DECLARE @intAlpha INT
SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)
BEGIN
WHILE @intAlpha > 0
BEGIN
SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '')
SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)
END
END
RETURN ISNULL(@strAlphaNumeric, 0)
END
GO
SELECT dbo.udf_GetNumeric('1143_RRF-tansTracks') AS NumberFromString;
这是给定的 demo。
您可以使用 TRANSLATE()
和 REPLACE()
函数作为
SELECT Str,
REPLACE(
TRANSLATE(Str, 'abcdefghiJklmnopqrstuvwxyz_-',
' '), ' ', '')
FROM
(
VALUES
('1143_RRF-tansTracks'),
('DGGP-45-HAEJTJ_wer'),
('3TTKH_YPreTTR'),
('4534554PostRTE'),
('WERET677ITD'),
('PINT_pilly-er_45321')
) T(Str);
不太好,但如果你真的需要单线:
SUBSTRING(SUBSTRING(Name, PATINDEX('%[0-9]%',Name),999),1,PATINDEX('%[^0-9]%',SUBSTRING(Name,PATINDEX('%[0-9]%',Name),999)+'x')-1)
或者:
SUBSTRING(Name,PATINDEX('%[0-9]%',Name),LEN(NAME)-PATINDEX('%[0-9]%',REVERSE(Name))-PATINDEX('%[0-9]%',Name)+2)
这是使用标量函数的替代方法。这将突飞猛进地胜过标量函数。
create function [dbo].[GetNumbersOnly](@pString varchar(8000))
returns table as return
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4)
, ValueList as
(
SELECT N, SUBSTRING(@pString, N, 1) as NewVal
FROM cteTally
WHERE N <= LEN(@pString)
AND SUBSTRING(@pString, N, 1) LIKE ('[0-9]')
)
SELECT top 1 NewVal = replace(STUFF((
SELECT '+' + NewVal
FROM ValueList
FOR XML PATH(''), TYPE).value('.','varchar(max)'),1,1,''), '+', '')
FROM ValueList
然后您可以将其用于当前输出。
declare @Something table
(
Name varchar(100)
)
insert @Something values
('1143_RRF-tansTracks')
, ('DGGP-45-HAEJTJ_wer')
, ('3TTKH_YPreTTR')
, ('4534554PostRTE')
, ('WERET677ITD')
, ('PINT_pilly-er_45321')
select *
from @Something s
cross apply dbo.GetOnlyNumbers(s.Name) n
我已经检查了这里与可变长度子字符串相关的许多线程 - none 已经回答了我的具体情况 - 请不要标记为可能重复,除非我不知何故错过了它。
蔚蓝 SQL 服务器 2017
我在 table dbo.MyTable
中有一个名为 Name
的 varchar(50)
字段,具有以下类型的值:
1143_RRF-tansTracks
DGGP-45-HAEJTJ_wer
3TTKH_YPreTTR
4534554PostRTE
WERET677ITD
PINT_pilly-er_45321
我正在尝试使用 SUBSTRING
来获得这个:
1143
45
3
4534554
677
45321
我无法理解如何定义 length
参数。
我目前拥有的:
SUBSTRING(Name, (PATINDEX('%[0-9]%',[Name])),7) AS Number
7
只是一个占位符 - 我该如何正确编写 length
参数来实现我的号码提取?
您可以创建这样的函数以从 SQL 服务器中的字符串中获取数字,如下所示。
CREATE FUNCTION dbo.udf_GetNumeric (@strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256)
AS
BEGIN
DECLARE @intAlpha INT
SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)
BEGIN
WHILE @intAlpha > 0
BEGIN
SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '')
SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)
END
END
RETURN ISNULL(@strAlphaNumeric, 0)
END
GO
SELECT dbo.udf_GetNumeric('1143_RRF-tansTracks') AS NumberFromString;
这是给定的 demo。
您可以使用 TRANSLATE()
和 REPLACE()
函数作为
SELECT Str,
REPLACE(
TRANSLATE(Str, 'abcdefghiJklmnopqrstuvwxyz_-',
' '), ' ', '')
FROM
(
VALUES
('1143_RRF-tansTracks'),
('DGGP-45-HAEJTJ_wer'),
('3TTKH_YPreTTR'),
('4534554PostRTE'),
('WERET677ITD'),
('PINT_pilly-er_45321')
) T(Str);
不太好,但如果你真的需要单线:
SUBSTRING(SUBSTRING(Name, PATINDEX('%[0-9]%',Name),999),1,PATINDEX('%[^0-9]%',SUBSTRING(Name,PATINDEX('%[0-9]%',Name),999)+'x')-1)
或者:
SUBSTRING(Name,PATINDEX('%[0-9]%',Name),LEN(NAME)-PATINDEX('%[0-9]%',REVERSE(Name))-PATINDEX('%[0-9]%',Name)+2)
这是使用标量函数的替代方法。这将突飞猛进地胜过标量函数。
create function [dbo].[GetNumbersOnly](@pString varchar(8000))
returns table as return
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4)
, ValueList as
(
SELECT N, SUBSTRING(@pString, N, 1) as NewVal
FROM cteTally
WHERE N <= LEN(@pString)
AND SUBSTRING(@pString, N, 1) LIKE ('[0-9]')
)
SELECT top 1 NewVal = replace(STUFF((
SELECT '+' + NewVal
FROM ValueList
FOR XML PATH(''), TYPE).value('.','varchar(max)'),1,1,''), '+', '')
FROM ValueList
然后您可以将其用于当前输出。
declare @Something table
(
Name varchar(100)
)
insert @Something values
('1143_RRF-tansTracks')
, ('DGGP-45-HAEJTJ_wer')
, ('3TTKH_YPreTTR')
, ('4534554PostRTE')
, ('WERET677ITD')
, ('PINT_pilly-er_45321')
select *
from @Something s
cross apply dbo.GetOnlyNumbers(s.Name) n