存储过程运行正常,但突然停止某些值

时间:2019-01-09 16:10:48

标签: sql sql-server

因此,我一直在为正在构建的SSRS报告处理许多存储过程,并且出现了一个奇怪的错误,需要一双新鲜的眼睛才能看到我可能会丢失的内容。

我的过程非常简单-SELECT表中的各个列,JOININSERT表中,#temp的所有列表格以显示为我的报告中的明细行。

我的完整过程如下所示:

SELECT

正如我所说,这段代码一直存在一个奇怪的问题。在过去的两个星期中,所有测试用例都运行良好。我正在使用USE [DB] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[rpt_select_ACHW_Ob] @PR_ID INT AS BEGIN SET NOCOUNT ON; CREATE TABLE #temp (BuildingNum INT, MTHD VARCHAR(50), ObDescript NVARCHAR(50), SizeRemarks VARCHAR(50), ObLength NUMERIC, ObWidth NUMERIC, ObArea NUMERIC, Stories NUMERIC, Grade VARCHAR(50), YearBuilt SMALLINT, Condition VARCHAR(50), Phys NUMERIC, FC VARCHAR(50), PercentDone NUMERIC, TaxValue NUMERIC) DECLARE @RowCounter INT, @h INT SET @RowCounter = 11 INSERT INTO #temp(BuildingNum, MTHD, ObDescript, SizeRemarks, ObLength, ObWidth, ObArea, Stories, Grade, YearBuilt, Condition, Phys, FC, PercentDone, TaxValue) SELECT ob.Ob_LineNumber AS BuildingNum, CASE WHEN ob.SP IS NOT NULL THEN 'S' ELSE 'P' END AS MTHD, som.Id AS ObDescript, CASE WHEN ob.SF IS NULL THEN ob.CN ELSE CAST((ob.SF + '/' + ob.CN) AS VARCHAR) END AS SizeRemarks, CASE WHEN ob.ob_Length IS NULL THEN 0 ELSE ob.Ob_Length END AS ObLength, CASE WHEN ob.ob_Width IS NULL THEN 0 ELSE ob.Ob_Width END AS ObWidth, CASE WHEN ob.ob_Length IS NULL WHEN ob.ob_Width IS NULL THEN 0 THEN 0 ELSE (ob.Ob_Length * ob.Ob_Width) END AS ObArea, ob.Ob_NStories AS OBStories, sovg.Grade AS ObGrade, ob.Ob_YearBuilt As ObYearBuilt, ob.Ob_ConditionCode AS ObConditionCode, ob.DR AS phys, ob.FC AS FC, ob.Ob_PercentComplete AS ObPercentComplete, ob.Ob_ValueTax AS TaxValue FROM t_Ob ob WITH (NOLOCK) LEFT JOIN t_ObToPR otpr WITH (NOLOCK) ON ob.Ob_ID=otpr.Ob_ID LEFT JOIN t_PR pr WITH (NOLOCK) ON otpr.PR_ID=pr.PR_ID LEFT JOIN t_S_Grade sovg WITH (NOLOCK) ON ob.S_Grade_ID=sovg.S_Grade_ID LEFT JOIN t_SObD sod WITH (NOLOCK) ON ob.SObD_ID=sod.SObD_ID LEFT JOIN t_SObM som WITH (NOLOCK) ON sod.SObM_ID=som.SObM_ID WHERE pr.PR_Id = @PR_ID SET @h = (SELECT COUNT(*) FROM #temp) WHILE @h < @RowCounter OR @h % @RowCounter > 0 BEGIN INSERT INTO #temp (BuildingNum) VALUES (NULL) SET @h = @h + 1 END SELECT * FROM #temp ORDER BY CASE WHEN BuildingNum IS NULL THEN 1 ELSE 0 END, BuildingNum END 根据参数EXEC选择记录,并且工作正常。昨天,在未触及任何代码之后,我开始仅针对某些@PR_ID值生成错误代码:

  

消息8114,级别16,状态5,过程rpt_select_ACHW_Ob,第28行[批处理开始第2行]
  将数据类型varchar转换为数字时出错。

第28行将引导您转到PR_ID,我已对其进行了10次检查。 FC VARCHAR(50)表中声明的所有数据类型都与所选值完全匹配。是否有人对为什么它停止工作有任何想法?

Here's a dbFiddle link with some sample data

当前正在使用SQL Server 2012。

2 个答案:

答案 0 :(得分:4)

这个评论太长了。

发生了两件事之一。不太可能是您的原始查询编写正确,并且有人更改了基础表(将整数列更改为字符串列),然后用非数字数据填充了字符串列。

更可能的情况是您的原始查询具有隐式转换。这只是一个等待发生的问题-现在您知道为什么了。您有一条来自SQL Server的错误消息,它没有指定发生问题的表,行或列。 Arrggg!

我的建议是遍历查询并检查每个表达式和比较,以确保类型兼容(数字/数字,字符串/字符串,日期时间/日期时间足够)。如果不是,请添加显式转换。您可以使用try_convert()try_cast()添加转换,这至少会避免错误(以产生NULL为代价)。

我希望SQL Server具有“无隐式转换”模式,在此模式下,它会警告您查询正在使用此类转换。 las,不。因此,养成编写查询的习惯,以便所有转换都是明确的。

编辑:

例如(基于注释),该表达式:

CAST((ob.SF + '/' + ob.CN) AS VARCHAR

应为:

CAST( (ob.SF as VARCHAR(255)) + '/' + ob.CN) AS VARCHAR(255))

请注意,您应该在SQL Server的所有CHAR() / VARCHAR()引用中都包含长度。

答案 1 :(得分:1)

根据您对@Gordon的回答的评论:如果准确,则将Gordon的回答标记为您的解决方案。

这将失败:

Declare @SF Int = 12
Declare @CN VarChar(10) = '2'

Select CAST((@SF + '/' + @CN) AS VARCHAR)

除非您添加演员表:

Select CAST((Cast(@SF As VarChar(10)) + '/' + @CN) AS VARCHAR)

结果

12/2