2015-01-31 81 views
1

我有一列數據類型varchar,其中一些包含數字(十進制)值。我需要找到數值大於100的所有行。我使用ISNUMERIC來篩選包含數字的行,之後我嘗試使用CASTCONVERT將數字更改爲decimal值。我讀了另一個建議使用子查詢將解決這個問題是說,但我已經試過了也沒有運氣SQL Server 2008 R2數據類型轉換錯誤

這是我收到錯誤消息:

Arithmetic overflow error converting varchar to data type numeric.

代碼:

select field_name 
from table_name 
where ISNUMERIC(field_name) = 1 and 
     field_name in (select cast(field_name as decimal) 
        from table_name 
        where ISNUMERIC(field_name) = 1 
         and field_name not like '%,%' 
         and field_name not like '%-%' 
         and field_name != '.' 
         and field_name > 100.00) 

回答

1

這是您的查詢:

select field_name 
from table_name 
where ISNUMERIC(field_name) = 1 and 
     field_name in (select cast(field_name as decimal) 
        from table_name 
        where ISNUMERIC(field_name) = 1 and 
          field_name not like '%,%' and 
          field_name not like '%-%' and 
          field_name <> '.' and 
          field_name > 100 
        ) 

您正在假定在select之前過濾子句。這不是真的。實際上,SQL Server將cast()推送到讀取數據的操作。然後它應用過濾器。

事實上,子查詢和公用表表達式也不能保證評估的順序。什麼是case(至少在這種情況下不涉及聚合)。所以,你可以寫你的查詢爲:

select field_name 
from table_name 
where (case when ISNUMERIC(field_name) = 1 and 
       field_name not like '%,%' and 
       field_name not like '%-%' and 
       field_name <> '.' 
      then cast(field_name as decimal) 
     end) > 100; 

我看不到子查詢的理由。

0

查詢有幾個問題,但是導致錯誤的主要問題很簡單:在進行比較之前,field_name > 100.00條件不會將VARCHAR字段轉換爲數字類型。將其更改爲CONVERT(DECIMAL(38, 18), [field_name])將解決您所看到的錯誤。

運行以下一次看到它的工作,然後取消對AND [field_name] > 100.00線,並再次運行,你會得到你已經看到關於「算術溢出錯誤轉換VARCHAR數據類型數字」的錯誤:

DECLARE @table_name TABLE (field_name VARCHAR(50) NOT NULL); 
INSERT INTO @table_name (field_name) VALUES ('1234.5678'); 
INSERT INTO @table_name (field_name) VALUES ('12.78'); 
INSERT INTO @table_name (field_name) VALUES ('s'); 
INSERT INTO @table_name (field_name) VALUES ('2015-01-30'); 
INSERT INTO @table_name (field_name) VALUES ('51234.5678'); 
INSERT INTO @table_name (field_name) VALUES ('987651234.56789124'); 

SELECT field_name 
FROM @table_name 
WHERE ISNUMERIC([field_name]) = 1 
AND [field_name] IN (
         SELECT CAST([field_name] AS DECIMAL) 
         FROM @table_name 
         WHERE ISNUMERIC([field_name]) = 1 
         AND [field_name] NOT LIKE '%,%' 
         AND [field_name] NOT LIKE '%-%' 
         AND [field_name] != '.' 
--      AND [field_name] > 100.00 
         AND CONVERT(DECIMAL(38, 18), [field_name]) > 100.00 
        ); 

,仍存在一些問題:

  1. 子查詢,如問題所示,是沒有意義的返回轉換值的列表。有可能查詢已經被修改用於在這裏發佈,因此它的真實形式更有意義,但子查詢並不需要,也無濟於事。
  2. CASTDECIMAL未指定精確度和比例。默認值分別爲18和0。意思是說,你正在將這些字符串轉換成DECIMAL(18, 0)。這似乎沒有任何影響,但最好指定值。運行SELECT CAST('123.456' AS DECIMAL)將返回123
  3. 你真的不需要需要來過濾掉逗號,因爲這些值可以被刪除,給你一個可以轉換的值。當然,除非你有一些代碼,如12,34,56,78。但是,如果它們是有效的號碼,如1,234.56,那麼你可以使用REPLACE([field_name], ',', '')
  4. 在該示例的頂部添加以下兩行對與插入片段上述錯誤:

    INSERT INTO @table_name (field_name) VALUES ('1,234.5678'); 
    INSERT INTO @table_name (field_name) VALUES ('.'); 
    

所有這些都可以通過執行以下操作來完成(將上面的查詢替換爲下面的查詢,但保留DECLAREINSERT s):

SELECT field_name, CAST([field_name] AS DECIMAL(38, 18)) AS [DecimalValue] 
FROM @table_name 
WHERE ISNUMERIC(field_name) = 1 
AND field_name NOT LIKE '%,%' 
AND field_name NOT LIKE '%-%' 
AND field_name <> '.' 
AND CONVERT(DECIMAL(38, 18), REPLACE([field_name], ',', '')) > 100.00; 
相關問題