转换失败将VARCHAR转换为INT

时间:2015-02-27 00:57:51

标签: sql-server

  

转换varchar值时转换失败' 1   12:57:39 3168.68 485 H5555'到数据类型int。这发生在SQL中   Server 2012提供以下代码。

SELECT 
MEMBER_ID
,STUFF
(
    (
        SELECT ',[' + C1 + '-' + C2 + ']' AS [text()]
        FROM 
        (
            SELECT DISTINCT A.MEMBER_ID
            ,A.CLAIM_ID AS C1
            ,A.PLAN_ID AS PC1
            ,B.CLAIM_ID C2
            ,B.PLAN_ID AS PC2
            ,A.AMOUNT AS AMT1
            ,B.AMOUNT AS AMT2
            FROM TestSQL A 
            JOIN TestSQL B ON A.MEMBER_ID = B.MEMBER_ID 
            WHERE A.CLAIM_ID <> '1 12:57:39 3168.68 485 H5555' 
            AND YEAR(A.DATE) > 2000 
            AND B.DATE > A.DATE 
            AND B.PLAN_ID <> A.PLAN_ID 
            AND (CAST(B.CLAIM_ID AS INT)-CAST(A.CLAIM_ID AS INT))=2
        ) Y             
        WHERE MEMBER_ID = X.MEMBER_ID
        FOR XML PATH('')
    ),1,1,''
) AS CLAIM_ID_LIST
FROM 
(
    SELECT DISTINCT A.MEMBER_ID
    ,A.CLAIM_ID AS C1
    ,A.PLAN_ID AS PC1
    ,B.CLAIM_ID C2
    ,B.PLAN_ID AS PC2
    ,A.AMOUNT AS AMT1
    ,B.AMOUNT AS AMT2
    FROM TestSQL A 
    JOIN TestSQL B ON A.MEMBER_ID = B.MEMBER_ID
    WHERE YEAR(A.DATE) > 2000  
    AND B.DATE > A.DATE 
    AND B.PLAN_ID <> A.PLAN_ID 
    AND (CAST(B.CLAIM_ID AS INT)-CAST(A.CLAIM_ID AS INT))=2 
    AND A.CLAIM_ID IN (SELECT CLAIM_ID FROM TestSQL WHERE MEMBER_ID<>'')
) X

我试图过滤掉1 12:57:39 3168.68 485 H5555并仍然给我这个错误。这是CLAIM_ID

我怀疑它是

WHERE MEMBER_ID = X.MEMBER_ID
FOR XML PATH正上方的

子句,但我不知道为什么。第二个子查询有效。我很欣赏这方面的任何见解。

2 个答案:

答案 0 :(得分:2)

这是错误的来源:

(CAST(B.CLAIM_ID AS INT)-CAST(A.CLAIM_ID AS INT)) = 2

1 12:57:39 3168.68 485 H5555投射到INT会产生错误。虽然你说你已经在WHERE A.CLAIM_ID <> '1 12:57:39 3168.68 485 H5555'过滤了它。优化器可以选择首先评估CAST,从而导致错误。

您可能希望先在CTE中对其进行过滤。然后使用CTE代替:

;WITH CTE AS(
    SELECT
        *
    FROM TestSQL
    WHERE
        CLAIM_ID <> '1 12:57:39 3168.68 485 H5555'
)
SELECT 
MEMBER_ID
,STUFF
(
    (
        SELECT ',[' + C1 + '-' + C2 + ']' AS [text()]
        FROM 
        (
            SELECT DISTINCT A.MEMBER_ID
            ,A.CLAIM_ID AS C1
            ,A.PLAN_ID AS PC1
            ,B.CLAIM_ID C2
            ,B.PLAN_ID AS PC2
            ,A.AMOUNT AS AMT1
            ,B.AMOUNT AS AMT2
            FROM CTE A 
            JOIN CTE B ON A.MEMBER_ID = B.MEMBER_ID 
            WHERE A.CLAIM_ID <> '1 12:57:39 3168.68 485 H5555' 
            AND YEAR(A.DATE) > 2000 
            AND B.DATE > A.DATE 
            AND B.PLAN_ID <> A.PLAN_ID 
            AND (CAST(B.CLAIM_ID AS INT)-CAST(A.CLAIM_ID AS INT))=2
        ) Y             
        WHERE MEMBER_ID = X.MEMBER_ID
        FOR XML PATH('')
    ),1,1,''
) AS CLAIM_ID_LIST
FROM 
(
    SELECT DISTINCT A.MEMBER_ID
    ,A.CLAIM_ID AS C1
    ,A.PLAN_ID AS PC1
    ,B.CLAIM_ID C2
    ,B.PLAN_ID AS PC2
    ,A.AMOUNT AS AMT1
    ,B.AMOUNT AS AMT2
    FROM CTE A 
    JOIN CTE B ON A.MEMBER_ID = B.MEMBER_ID
    WHERE YEAR(A.DATE) > 2000  
    AND B.DATE > A.DATE 
    AND B.PLAN_ID <> A.PLAN_ID 
    AND (CAST(B.CLAIM_ID AS INT)-CAST(A.CLAIM_ID AS INT))=2 
    AND A.CLAIM_ID IN (SELECT CLAIM_ID FROM CTE WHERE MEMBER_ID<>'')
) X

要确保只返回数字CLAIM_ID,您可以在CTE内使用此内容:

SELECT *
FROM TestSQL
WHERE CLAIM_ID NOT LIKE '%[^0-9]%'

答案 1 :(得分:1)

试试这个:

--use cte to create a copy of the table minus the dodgy row
--or simply set that claim to null and cast remaining values
--use this anywhere we need to cast claim_id to int
;with cte as 
(
    select *
    , case 
        when CLAIM_ID = '1 12:57:39 3168.68 485 H5555' 
            then null 
        else 
            cast(CLAIM_ID as int) 
    end CLAIM_ID_INT
    from TestSQL
)
SELECT 
MEMBER_ID
,STUFF
(
    (
        SELECT ',[' + C1 + '-' + C2 + ']' AS [text()]
        FROM 
        (
            SELECT DISTINCT A.MEMBER_ID
            ,A.CLAIM_ID AS C1
            ,A.PLAN_ID AS PC1
            ,B.CLAIM_ID C2
            ,B.PLAN_ID AS PC2
            ,A.AMOUNT AS AMT1
            ,B.AMOUNT AS AMT2
            FROM cte A 
            JOIN cte B ON A.MEMBER_ID = B.MEMBER_ID 
            WHERE A.CLAIM_ID <> '1 12:57:39 3168.68 485 H5555' 
            AND YEAR(A.DATE) > 2000 
            AND B.DATE > A.DATE 
            AND B.PLAN_ID <> A.PLAN_ID 
            AND (B.CLAIM_ID_INT - A.CLAIM_ID_INT)=2
        ) Y             
        WHERE Y.MEMBER_ID = X.MEMBER_ID
        FOR XML PATH('')
    ),1,1,''
) AS CLAIM_ID_LIST
FROM 
(
    SELECT DISTINCT A.MEMBER_ID
    ,A.CLAIM_ID AS C1
    ,A.PLAN_ID AS PC1
    ,B.CLAIM_ID C2
    ,B.PLAN_ID AS PC2
    ,A.AMOUNT AS AMT1
    ,B.AMOUNT AS AMT2
    FROM cte A 
    JOIN cte B ON A.MEMBER_ID = B.MEMBER_ID
    WHERE YEAR(A.DATE) > 2000  
    AND B.DATE > A.DATE 
    AND B.PLAN_ID <> A.PLAN_ID 
    AND B.CLAIM_ID_INT-A.CLAIM_ID_INT = 2 
    AND A.CLAIM_ID IN (SELECT CLAIM_ID FROM cte WHERE MEMBER_ID<>'')
) X