Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
让某人使用SQL Server函数,该函数给定一个模式和一个值,可以返回一个规范化的值_Sql_Function_Design Patterns_Sql Server 2008 R2 - Fatal编程技术网

让某人使用SQL Server函数,该函数给定一个模式和一个值,可以返回一个规范化的值

让某人使用SQL Server函数,该函数给定一个模式和一个值,可以返回一个规范化的值,sql,function,design-patterns,sql-server-2008-r2,Sql,Function,Design Patterns,Sql Server 2008 R2,我正在用SQL2008R2编写一个函数,我可以给它一些参数,比如值varchar、模式varchar、分隔符char和填充符char。然后我想用模式'000.000.000.000'给值'22687',一个分隔符'。'填充将是'0',然后我希望函数将返回'000.000.022.687',是否有任何函数已经完成,可以这样做 大概是这样的: DECLARE @valor VARCHAR(30) DECLARE @formato VARCHAR(30) DECLARE @separador CHAR

我正在用SQL2008R2编写一个函数,我可以给它一些参数,比如值varchar、模式varchar、分隔符char和填充符char。然后我想用模式'000.000.000.000'给值'22687',一个分隔符'。'填充将是'0',然后我希望函数将返回'000.000.022.687',是否有任何函数已经完成,可以这样做

大概是这样的:

DECLARE @valor VARCHAR(30)
DECLARE @formato VARCHAR(30)
DECLARE @separador CHAR(1) 
DECLARE @rellenarcon CHAR(1)

SELECT @valor       = '22959'
SELECT @formato     = '000.000.000.000'
SELECT @separador   = '.'
SELECT @rellenarcon = '0'

DECLARE @n  INTEGER
DECLARE @m  INTEGER
DECLARE @i  INTEGER
DECLARE @j  INTEGER

SELECT @n   = LEN(@formato)
SELECT @m   = LEN(@valor)
SELECT @i   = 1
SELECT @j   = 1

DECLARE @res2 varchar(30)

SELECT @res2 = ''
SELECT @valor = REVERSE(@valor)

WHILE @i<=@n
BEGIN
    if SUBSTRING(@formato,@i,1) <> @separador
    begin
        IF @j<=@m
        BEGIN
            SELECT @res2 = @res2 + SUBSTRING(@valor,@j,1)
            SELECT @i=@i+1
            SELECT @j=@j+1
        END
        ELSE
        BEGIN
            SELECT @res2 = @res2 + @rellenarcon
            SELECT @i=@i+1      
        END
    end
    else
    BEGIN
        SELECT @res2 = @res2 + @separador
        SELECT @i=@i+1
    END
END

print reverse(@res2)
是从java到tsql的交叉代码,java中的原始代码是:

    public static String formatear(String valor, String formato, char separator, 
        char fillWith, Map<Integer, String> params) {

    int n = formato.length() - 1;
    int m = valor.length() - 1;
    int i = n;
    int j = m;

    StringBuilder res = new StringBuilder(formato);

    for(; i >= 0; i--) {
        if(res.charAt(i) != separator) {
            if(j >= 0) {
                res.deleteCharAt(i);
                res.insert(i, valor.charAt(j--));
            } else {
                res.deleteCharAt(i);
                res.insert(i, fillWith);
            }
        }
    }
    if(params != null) {
        Set<Integer> keys = params.keySet();

        for(Integer key : keys) {
            i = key;
            res.deleteCharAt(i);
            res.insert(i, params.get(key));
        }
    }

    return res.toString();
}
此查询将执行以下操作:

;with cteZeroPadded(Num) as
(
    Select  Right('000000000000' + '22687', 12)
)
,cteSplit as
(
    Select  SUBSTRING(Num, 1, 3) Col1
            ,SUBSTRING(Num, 4, 3) Col2
            ,SUBSTRING(Num, 7, 3) Col3
            ,SUBSTRING(Num, 10, 3) Col4
    From    cteZeroPadded
)
Select  Col1 + '.' + Col2 + '.' + Col3 + '.' + Col4
From    cteSplit

在SQLServer2005+中,可以将选项与递归


请参见

上的演示,以下假设输入格式正确,例如,值不长于模式

declare @Pattern as VarChar(64) = '000.000.000.000';
declare @Fill as Char = '0';
declare @Value as VarChar(64) = '22687';
declare @False as Bit = 0;
declare @True as Bit = 1;

with Gargoyle as (
  select @Pattern as Pattern, @Value as Value, Cast( '' as VarChar(64) ) as Buffer,
    case when Right( @Pattern, 1 ) = @Fill then @True else @False end as Fill
  union all
  select
    -- Always consume a character from the pattern.
    Left( Pattern, Len( Pattern ) - 1 ),
    -- Consume a character from the value if the pattern contains fill at the current position.
    case
      when Fill = @True and Value != '' then Left( Value, Len( Value ) - 1 )
      else Value end,
    -- Add the correct character to the buffer.
    Cast( case when Fill = @True and Value != '' then Right( Value, 1 ) else Right( Pattern, 1 ) end + Buffer as VarChar(64) ),
    -- Check the next pattern character for fill.
    case
      when Len( Pattern ) = 1 then @False
      when Substring( Pattern, Len( Pattern ) - 1, 1 ) = @Fill then @True
      else @False end
    from Gargoyle
    where Pattern != ''
  )
  select Buffer
    from Gargoyle
    where Pattern = '';
或者,作为一种功能:

create function dbo.PatternFill( @Pattern as VarChar(64), @Fill as Char, @Value as VarChar(64) )
  returns VarChar(64)
  as
  begin
  declare @Buffer as VarChar(64) = ''
  declare @PatternChar as Char = Right( @Pattern, 1 )
  declare @ValueChar as Char = Right( @Value, 1 )
  while @Pattern != ''
    begin
    if @PatternChar = @Fill and @ValueChar != ''
      begin
      -- Replace a fill character with a value character.
      select @Buffer = @ValueChar + @Buffer
      if Len( @Value ) > 1
        select @Value = Left( @Value, Len( @Value ) - 1 ), @ValueChar = Right( @Value, 1 )
      else
        select @ValueChar = '', @Value = ''
      end
    else
      begin
      -- Copy the pattern character.
      select @Buffer = @PatternChar + @Buffer
      end
    if Len( @Pattern ) > 1
      select @Pattern = Left( @Pattern, Len( @Pattern ) - 1 ), @PatternChar = Right( @Pattern, 1 )
    else
      select @PatternChar = '', @Pattern = ''
    end
  return @Buffer
  end
go

declare @Result as VarChar(64)
declare @Count as Int = 1000000
declare @Start as DateTime = GetDate()
while @Count > 0
  select @Result = dbo.PatternFill( '000.000.000.000', '0', '22687' ), @Count = @Count - 1
select @Result as [Result], DateDiff( ms, @Start, GetDate() ) as [Total ms]

我的笔记本上的1000000次迭代耗时151656ms,但它正忙着启动。这是一个简单的计时,不需要校正空循环或调用空函数所消耗的时间。

什么会消耗这些数据?通常我会尽量避免在数据库端格式化这样的类型…合理的描述是:给定@Pattern='000.000.000'、@Fill='0'和@Value='22687',将@Pattern中的填充字符从右向左替换为@Value中的字符吗?分隔符似乎无关紧要。这是一段java代码,用于Birt中的报告,我需要对sql@AbeMiessler进行交叉转换。数据传回java应用程序时,您可以格式化吗?@AbeMiessler可能。。我只是在编写sql方面的代码,java应用程序是另一个程序员,我要问的是,因为sql中的这些东西可能很昂贵。这不需要@Pattern和@Separator作为输入。啊,的确如此。我被困在“如果这样怎么办”的问题上,其余的都失败了。我不知道如何让它充满活力……我是CTE的新手,让我试着去理解它。。哈哈,但它看起来非常令人印象深刻。@Artenation-只要将最后一部分更改为从石像鬼中选择*,你就会看到发生了什么。我感觉自己就像弗林的儿子一样,当他进入了特隆的世界。。非常感谢您接受HABOanswer。。再一次非常感谢你,我正在向我的工作团队展示你的代码@尽管速度很慢。。32秒,只有209.063行。。我那难看的代码在HABO的网站上运行了2到3秒
create function dbo.PatternFill( @Pattern as VarChar(64), @Fill as Char, @Value as VarChar(64) )
  returns VarChar(64)
  as
  begin
  declare @Buffer as VarChar(64) = ''
  declare @PatternChar as Char = Right( @Pattern, 1 )
  declare @ValueChar as Char = Right( @Value, 1 )
  while @Pattern != ''
    begin
    if @PatternChar = @Fill and @ValueChar != ''
      begin
      -- Replace a fill character with a value character.
      select @Buffer = @ValueChar + @Buffer
      if Len( @Value ) > 1
        select @Value = Left( @Value, Len( @Value ) - 1 ), @ValueChar = Right( @Value, 1 )
      else
        select @ValueChar = '', @Value = ''
      end
    else
      begin
      -- Copy the pattern character.
      select @Buffer = @PatternChar + @Buffer
      end
    if Len( @Pattern ) > 1
      select @Pattern = Left( @Pattern, Len( @Pattern ) - 1 ), @PatternChar = Right( @Pattern, 1 )
    else
      select @PatternChar = '', @Pattern = ''
    end
  return @Buffer
  end
go

declare @Result as VarChar(64)
declare @Count as Int = 1000000
declare @Start as DateTime = GetDate()
while @Count > 0
  select @Result = dbo.PatternFill( '000.000.000.000', '0', '22687' ), @Count = @Count - 1
select @Result as [Result], DateDiff( ms, @Start, GetDate() ) as [Total ms]