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'))

Резултати в следната грешка:

Msg 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. Някой има ли предложения? TIA.


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