[英]Convert fractional string to decimal
我有一些列,這些列的值要么是小數字符串(即6 11/32),要么是小數(1.5)。 是否有CAST
或CONVERT
調用可以將其轉換為一致的小數?
錯誤:
消息8114,級別16,狀態5,第1行將數據類型varchar轉換為數值時出錯。
我可以避免進行任何形式的解析嗎?
謝謝!
PS我正在使用SQL Server Management Studio 2012
。
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')訪問它
您需要解析。 正如尼爾斯所說,這不是一個好主意。 但是可以使用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
請注意,如果傳遞的內容與形式“ mm / nn”,“ xx mm / nn”或實際十進制數不匹配,則此操作將失敗。
這是沒有功能和存儲過程的解決方案-僅出於樂趣。 首先,您必須創建一個新列(我稱其為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
我不知道有任何數據庫系統或代碼框架可用於本地支持6 11/32
類的字符串。 最好的選擇是在相關表中添加一列,並使用腳本在其中對實際值進行歸一化,或者在其上創建一個自動執行此操作的視圖。 不過,這將需要一些復雜的代碼,而在SQL中完全不是一個好主意。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.