2017-09-11 117 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