SQL Server 2008: ошибка при преобразовании типа данных nvarchar в число с плавающей точкой - PullRequest
3 голосов
/ 04 февраля 2012

В настоящее время устранение проблемы при выполнении этого 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 в число с плавающей точкой.

Действительно странная вещь, если я изменю 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. У кого-нибудь есть предложения? ТИА.

Ответы [ 3 ]

5 голосов
/ 04 февраля 2012

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

SET DataValue = CASE WHEN ISNUMERIC(DataValue)=1 THEN CAST(DataValue AS float) * 1.335 
                     ELSE 0 END
2 голосов
/ 04 февраля 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;
1 голос
/ 04 февраля 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 покажет вам те, которые не являются.

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