Frage

I imported a flat file into an SQL database and it created all of the fields as varchar(50). I was able to change the data type of most fields, but hit an error in the weight field. All of the data in the weight field is less than 6 characters in total length and is either a whole integer or a decimal. I have tried both:

UPDATE MAWB
SET Weight = CAST(Weight AS decimal(12,2))

and:

ALTER TABLE MAWB
ALTER COLUMN [Weight] decimal(10,2)

I always get the error: Error converting data type varchar to numeric.

I've checked that all of the fields are considered numeric using:

SELECT COUNT(*)
FROM MAWB
WHERE ISNUMERIC(Weight) = 0

I've also tried LTRIM and RTRIM just to be safe, but still get the error when I try to change the field. Does anyone know what else might be causing this error?

War es hilfreich?

Lösung 2

You can find the offending rows with this query:

SELECT *
FROM MAWB
WHERE TRY_CONVERT(decimal(12,2),Weight) IS NULL
AND Weight IS NOT NULL

Andere Tipps

So, ISNUMERIC() is far from perfect. It can return true for values like e, $, '€' and tab, and many others you wouldn't expect. But of course you can't convert those to every numeric type (ISNUMERIC() merely identifies that it can be converted to at least one of the numeric types). LTRIM() and RTRIM() won't help because they won't clear tab and other similar characters.

To identify rows which are really not numeric:

SELECT weight FROM dbo.table WHERE column NOT LIKE '%[^0-9.-]%';

Or you can write a more elaborate scalar function, like the one in the link above, which handles more edge cases:

CREATE FUNCTION dbo.isReallyNumeric  
(  
    @num VARCHAR(64)  
)  
RETURNS BIT  
BEGIN  
    IF LEFT(@num, 1) = '-'  
        SET @num = SUBSTRING(@num, 2, LEN(@num))  

    DECLARE @pos TINYINT  

    SET @pos = 1 + LEN(@num) - CHARINDEX('.', REVERSE(@num))  

    RETURN CASE  
    WHEN PATINDEX('%[^0-9.-]%', @num) = 0  
        AND @num NOT IN ('.', '-', '+', '^') 
        AND LEN(@num)>0  
        AND @num NOT LIKE '%-%' 
        AND  
        (  
            ((@pos = LEN(@num)+1)  
            OR @pos = CHARINDEX('.', @num))  
        )  
    THEN  
        1  
    ELSE  
    0  
    END  
END  
GO 

Once you've identified these rows and fixed the data, please, please, please fix the table too.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top