2014-11-20 26 views
0

我有幾列有分數字符串(即6 11/32)或小數(1.5)的值。是否有CASTCONVERT調用可以將這些調用轉換爲一致的小數?將分數字符串轉換爲十進制

錯誤:

消息8114,級別16,狀態5,第1行 錯誤數據類型爲varchar轉換爲數字。

我可以避免做任何形式的解析嗎?

謝謝!

P.S.我在SQL Server Management Studio 2012工作。

回答

2
CREATE FUNCTION ufn_ConvertToNumber(@STR VARCHAR(50)) 
RETURNS decimal(18,10) 
AS 
BEGIN 
     DECLARE @L VARCHAR(50) = '' 
     DECLARE @A DECIMAL(18,10) = 0 
     SET @STR = LTRIM(RTRIM(@STR)); -- Remove extra spaces 
     IF ISNUMERIC(@STR) > 0 SET @A = CONVERT(DECIMAL(18,10), @STR) -- Check to see if already real number 
     IF CHARINDEX(' ',@STR,0) > 0 
     BEGIN 
      SET @L = SUBSTRING(@STR,1,CHARINDEX(' ',@STR,0) - 1) 
      SET @STR = SUBSTRING(@STR,CHARINDEX(' ',@STR,0) + 1 ,50) 
      SET @A = CONVERT(DECIMAL(18,10), @L) 
     END 
     IF CHARINDEX('/',@STR,0) > 0 
     BEGIN 
      SET @L = SUBSTRING(@STR,1,CHARINDEX('/',@STR,0) - 1) 
      SET @STR = SUBSTRING(@STR,CHARINDEX('/',@STR,0) + 1 ,50) 
      SET @A = @A + (CONVERT(DECIMAL(18,10), @L)/CONVERT(DECIMAL(18,10), @STR) ) 
     END 
     RETURN @A 
END 
GO 

然後通過選擇dbo.ufn_ConvertToNumber訪問它(「5 9/5」)

+0

比我的更健壯一點。 +1 – 2014-11-21 00:10:05

0

我不知道任何數據庫系統或此問題的代碼框架,原生支持像6 11/32這樣的字符串。您最好的選擇是在相關表格中添加一列,並用腳本對其中的實際值進行非規範化處理,或者在其上創建一個自動完成的視圖。但是,它會花費一些複雜的代碼,並且在SQL中完成它可能不是一個好主意。

+0

Excel支持分數:) – 2014-11-20 23:35:09

+0

雖然我曾經看到一些非常糟糕的Web應用程序使用Excel作爲他們的數據層,我不會將其完全稱爲「數據庫系統」;)Excel是最終用戶工具,因此支持最終用戶符號更有意義。 – 2014-11-20 23:38:05

+0

分數類通常作爲開始OOP編程類的練習。這很容易做到,並且可以通過搜索「C#分數類」或「Java分數類」輕鬆找到。 – 2014-11-20 23:38:12

1

你需要解析。正如尼爾斯所說,這不是一個好主意;但它可以通過T-SQL標量函數簡單地完成。

CREATE FUNCTION dbo.FracToDec (@frac VARCHAR(100)) 
RETURNS DECIMAL(14, 6) 
AS 
    BEGIN 
     RETURN CASE 
      WHEN @frac LIKE '% %/%' 
       THEN CAST(LEFT(@frac, CHARINDEX(' ', @frac, 1) -1) AS DECIMAL(14,6)) + 
        (CAST(SUBSTRING(@frac, CHARINDEX(' ', @frac, 1) + 1, CHARINDEX('/', @frac, 1)-CHARINDEX(' ',@frac,1)-1) AS DECIMAL(14,6)) 
        /CAST(RIGHT(@frac, LEN(@frac) - CHARINDEX('/', @frac, 1)) AS DECIMAL(14,6))) 
      WHEN @frac LIKE '%/%' 
       THEN CAST(LEFT(@frac, CHARINDEX('/', @frac, 1) - 1) AS DECIMAL(14,6))/CAST(RIGHT(@frac, LEN(@frac) - CHARINDEX('/', @frac, 1)) AS DECIMAL(14,6)) 
      ELSE 
       CAST(@frac AS DECIMAL(14,6)) 
      END 
    END 
GO 

-- Test cases 
SELECT dbo.FracToDec('22/7'), dbo.fracToDec('3.117'), dbo.fracToDec('7 3/4') 

-- Output 
-- 3.142857 3.117000 7.750000 

注意,這將失敗,如果通過實際上並不匹配形式的內容「毫米/ NN」,「XX毫米/ NN」還是真正的小數。

1

這裏是沒有的功能和存儲過程的解決方案 - 只爲它的樂趣。首先,你必須使用下面的查詢來創建新的列(我稱之爲decimal),然後用從原來的混合格式塔(稱inconsistent)轉換的值填充它:

UPDATE "my_table" 
SET  "decimals" = CASE WHEN CHARINDEX('/', "inconsistent") > 0 
          THEN CAST(CASE WHEN CHARINDEX(' ', 
                 RTRIM(LTRIM("inconsistent"))) > 0 
             THEN LEFT(RTRIM(LTRIM("inconsistent")), 
                CHARINDEX(' ', 
                  RTRIM(LTRIM("inconsistent"))) 
                - 1) 
             ELSE '0' 
            END AS FLOAT) 
           + CAST(SUBSTRING(RTRIM(LTRIM("inconsistent")), 
               CHARINDEX(' ', 
                  RTRIM(LTRIM("inconsistent"))) 
               + 1, 
               CHARINDEX('/', 
                  RTRIM(LTRIM("inconsistent"))) 
               - 1 - CHARINDEX(' ', 
                   RTRIM(LTRIM("inconsistent")))) AS FLOAT) 
          /CAST(RIGHT(RTRIM(LTRIM("inconsistent")), 
              LEN(RTRIM(LTRIM("inconsistent"))) 
              - CHARINDEX('/', 
                 RTRIM(LTRIM("inconsistent")))) AS FLOAT) 
          ELSE CAST(RTRIM(LTRIM("inconsistent")) AS FLOAT) 
        END 
+0

不可讀的榮譽:)爲什麼backquotes雖然? – 2014-11-23 03:42:20

+0

而我其實在想有人會發現它優雅:))哦,殘酷的世界! :))笑話分開,當然要感謝!至於反引號:習慣了MySQL(精確到PhpMyAdmin),需要那些正確處理數據庫/表/列名(不知道它們是否可以正常工作 - 可能它會 - 但我以某種方式得到了這種習慣) 。意識到這個問題是關於MS SQL的,但是老習慣很難(另外還應該工作)。這裏的一些故事爲雅:) – 2014-11-23 03:52:09

+1

其實反引號* *不*工作在MS SQL,只是試過。可以是「雙引號」或[括號]。而MS SQL沒有'IF()'結構;它是'CASE當cond THEN val1 ELSE val2 END'時。對不起:( – 2014-11-23 16:04:24

相關問題