将 Phone 数字格式化为美国格式 (###) ###-####
Formatting Phone Number to US Format (###) ###-####
我正在尝试将 SQL 服务器数据库中的大约 1000 phone 个数字重新格式化为美国格式 (###) ###-####
目前 phone 数字的格式有多种,从##########、###-###-####,一种是## #)-###-####。还有一种只有六位数。
作为第一步,我一直在尝试隔离所有这些行中的数字,但它只是返回与它们已经相同的数字。
select SUBSTRING(phone, PATINDEX('%[0-9]%', phone), LEN(phone)) from people
我怎样才能最好地编写一个将它们全部格式化为 (###) ###-####
的查询?
预期输出:
(555) 222-3333
(555) 444-3030
(555) 092-0920
(555) 444-4444
由于已经提出了一个建议,并且其中关于在字符串中隔离数字的建议使用了 while 循环,因此我需要 post 替代不使用任何循环的方法。相反,它使用计数或数字 table。这些有很多解决方案。我喜欢使用快如闪电且读取为零的视图。
这是我的理货版本 table。
create View [dbo].[cteTally] as
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
)
select N from cteTally
接下来我们需要一个 table 值函数来使用我们的计数 table 删除不是数字的字符。这也非常快,因为我们使用的是计数 table 而不是循环。
create function GetOnlyNumbers
(
@SearchVal varchar(8000)
) returns table as return
with MyValues as
(
select substring(@SearchVal, N, 1) as number
, t.N
from cteTally t
where N <= len(@SearchVal)
and substring(@SearchVal, N, 1) like '[0-9]'
)
select distinct NumValue = STUFF((select number + ''
from MyValues mv2
order by mv2.N
for xml path('')), 1, 0, '')
from MyValues mv
既然我们已经完成了所有的跑腿工作,我们就可以专注于手头的任务了。由于您没有提供任何样本数据,我只是编造了一些东西。我不太确定这是否代表您的数据,但这适用于我创建的样本数据。
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something(SomeVal varchar(100))
insert #Something values
('Maybe you have other stuff in here. 5552223333 additional characters can cause grief')
, ('321-654-9878')
, ('123)-333-4444')
, ('1234567')
select replace(format(try_convert(bigint, n.NumValue), '(###) ###-####'), '() ', '')
, n.NumValue
from #Something s
cross apply dbo.GetOnlyNumbers(s.SomeVal) n
格式化数据的输出如下所示:
(555) 222-3333
(321) 654-9878
(123) 333-4444
123-4567
如果重新格式化将要重复使用的内容,那么按照@GSerg 的建议创建 UDF 将是可行的方法。
如果这只是一次性清理,您可以试一试。
首先用一系列嵌套的 REPLACE() 函数替换所有带有空字符串的数字。
DECLARE @PhoneNumbers TABLE (
Number varchar (20))
INSERT INTO @PhoneNumbers VALUES ('(888-239/1239')
INSERT INTO @PhoneNumbers VALUES ('222.1234')
SELECT
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(Number, '0', '')
, '1', '')
, '2', '')
, '3', '')
, '4', '')
, '5', '')
, '6', '')
, '7', '')
, '8', '')
, '9', '')
FROM @PhoneNumbers
然后将这些结果非数字字符放入各自的嵌套 REPLACE() 函数中并格式化结果。您将不得不单独处理每个长度。如果您只有 7 位数字,并且想将其格式化为 10 位数字,那么您希望那些额外的 3 位数字是什么。这将处理 10 位 phone 数字。
SELECT FORMAT(x.NumbersOnly, '(###) ###-####')
FROM
(
SELECT
CONVERT(BIGINT,
REPLACE(
REPLACE(
REPLACE(
REPLACE(Number, '(', '')
, '-', '')
, '/', '')
, '.', '')
) AS NumbersOnly
FROM @PhoneNumbers
) x
WHERE LEN(x.NumbersOnly) = 10
这里是 dbfiddle.
我正在尝试将 SQL 服务器数据库中的大约 1000 phone 个数字重新格式化为美国格式 (###) ###-####
目前 phone 数字的格式有多种,从##########、###-###-####,一种是## #)-###-####。还有一种只有六位数。
作为第一步,我一直在尝试隔离所有这些行中的数字,但它只是返回与它们已经相同的数字。
select SUBSTRING(phone, PATINDEX('%[0-9]%', phone), LEN(phone)) from people
我怎样才能最好地编写一个将它们全部格式化为 (###) ###-####
的查询?
预期输出:
(555) 222-3333
(555) 444-3030
(555) 092-0920
(555) 444-4444
由于已经提出了一个建议,并且其中关于在字符串中隔离数字的建议使用了 while 循环,因此我需要 post 替代不使用任何循环的方法。相反,它使用计数或数字 table。这些有很多解决方案。我喜欢使用快如闪电且读取为零的视图。
这是我的理货版本 table。
create View [dbo].[cteTally] as
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
)
select N from cteTally
接下来我们需要一个 table 值函数来使用我们的计数 table 删除不是数字的字符。这也非常快,因为我们使用的是计数 table 而不是循环。
create function GetOnlyNumbers
(
@SearchVal varchar(8000)
) returns table as return
with MyValues as
(
select substring(@SearchVal, N, 1) as number
, t.N
from cteTally t
where N <= len(@SearchVal)
and substring(@SearchVal, N, 1) like '[0-9]'
)
select distinct NumValue = STUFF((select number + ''
from MyValues mv2
order by mv2.N
for xml path('')), 1, 0, '')
from MyValues mv
既然我们已经完成了所有的跑腿工作,我们就可以专注于手头的任务了。由于您没有提供任何样本数据,我只是编造了一些东西。我不太确定这是否代表您的数据,但这适用于我创建的样本数据。
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something(SomeVal varchar(100))
insert #Something values
('Maybe you have other stuff in here. 5552223333 additional characters can cause grief')
, ('321-654-9878')
, ('123)-333-4444')
, ('1234567')
select replace(format(try_convert(bigint, n.NumValue), '(###) ###-####'), '() ', '')
, n.NumValue
from #Something s
cross apply dbo.GetOnlyNumbers(s.SomeVal) n
格式化数据的输出如下所示:
(555) 222-3333
(321) 654-9878
(123) 333-4444
123-4567
如果重新格式化将要重复使用的内容,那么按照@GSerg 的建议创建 UDF 将是可行的方法。
如果这只是一次性清理,您可以试一试。
首先用一系列嵌套的 REPLACE() 函数替换所有带有空字符串的数字。
DECLARE @PhoneNumbers TABLE (
Number varchar (20))
INSERT INTO @PhoneNumbers VALUES ('(888-239/1239')
INSERT INTO @PhoneNumbers VALUES ('222.1234')
SELECT
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(Number, '0', '')
, '1', '')
, '2', '')
, '3', '')
, '4', '')
, '5', '')
, '6', '')
, '7', '')
, '8', '')
, '9', '')
FROM @PhoneNumbers
然后将这些结果非数字字符放入各自的嵌套 REPLACE() 函数中并格式化结果。您将不得不单独处理每个长度。如果您只有 7 位数字,并且想将其格式化为 10 位数字,那么您希望那些额外的 3 位数字是什么。这将处理 10 位 phone 数字。
SELECT FORMAT(x.NumbersOnly, '(###) ###-####')
FROM
(
SELECT
CONVERT(BIGINT,
REPLACE(
REPLACE(
REPLACE(
REPLACE(Number, '(', '')
, '-', '')
, '/', '')
, '.', '')
) AS NumbersOnly
FROM @PhoneNumbers
) x
WHERE LEN(x.NumbersOnly) = 10
这里是 dbfiddle.