消息8114,级别16,状态5,行1错误将数据类型nvarchar转换为实数

时间:2013-06-11 22:01:23

标签: sql sql-server tsql

目前,我正在执行以下查询并收到以上错误消息:

SELECT dbo.qryOtherFieldDataVerifySource.ItemID,
       dbo.qryOtherFieldDataVerifySource.EDGRDataID,
       dbo.qryOtherFieldDataVerifySource.LineItemID,
       dbo.qryOtherFieldDataVerifySource.ZEGCodeID,
       dbo.qryOtherFieldDataVerifySource.DataValue,
       dbo.tblBC.AcceptableValues,
       dbo.qryOtherFieldDataVerifySource.DataUnitID,
       dbo.qryOtherFieldDataVerifySource.DataDate,
       dbo.tblBC.DataTypeID,
       CASE
         WHEN DataTypeID = '{5951994B-BF47-4117-805D-B8F85FAB76A8}'
              AND ISNUMERIC(DataValue) = 1 THEN ( CASE
                                                    WHEN CAST(DataValue AS FLOAT(8)) >= 0 THEN 1
                                                    ELSE 0
                                                  END )
         ELSE 0
       END AS ValidPositiveNumericValue,
       CASE DataTypeID
        WHEN '{A6317BA5-F8FB-4866-A26B-24594650C2DC}'THEN ( CASE UPPER(DataValue)
        WHEN 'TRUE' THEN 1
        WHEN 'FALSE' THEN 1
        WHEN 'YES' THEN 1
        WHEN 'NO' THEN 1
        WHEN 'Y' THEN 1
        WHEN 'N' THEN 1
        WHEN '0' THEN 1
        WHEN '1' THEN 1
        ELSE 0
      END )
         WHEN '{5951994B-BF47-4117-805D-B8F85FAB76A8}' THEN ISNUMERIC(DataValue)
         ELSE 1
       END AS ValidDataType,
       dbo.tblZEGCode.ZEGCode,
       dbo.qryOtherFieldDataFieldName.FieldName
FROM   dbo.qryOtherFieldDataVerifySource
       LEFT OUTER JOIN dbo.qryOtherFieldDataFieldName
         ON dbo.qryOtherFieldDataVerifySource.ItemID = dbo.qryOtherFieldDataFieldName.ItemID
       LEFT OUTER JOIN dbo.tblBC
                       RIGHT OUTER JOIN dbo.tblZEGCode
                         ON dbo.tblBC.BCID = dbo.tblZEGCode.BCID
         ON dbo.qryOtherFieldDataVerifySource.ZEGCodeID = dbo.tblZEGCode.ZEGCodeID 

有人有任何建议吗?

3 个答案:

答案 0 :(得分:4)

我建议查找阻止你转换为float(也就是真实)类型的错误值,并在测试之前将e0连接到值:

SELECT *
FROM dbo.YourTable
WHERE
   DataTypeID = '{5951994B-BF47-4117-805D-B8F85FAB76A8}' -- the type for float
   AND IsNumeric(
      DataValue + CASE WHEN DataValue NOT LIKE '%[ed]%' THEN 'e0' ELSE '' END
   ) = 0
   AND IsNumeric(DataValue) = 1
;

这适用于SQL Server 2000及更高版本。

更新1 :由于您分享了您只想查找那些无法轻易检测到的内容,而不是所有那些不是真正数字的内容,我添加了第二个IsNumeric

更新2 :您最后告诉我,您的一些价值观已经包含科学记数法。这非常容易处理。我已经更新了上面的查询。请试试它的大小。

对于使用SQL Server 2012或更高版本的任何人来说,使用TRY_PARSE最好解决此问题:

SELECT TRY_PARSE(Value AS float)

这会将任何值转换为float,但会为其他任何值返回NULL。因此,您可以通过检查此表达式是否IS NULL来检查转换为float是否会失败。

答案 1 :(得分:0)

创建以下游标以使查询一次执行一行,这样我就可以识别问题数据行:

SET ARITHABORT OFF
SET ARITHIGNORE ON
SET ANSI_WARNINGS OFF

DECLARE @msg VARCHAR(4096)

BEGIN TRY

    DECLARE @itemid AS NVARCHAR(255);

DECLARE C CURSOR FAST_FORWARD FOR
    SELECT ItemID AS itemid
    FROM dbo.qryOtherFieldDataVerifySource;

OPEN C;

FETCH NEXT FROM C INTO @itemid;

WHILE @@fetch_status = 0
BEGIN

    SELECT  dbo.qryOtherFieldDataVerifySource.ItemID, dbo.qryOtherFieldDataVerifySource.EDGRDataID, dbo.qryOtherFieldDataVerifySource.LineItemID, 
            dbo.qryOtherFieldDataVerifySource.ZEGCodeID, dbo.qryOtherFieldDataVerifySource.DataValue, dbo.tblBC.AcceptableValues, 
            dbo.qryOtherFieldDataVerifySource.DataUnitID, dbo.qryOtherFieldDataVerifySource.DataDate, dbo.tblBC.DataTypeID, 
            CASE WHEN DataTypeID = '{5951994B-BF47-4117-805D-B8F85FAB76A8}' AND ISNUMERIC(DataValue) = 1 THEN (CASE WHEN CAST(DataValue AS Float(8)) 
            >= 0 THEN 1 ELSE 0 END) ELSE 0 END AS ValidPositiveNumericValue, 
            CASE DataTypeID WHEN '{A6317BA5-F8FB-4866-A26B-24594650C2DC}' THEN (CASE UPPER(DataValue) 
            WHEN 'TRUE' THEN 1 WHEN 'FALSE' THEN 1 WHEN 'YES' THEN 1 WHEN 'NO' THEN 1 WHEN 'Y' THEN 1 WHEN 'N' THEN 1 WHEN '0' THEN 1 WHEN '1' THEN 1 ELSE
            0 END) WHEN '{5951994B-BF47-4117-805D-B8F85FAB76A8}' THEN ISNUMERIC(DataValue) ELSE 1 END AS ValidDataType, dbo.tblZEGCode.ZEGCode, 
            dbo.qryOtherFieldDataFieldName.FieldName
     FROM   dbo.qryOtherFieldDataVerifySource LEFT OUTER JOIN
            dbo.qryOtherFieldDataFieldName ON dbo.qryOtherFieldDataVerifySource.ItemID = dbo.qryOtherFieldDataFieldName.ItemID LEFT OUTER JOIN
            dbo.tblBC RIGHT OUTER JOIN
            dbo.tblZEGCode ON dbo.tblBC.BCID = dbo.tblZEGCode.BCID ON dbo.qryOtherFieldDataVerifySource.ZEGCodeID = dbo.tblZEGCode.ZEGCodeID
     WHERE dbo.qryOtherFieldDataVerifySource.ItemID = '' + @itemid + ''

    FETCH NEXT FROM C INTO @itemid;
END

CLOSE C;

DEALLOCATE C;

END TRY 
BEGIN CATCH
SET @msg = 'Failure occurred attempting to execute qryOtherFieldDataVerify.';
EXEC ApplicationManagement.dbo.spLogProcedureCall 
    @ObjectID       = @@PROCID,
    @AdditionalInfo = @msg;
RAISERROR(@msg, 0, 1);
END CATCH   

DECLARE @returnCode int
SET @returnCode = CASE WHEN @msg IS NOT NULL THEN 1 ELSE 0 END
SELECT @returnCode AS ErrCode;

答案 2 :(得分:0)

试试这个 -

SELECT
      s.ItemID
    , s.EDGRDataID
    , s.LineItemID
    , s.ZEGCodeID
    , s.DataValue
    , t.AcceptableValues
    , s.DataUnitID
    , s.DataDate
    , t.DataTypeID
    , ValidPositiveNumericValue =
        CASE WHEN DataTypeID = '{5951994B-BF47-4117-805D-B8F85FAB76A8}' AND ISNUMERIC(DataValue) = 1 
            THEN CASE WHEN CAST(DataValue AS FLOAT(8)) >= 0 THEN 1 ELSE 0 END
            ELSE 0
        END
    , ValidDataType =
       CASE 
        WHEN DataTypeID = '{A6317BA5-F8FB-4866-A26B-24594650C2DC}'
            THEN CASE WHEN UPPER(DataValue) IN ('TRUE', 'FALSE', 'YES', 'NO', 'Y', 'N', '0', '1') THEN 1 ELSE 0 END 
        WHEN DataTypeID = '{5951994B-BF47-4117-805D-B8F85FAB76A8}' 
            THEN ISNUMERIC(DataValue)
         ELSE 1
       END
    , c.ZEGCode
    , f.FieldName
FROM dbo.qryOtherFieldDataVerifySource s
LEFT JOIN dbo.qryOtherFieldDataFieldName f ON s.ItemID = f.ItemID
RIGHT JOIN dbo.tblZEGCode c ON s.ZEGCodeID = c.ZEGCodeID
LEFT JOIN dbo.tblBC t ON t.BCID = c.BCID