2016-08-18 4 views
1

Я пытаюсь взять средний столбец в моей базе данных. Столбец AMOUNT и хранится как NVARCHAR(300),null.Ошибка преобразования типа данных nvarchar в числовой - SQL Server

Когда я пытаюсь преобразовать его в числовое значение, я получаю следующее сообщение об ошибке:

Msg 8114, Level 16, State 5, Line 1
Error converting datatype NVARCHAR to NUMBER

Вот что я прямо сейчас.

SELECT AVG(CAST(Reimbursement AS DECIMAL(18,2)) AS Amount 
FROM Database 
WHERE ISNUMERIC(Reimbursement) = 1 
    AND Reimbursement IS NOT NULL 
+0

Похоже у вас есть какие-то не-числовые значения в этом столбце ... – jarlh

+0

Какую версию SQLServer вы используете? – TheGameiswar

ответ

7

Вы бы подумали, что ваш код будет работать. Однако SQL Server не гарантирует, что предложение WHERE фильтрует базу данных до преобразования для SELECT. По-моему, это ошибка. По мнению Microsoft, это функция оптимизации.

Следовательно, ваш WHERE не гарантируется. Даже при использовании CTE проблема не устраняется.

Лучшее решение TRY_CONVERT() доступно в SQL Server 2012+:

SELECT AVG(TRY_CONVERT(DECIMAL(18,2), Reimbursement)) AS Amount 
FROM Database 
WHERE ISNUMERIC(Reimbursement) = 1 AND Reimbursement IS NOT NULL; 

В более ранних версиях, вы можете использовать CASE. CASEделает гарантирует последовательное упорядочение статей, так:

SELECT AVG(CASE WHEN ISNUMERIC(Reimbursement) = 1 AND Reimbursement IS NOT NULL 
       THEN CONVERT(DECIMAL(18,2), Reimbursement)) 
      END) 
FROM Database; 

Поскольку AVG() игнорирует NULL значения, то WHERE не является необходимым, но вы можете включить его, если вам нравится.

Наконец, можно упростить код, используя вычисляемый столбец:

alter database add Reimbursement_Value as 
    (CASE WHEN ISNUMERIC(Reimbursement) = 1 AND Reimbursement IS NOT NULL 
      THEN CONVERT(DECIMAL(18,2), Reimbursement)) 
    END); 

Тогда вы могли бы написать код, как:

select avg(Reimbursement_Value) 
from database 
where Reimbursement_Value is not null; 
1

Quote from MSDN ...

ISNUMERIC returns 1 for some characters that are not numbers, such as plus (+), minus (-), and valid currency symbols such as the dollar sign ($). For a complete list of currency symbols, see money and smallmoney

select isnumeric('+')---1 
select isnumeric('$')---1 

поэтому постарайтесь, чтобы добавить, чтобы избежать нечисловой номера Мессинг с ..

выводе
WHERE Reimbursement NOT LIKE '%[^0-9]%' 

Если вы на SQLServer 2012, вы можете попробовать использовать TRY_Convert, который выводит значение null для ошибок преобразования.

SELECT AVG(try_convert(DECIMAL(18,2),Reimbursement)) 
from 
table 
+1

'try_convert()' правильный ответ. –

0

Я предполагаю, что, поскольку это Nvarchar, вы найдете там какие-то значения с '$', '.' Или a (,). Я хотел бы выполнить запрос likt это:

SELECT Amount 
FROM database 
WHERE Amount LIKE '%$%' OR 
     Amount LIKE '%.%' OR 
     Amount LIKE '%,%' 

Посмотрите, что вы получите, и я думаю, вы получите некоторые строки возвращаются, а затем обновить эти строки и попробовать еще раз.

В настоящее время ваш запрос будет вытаскивать все числа, которые не являются числовыми, что является причиной того, что он тоже терпит неудачу. Вместо этого попробуйте запустить:

SELECT AVG(CAST(Reimbursement AS DECIMAL(18,2)) AS Amount 
FROM Database 
--Changed ISNUMERIC() = to 0 for true so it will only pull numeric numbers. 
WHERE ISNUMERIC(Reimbursement) = 0 and Reimbursement IS NOT NULL 
+0

Привет @Wes Palmer Я провел первую строчку, и я получаю и выводю вот так. $ 11.162 $ 11.162 $ 11.162 $ 11.162 $ 11.162 $ 10.194 это может быть связано с тем, что есть знак доллара ведущий все свои ценности, когда я пытаюсь CONVER его к INT? –

+0

Да Знаки доллара и запятая, чтобы отделить тысячи от сотен, также приведут к ее провалу, потому что она хранится как обычный текст. Таким образом, вам, возможно, придется обновить эти значения до некоторого числа, а затем использовать свой скрипт. –

Смежные вопросы