SQL Server 2008: ошибка преобразования типа данных nvarchar в float

В настоящее время устраняется проблема, связанная с запуском этого SQL-запроса:

UPDATE tblBenchmarkData 
SET OriginalValue = DataValue, OriginalUnitID = DataUnitID, 
    DataValue = CAST(DataValue AS float) * 1.335 
WHERE 
    FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5' 
    AND ZEGCodeID IN 
             (SELECT ZEGCodeID FROM tblZEGCode 
              WHERE(ZEGCode = 'C004') OR 
                   (LEFT(ZEGParentCode, 4) = 'C004'))

Выдает следующую ошибку:

Сообщение 8114, уровень 16, состояние 5, строка 1
Ошибка преобразования типа данных nvarchar в float.

Действительно странно, если я изменю UPDATE на SELECT, чтобы проверить, что полученные значения являются числовыми значениями:

SELECT DataValue 
FROM tblBenchmarkData 
WHERE FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5' 
AND ZEGCodeID IN 
         (SELECT ZEGCodeID 
          FROM tblZEGCode WHERE(ZEGCode = 'C004') OR 
                               (LEFT(ZEGParentCode, 4) = 'C004'))

Вот результаты:

DataValue
2285260
1205310

Хотел бы использовать TRY_PARSE или что-то в этом роде; однако мы работаем на SQL Server 2008, а не на SQL Server 2012. У кого-нибудь есть предложения? ТИА.


person user8128167    schedule 03.02.2012    source источник


Ответы (3)


Было бы полезно увидеть определение схемы tblBenchmarkData, но вы можете попробовать использовать ISNUMERIC в своем запросе. Что-то типа:

SET DataValue = CASE WHEN ISNUMERIC(DataValue)=1 THEN CAST(DataValue AS float) * 1.335 
                     ELSE 0 END
person csm8118    schedule 03.02.2012

Порядок исполнения не всегда соответствует ожиданиям.

Если вы устанавливаете предложение where, это обычно не означает, что вычисления в списке select будут применяться только к строкам, которые соответствуют этому where. SQL Server может легко принять решение о массовых вычислениях, а затем отфильтровать нежелательные строки.

Тем не менее, вы можете легко написать try_parse самостоятельно:

create function dbo.try_parse(@v nvarchar(30))
returns float
with schemabinding, returns null on null input
as
begin
  if isnumeric(@v) = 1
    return cast(@v as float);

  return null;
end;
person GSerg    schedule 03.02.2012

Итак, начнем с вашего запроса на обновление, который выдает ошибку (пожалуйста, простите меня за переписывание для моей ясности):

UPDATE B
SET
   OriginalValue = DataValue,
   OriginalUnitID = DataUnitID,
   DataValue = CAST(DataValue AS float) * 1.335
FROM
   dbo.tblBenchmarkData B
   INNER JOIN dbo.tblZEGCode Z
      ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
   B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
   AND (
      Z.ZEGCode = 'C004' OR 
      Z.ZEGParentCode LIKE 'C004%'
   )

Я думаю, вы обнаружите, что оператор SELECT с точно такими же выражениями даст ту же ошибку:

SELECT
   OriginalValue,
   DataValue NewOriginalValue,
   OriginalUnitID,
   DataUnitID OriginalUnitID,
   DataValue,
   CAST(DataValue AS float) * 1.335 NewDataValue
FROM
   dbo.tblBenchmarkData B
   INNER JOIN dbo.tblZEGCode Z
      ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
   B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
   AND (
      Z.ZEGCode = 'C004' OR 
      Z.ZEGParentCode LIKE 'C004%'
   )

Это должно показать вам строки, которые не могут быть преобразованы:

SELECT
    B.*
 FROM
    dbo.tblBenchmarkData B
    INNER JOIN dbo.tblZEGCode Z
       ON B.ZEGCodeID = Z.ZEGCodeID
 WHERE
    B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
    AND (
       Z.ZEGCode = 'C004' OR 
       Z.ZEGParentCode LIKE 'C004%'
    )
    AND IsNumeric(DataValue) = 0
    -- AND IsNumeric(DataValue + 'E0') = 0 -- try this if the prior doesn't work

Трюк в последней закомментированной строке состоит в том, чтобы прикрепить к строке что-то, чтобы только действительные числа были числовыми. Например, если вам нужны только целые числа, IsNumeric(DataValue + '.0E0') = 0 покажет вам те, которые не являются целыми числами.

person ErikE    schedule 03.02.2012
comment
Спасибо за ответ! Еще одна проблема, с которой я столкнулся, заключалась в том, что если данные представлены в экспоненциальном представлении, CAST не работает. Таким образом, чтобы решить эту проблему, выполните представление базы данных, которое меняет все числа с научной на стандартную запись, например, DataValue 2.86777e+006 5.43724e+006 - person user8128167; 06.02.2012
comment
Ага, если у вас уже есть научная запись, то мой трюк с добавлением «E0» не сработает. Но функция IsNumeric все равно должна вам помочь. - person ErikE; 06.02.2012