使用带CONVERT或CAST的WHERE子句的T-SQL查询

时间:2018-02-14 15:12:14

标签: sql sql-server tsql

我在使用代码生成的特定T-SQL查询时遇到了问题。

下面是代码,第一个DECLARE块是从代码发送的,因此这些值会发生变化。

XML业务与将CSV NVARCHAR转换为临时表格有关。

-- DECLARE BLOCK IS SENT BY CODE FROM DIALOG BOX
DECLARE @IdString NVARCHAR(MAX) ='F6LC1'
DECLARE @pm_StartDate DATETIME ='20180201'
-- END DECLARE BLOCK

DECLARE @listOfIds table(entityId nvarchar(50));

DECLARE @x XML 

SELECT @x = CAST('<A>'+ REPLACE(REPLACE(@IdString,' ',''),',','</A><A>')+ '</A>' AS XML)

INSERT INTO @listOfIds
SELECT t.value('.', 'NVARCHAR(50)') AS inVal
FROM @x.nodes('/A') AS x(t)

DECLARE @pm_StartDateTrim NVARCHAR(MAX) = LEFT(CONVERT(NVARCHAR(MAX),@pm_StartDate,112),6)
DECLARE @intStartDate INT = CAST(@pm_StartDateTrim AS INT)

SELECT @pm_StartDate
SELECT @pm_StartDateTrim
SELECT @intStartDate

SELECT   gl.[ACCTNUM]
        ,acc.[ACCTNAME]
        ,gl.[ENTITYID]
        ,CONVERT(INT,gl.[PERIOD]) AS periodConverted
        ,gl.[ACTIVITY]
        ,bldg.[BLDGNAME]
        ,bldg.[BLDGGLA]
        ,gl.[BALFOR]
FROM [dbo].[GLSUM] AS gl
        INNER JOIN [dbo].[BLDG] AS bldg ON gl.[ENTITYID] = bldg.[BLDGID]
        INNER JOIN [dbo].[GACC] AS acc ON gl.[ACCTNUM] = acc.[ACCTNUM]
WHERE gl.ENTITYID IN (SELECT entityId FROM @listOfIds)
        AND gl.BASIS = 'A'
        AND gl.ACTIVITY != 0
        AND gl.PERIOD NOT LIKE '%[^0-9]%'
        AND CONVERT(INT,gl.[PERIOD]) >= @intStartDate
ORDER BY gl.PERIOD ASC

我正在尝试仅包含PERIOD大于或等于所提供的StartDate的记录。

PERIOD数据库中的数据仅为YYYYMM,与201502类似。

StartDate提供的数据为DATETIME,因此我转换为YYYYMM进行比较。

我正在尝试同时使用INT,因此我可以使用<>=等进行比较。

所以,如果我留在第2行到最后一行AND CONVERT(INT,gl.[PERIOD]) >= @intStartDate,那么我得到Conversion failed when converting the varchar value 'R2W274' to data type int.

问题在于我的数据中没有这样的值。

当我注释掉那一行时,我得到数据并且R2W274在任何记录的任何字段中都找不到。{/ p>

我认为R2W274值实际上在gl.ENTITYID字段中,但在我的任何记录中都没有,通常只在数据库中。

所以,我不确定为什么这个查询甚至试图首先转换gl.ENTITYID

任何帮助?

更新

我在上面的WHERE子句中添加了推荐的附加内容。我仍然得到同样的错误。

1 个答案:

答案 0 :(得分:3)

请确保没有返回的数据:

select * from [dbo].[GLSUM] where [Period] = 'R2W274'

添加这样的try / catch块会有所帮助:

BEGIN TRY  
    -- Generate divide-by-zero error.  
    your select query comes here.  
END TRY  
BEGIN CATCH  
    -- Execute error retrieval routine.  
    print 'error';
END CATCH;

尝试/捕获块引用:https://docs.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql

我要做的是在where子句中删除这些数据:

WHERE gl.ENTITYID IN (SELECT entityId FROM @listOfIds)
        AND gl.BASIS = 'A'
        AND gl.ACTIVITY != 0
        AND gl.[PERIOD] not like '%[^0-9]%'
        AND CONVERT(INT,gl.[PERIOD]) >= @intStartDate

编辑:我原本期待where子句会修改它,感到惊讶的是它无法正常工作。请确保在包含转换的过滤器之前添加了过滤器。也许使用像这样的临时表会更安全:

select * 
into #temp_glsum
from [dbo].[GLSUM] gl
WHERE gl.[PERIOD] not like '%[^0-9]%'

并在主查询中使用#temp_glsum而不是[dbo].[GLSUM]