SQL标量函数的效率

时间:2013-04-12 14:04:21

标签: sql performance function

我有一个三数据库应用程序(我没有开发),其中存储了许多电话号码,但它们的格式不一致(555-5555,(555)555-5555,5555555555,5555555等)网络方面,我希望它们始终显示为555-555-5555。我已经编写了一个标量函数来清理它们,但它将被称为OFTEN,我担心它的效率。

你能看看,如果有更好的方法,请告诉我。

ALTER FUNCTION [dbo].[FormatPhone]
(
  @p AS VARCHAR(20)
) RETURNS VARCHAR(12) AS

BEGIN
DECLARE @ret AS VARCHAR(12) = ''
DECLARE @c AS CHAR
DECLARE @i AS INT
DECLARE @stop AS INT

-- loop to grab only digits from @p
SET @i = 1
SET @stop = LEN(@p)
WHILE @i <= @stop
BEGIN
    SET @c = SUBSTRING(@p, @i, 1)
    IF @c >= '0' AND @c <= '9' SET @ret = @ret + @c
    SET @i = @i + 1
END
IF LEN(@ret) = 7 SET @ret = '204' + @ret -- account for forgotten area code

SET @ret = LEFT(@ret, 3) + '-' + SUBSTRING(@ret, 4, 3) + '-' + RIGHT(@ret, 4)

RETURN @ret

谢谢! 尼克。

3 个答案:

答案 0 :(得分:2)

您所说的是数据清理。根据我的经验(我有一个为期6个月的项目与一个俄罗斯业务部门,其中约90%的人在电话号码格式问题上抨击我的头脑)这是一个彻底的痛苦。

我对此的建议是做一次并做得恰当;然后将系统放在适当位置以防止脏数据在将来进入系统。

我们最终做的是让管理办公室的几个女孩手工完成!问题是,如果你做错了,你就会使数据变得无用。快速进行自动解析,看看它能让你获得什么,但有时候人类会打败机器。

答案 1 :(得分:1)

  • 替换除数字以外的所有字符
  • 转换为示例XXX-XXX-XXXX

使用SUBSTRING,REPLACE T-SQL

答案 2 :(得分:0)

此函数查看数字/字符串以确定大小和格式,无需循环

CREATE Function [dbo].[FormatPhone] (@PD varchar(50))
RETURNS Varchar(50)
As 
Begin

Declare @F1 As tinyint
Declare @F2 As tinyint
Declare @F3 As tinyint
Declare @F4 As tinyint
Declare @F5 As tinyint
Declare @F6 As tinyint

Declare @NPD As Varchar(50)

Declare @PDLen As tinyint

--Trim any space off the ends
SET @PD = RTRIM(LTRIM(@PD))

--Default just return the data, unless in proper foramt
SET @NPD = @PD

--Check for phone number that all ready has formatting, 
--we are only going to format a 'Pure' set of numbers.
--Check for formating, space 
SET @F1 = CHARINDEX('(', @PD)
SET @F2 = CHARINDEX(')', @PD)
SET @F3 = CHARINDEX('-', @PD)
SET @F4 = CHARINDEX('.', @PD)
SET @F5 = CHARINDEX(' ', @PD)
SET @F6 = @F1 +@F2 + @F3 + @F4 + @F5


IF @F6 = 0
--No formating, figure out the lenght
BEGIN
SET @PDLen = LEN(@PD)

    IF @PDLen = 10  SET @NPD = '('+SUBSTRING(@PD, 1, 3)+') '+SUBSTRING(@PD, 4, 3)+'-'+SUBSTRING(@PD, 7, 4)
    IF @PDLen = 11 AND SUBSTRING(@PD, 1, 1) = '1'  SET @NPD = '('+SUBSTRING(@PD, 2, 3)+') '+SUBSTRING(@PD, 5, 3)+'-'+SUBSTRING(@PD, 8, 4)
    IF @PDLen = 7  SET @NPD = '(   ) '+SUBSTRING(@PD, 1, 3)+'-'+SUBSTRING(@PD, 4, 4)

END

RETURN @NPD

END