2017-09-11 115 views
1

排在首位,遗憾的代码量,我要发布! :(但我卡住了。我已经尝试了很多事情,没有一个似乎工作。我真的不知道哪里出错......无效的长度参数错误 - SQL Server 2008中

,我要解释一下这个功能是什么,它的转换时间值自定义格式到只有几秒钟。如果你想知道更多,该值表示起搏器检测到arrhytmic发作的持续时间。例如,如果持续时间为2分35秒,自定义格式是“PT2M35S”,并且它是一个字符串

我的函数(最初是在VBA中创建的,现在我试图迁移到SQL Server)通过char读取文本char,并根据char进行不同的计算。将代码转换为SQL函数:

ALTER FUNCTION PTtoSeconds(@duration varchar(30)) 
RETURNS FLOAT 
AS 
BEGIN 
    DECLARE @posLetraReciente INT 
    DECLARE @hayComa INT 
    DECLARE @posComa INT 

    SET @posLetraReciente = 1 
    SET @hayComa = 0 
    SET @posComa = 0 

    DECLARE @texto VARCHAR(30) 
    SET @texto = @duration 

    DECLARE @tiempoTotal FLOAT 
    DECLARE @factorTiempo FLOAT 
    DECLARE @incremento FLOAT 

    SET @tiempoTotal = 0.0 
    SET @factorTiempo = 0 
    SET @incremento = 0 

    DECLARE @caracter VARCHAR(30) 
    DECLARE @counter INT 
    SET @counter = 1 

    DECLARE @longtexto INT 
    SET @longtexto = LEN(@duration) 

    WHILE @counter < @longtexto 
     BEGIN 
     SET @caracter = SUBSTRING(@texto,@counter, 1) 

     SET @hayComa = CASE @caracter 
       WHEN '.' THEN 1 
       ELSE 0 
       END 

     SET @factorTiempo = CASE 
        WHEN @caracter = 'D' THEN 86400 
        WHEN @caracter = 'H' THEN 3600 
        WHEN @caracter = 'M' THEN 60 
        WHEN (@caracter = 'S' AND @hayComa = 1) THEN (1/(POWER(10,(@counter - (@posComa + 1))))) 
        WHEN (@caracter = 'S' AND @hayComa = 0) THEN 1 
        WHEN @caracter = 'T' THEN 0 
        WHEN @caracter = '.' THEN 1 
        ELSE 0 
     END 

     SET @posLetraReciente = @counter 

     SET @incremento = CASE 
       WHEN @caracter = 'D' THEN CAST((SUBSTRING(@texto, (@posLetraReciente + 1), @counter - (@posLetraReciente + 1))) as FLOAT) * @factorTiempo 
       WHEN @caracter = 'H' THEN CAST((SUBSTRING(@texto, (@posLetraReciente + 1), @counter - (@posLetraReciente + 1))) as FLOAT) * @factorTiempo 
       WHEN @caracter = 'M' THEN CAST((SUBSTRING(@texto, (@posLetraReciente + 1), @counter - (@posLetraReciente + 1))) as FLOAT) * @factorTiempo 
       WHEN (@caracter = 'S' AND @hayComa = 1) THEN CAST((SUBSTRING(@texto, (@posLetraReciente + 1), @counter - (@posLetraReciente + 1))) as FLOAT) * @factorTiempo 
       WHEN (@caracter = 'S' AND @hayComa = 0) THEN CAST((SUBSTRING(@texto, (@posLetraReciente + 1), @counter - (@posLetraReciente + 1))) as FLOAT) * @factorTiempo 
       WHEN @caracter = 'T' THEN CAST((SUBSTRING(@texto, (@posLetraReciente + 1), @counter - (@posLetraReciente + 1))) as FLOAT) * @factorTiempo 
       WHEN @caracter = '.' THEN CAST((SUBSTRING(@texto, (@posLetraReciente + 1), @counter - (@posLetraReciente + 1))) as FLOAT) * @factorTiempo 
       ELSE @factorTiempo 
     END 

     SET @tiempoTotal = @tiempoTotal + @incremento 
     SET @counter = @counter + 1 

    END 

    RETURN @tiempoTotal 
END 

错误调用SUBSTRING时出现。它说以下内容:

Invalid length parameter passed to the LEFT or SUBSTRING function. 

而我不知道是什么原因造成的。我试图在另一个查询separatedly使用SUBSTRING:

select X = SUBSTRING('PT3M44S',2,1) 

,它工作正常。这可能意味着错误来自变量@counter,但我不知道为什么。

任何方向都会受到欢迎。

谢谢!我尽力做到尽可能具体。如果你认为我没有,请善待并告诉我为什么!

伊格纳西奥

回答

0

你需要重写你的逻辑。

我搜索@posLetraReciente在你的代码,发现这个:SET @posLetraReciente = @counter

而这种表达@counter - (@posLetraReciente + 1)总是给你-1

你通过这个-1为您SUBSTRING第三个参数是无效

+0

没错!当我试图使用你的答案时,我发现它。好吧,现在没有“无效的长度参数...“错误,但该函数在调用时返回一个空值: 选择dbo.PTtoSeconds('PT3M44S') 但我认为要求这个答案可能超出此线程的范围... –

+0

>> >但函数在调用<<<时从函数中提取代码并在函数外部执行时返回空值;在WHILE循环中的每次SET操作后添加PRINT语句,这将帮助您找到错误的步骤 – sepupic

0

的问题应该是在这部分代码:

SUBSTRING(@texto, (@posLetraReciente + 1), @counter - (@posLetraReciente + 1))

如果SET @counter = 1SET @posLetraReciente = @counter然后@counter - (@posLetraReciente + 1)总是给你-1

,因为它说的documentation

第三个参数长度是一个正整数或bigint表达式,它指定将返回表达式的多少个字符。如果长度为负值,则会生成错误并且语句被终止。如果开始和长度的总和大于表达式中的字符数,则返回从开始处开始的整个值表达式。

+0

Thanks!I发现它现在错误没有被抛出,但功能不能正常工作...我会看看我能做什么!:D (但是,如果你仍然对此感兴趣,你可以继续帮助......我真的很感激,但我会理解你决定不帮忙!) –

+0

我改了这行'@counter (@posLetraReciente + 1)'到'(@posLetraReciente + 1) - @ counter'(不知道如果你想对长度做什么)并执行'Select dbo.PTtoSeconds('PT3M44S')'并返回“240”。我不确定你的下一个错误不起作用 – Ragmar