SQL 查询字符串在 SQL Server Management Studio 中有效,但在 VB.net 和 SQLCommand.ExecuteReader 中无效

SQL Query String Works in SQL Server Management Studio, But Not in VB.net with SQLCommand.ExecuteReader

我有一个使用 VB.net 代码的 ASPX 页面,它被设置为 运行 一系列 SQL 查询并用结果填充 SQLDataReader .每个 SQL 查询都是从 SQL 数据库中 table 的特定字段中提取的。这段代码完美地适用于我 运行 通过它的每个查询,除了一个。

涉及的VB代码如下

Dim SQL_Template_Query As String
Dim cmd3 As SqlCommand = New SqlCommand
Dim r3 As SqlDataReader    

cmd3 = New SqlCommand(SQL_Template_Query)
cmd3.CommandTimeout = 1200 ' Extended to 1200 sec = 20 min
cmd3.CommandType = CommandType.Text
cmd3.Connection = Global_Objects.SQLLocalDB_Connection
Try
    r3 = Nothing
    r3 = cmd3.ExecuteReader() ' THIS LINE IS WHERE THE ERROR OCCURS
Catch
    Session("Main_Error_Code") = 1
    Session("Main_Error_Message") = "The SQL statement for the following address is invalid. Please examine the GCDB_Excel_Reports_Templates record, and correct." &
                    Chr(13) & "ID " & ti.ID & ", " & ti.Sheet_Name & ", " & ti.Cell_Address

    ' Write to error log
    cxlErrorsSheetLog.Cell("A" & cxlErrorsCurRow).Value = Session("Main_Error_Message")
    cxlErrors.SaveAs(cxlErrorsPath)
    cxlErrors = Nothing
    cxlDoc = Nothing
    Return
End Try

如您所见,我已准备好代码来捕获错误,因此我确切地知道错误发生的位置,但我不确定原因。

时出现错误

SQL_Template_Query = "DECLARE @Start_Year int; SET @Start_Year=2018; DECLARE @Reporting_Year int; SET @Reporting_Year=2021; declare @First_Year int; set @First_Year = ( case when (@Reporting_Year-@Start_Year+1)<=5 then @Start_Year else @Reporting_Year - 4 end ); drop table if exists #Reporting_Years; create table #Reporting_Years ( Reporting_Year int ); insert into #Reporting_Years select distinct YEAR(Single_Date) from Single_Dates where YEAR(Single_Date) between @Reporting_Year-4 and @Reporting_Year; drop table if exists #Has_ACT; create table #Has_ACT (Building_ID int,Start_Date datetime,End_Date datetime); insert into #Has_ACT select distinct Building_ID,MIN(Start_Date),MAX(End_Date) from Tracking_Periods where Utility_Type_ID between 16 and 19 and YEAR(Start_Date)<=@Reporting_Year and (YEAR(End_Date)>=@First_Year or End_Date is null) group by Building_ID; select i1.Reporting_Year, SUM(case when i2.Asset_Class like 'Office' then GFA else null end) as Office_GFA, SUM(case when i2.Asset_Class like 'Retail' then GFA else null end) as Retail_GFA, SUM(case when i2.Asset_Class like 'Industrial' then GFA else null end) as Industrial_GFA from #Reporting_Years i1 left join ( select z1.Reporting_Year,x.Building_ID,y.Building,y.Asset_Class,x.Start_Year,x.End_Year,y.Most_Recent_GFA_Year, case when z1.Reporting_Year<=y.Most_Recent_GFA_Year then (select GFA from Annual_GFA where Building_ID=x.Building_ID and Reporting_Year=z1.Reporting_Year) else (select GFA from Annual_GFA where Building_ID=x.Building_ID and Reporting_Year=y.Most_Recent_GFA_Year) end as GFA from ( select Building_ID, case when YEAR(Start_Date)<@First_Year then @First_Year else YEAR(Start_Date) end as Start_Year, case when End_Date is null then @Reporting_Year when YEAR(End_Date)>@Reporting_Year then @Reporting_Year else YEAR(End_Date) end as End_Year from #Has_ACT) x left join ( select a.Building_ID,a.Building,a.Asset_Class,MAX(a.Reporting_Year) as Most_Recent_GFA_Year from View_All_Buildings_Annual_GFA a inner join View_All_Buildings b on a.Building_ID=b.Building_ID inner join View_All_Building_Ownership_By_Year c on c.Building_ID=a.Building_ID and c.Reporting_Year=@Reporting_Year inner join Building_Ownership d on a.Building_ID=d.Building_ID left join Override_Building_Count e on a.Building_ID=e.Building_ID and e.Report_ID=5 inner join #Has_ACT f on f.Building_ID=a.Building_ID where b.Asset_Manager like 'Anonymous' and b.Not_On_Program=0 and b.Exclude_From_Reporting=0 and b.Tenant=0 and d.Year_Removed is null and (e.Building_Count<>0 or e.Building_Count is null) group by a.Building_ID,a.Building,a.Asset_Class) y on x.Building_ID=y.Building_ID cross join #Reporting_Years z1 where z1.Reporting_Year between @First_Year and @Reporting_Year and z1.Reporting_Year>=x.Start_Year and z1.Reporting_Year<=x.End_Year and y.Building_ID is not null) i2 on i1.Reporting_Year=i2.Reporting_Year where i1.Reporting_Year between @Start_Year and @Reporting_Year group by i1.Reporting_Year order by i1.Reporting_Year; "

我按原样提供字符串,以防有人想知道 VB.net 是如何解析它的。对开发人员更友好的此查询解析如下所示。

DECLARE @Start_Year int;
SET @Start_Year=2018;
DECLARE @Reporting_Year int;
SET @Reporting_Year=2021;

declare @First_Year int;
set @First_Year =  
(  
case   
when (@Reporting_Year-@Start_Year+1)<=5 then @Start_Year   
else @Reporting_Year - 4 end  
);       

drop table if exists #Reporting_Years;       

create table #Reporting_Years  
(
Reporting_Year int
);   

insert into #Reporting_Years 
select distinct YEAR(Single_Date) 
from Single_Dates where YEAR(Single_Date) 
between @Reporting_Year-4 and @Reporting_Year;   

drop table if exists #Has_ACT;   

create table #Has_ACT (Building_ID int,Start_Date datetime,End_Date datetime);   

insert into #Has_ACT  
select distinct Building_ID,MIN(Start_Date),MAX(End_Date)  from Tracking_Periods  
where Utility_Type_ID between 16 and 19 
and YEAR(Start_Date)<=@Reporting_Year  
and (YEAR(End_Date)>=@First_Year or End_Date is null)  
group by Building_ID;     

select i1.Reporting_Year,  
SUM(case when i2.Asset_Class like 'Office' then GFA else null end) as Office_GFA,  
SUM(case when i2.Asset_Class like 'Retail' then GFA else null end) as Retail_GFA,  
SUM(case when i2.Asset_Class like 'Industrial' then GFA else null end) as Industrial_GFA  
from #Reporting_Years i1  
left join
(
select z1.Reporting_Year,x.Building_ID,y.Building,y.Asset_Class,x.Start_Year,x.End_Year,y.Most_Recent_GFA_Year,  
case  when z1.Reporting_Year<=y.Most_Recent_GFA_Year   
then 
(select GFA from Annual_GFA where Building_ID=x.Building_ID and Reporting_Year=z1.Reporting_Year)  
else 
(select GFA from Annual_GFA where Building_ID=x.Building_ID and Reporting_Year=y.Most_Recent_GFA_Year)
end as GFA  
from   
(  
select Building_ID,  
case  
when YEAR(Start_Date)<@First_Year then @First_Year  
else YEAR(Start_Date) end as Start_Year,  
case  
when End_Date is null then @Reporting_Year  
when YEAR(End_Date)>@Reporting_Year then @Reporting_Year  
else YEAR(End_Date) end as End_Year from #Has_ACT) x  
left join   
(
select a.Building_ID,a.Building,a.Asset_Class,MAX(a.Reporting_Year) as Most_Recent_GFA_Year  
from View_All_Buildings_Annual_GFA a      
inner join View_All_Buildings b on a.Building_ID=b.Building_ID      
inner join View_All_Building_Ownership_By_Year c on c.Building_ID=a.Building_ID and c.Reporting_Year=@Reporting_Year      
inner join Building_Ownership d on a.Building_ID=d.Building_ID      
left join Override_Building_Count e on a.Building_ID=e.Building_ID and e.Report_ID=5      
inner join #Has_ACT f on f.Building_ID=a.Building_ID    
where b.Asset_Manager like 'Anonymous'      
and b.Not_On_Program=0 and b.Exclude_From_Reporting=0 and b.Tenant=0      
and d.Year_Removed is null    
and (e.Building_Count<>0 or e.Building_Count is null)  
group by a.Building_ID,a.Building,a.Asset_Class) y on x.Building_ID=y.Building_ID  
cross join #Reporting_Years z1 where z1.Reporting_Year between @First_Year and @Reporting_Year  
and z1.Reporting_Year>=x.Start_Year and z1.Reporting_Year<=x.End_Year  
and y.Building_ID is not null) i2 on i1.Reporting_Year=i2.Reporting_Year  
where i1.Reporting_Year between @Start_Year and @Reporting_Year  
group by i1.Reporting_Year  
order by i1.Reporting_Year;  

当我在 SQL Server Management Studio 中 运行 这个查询时,一个字符一个字符地查询,它 return 正是我期望的结果。

但是,当VB代码运行s时,它会触发catch代码。阅读了类似问题的帖子后,我尝试修改查询以产生 0 而不是 NULL,但问题仍然存在。此外,其他查询会产生 NULL 值,但可以正常使用 VB 代码。

如有任何建议,我们将不胜感激。我也想知道是否有办法让 SQLDataAdapter 或 SQLCommand 到 return 错误。这将使事情更容易诊断。

更新: 如果我注释掉 Try...Catch...End Try,并允许 Visual Studio 生成错误,我会收到以下信息。

因此,对于使用单个连接的多个 SQL 查询,@AndrewMorton 似乎走在了正确的轨道上。我创建了一个全新的 VB.net 项目,添加了代码以提取导致问题的特定存储 SQL 语句,然后 运行 它。它工作没有问题。知道了,在原始项目中,我将代码替换为 运行 单独连接上的特定 SqlCommand,在每个循环后处理连接实例。

代码现在按预期运行。目前还不清楚为什么这个特定的 SQL 语句会导致问题,而不是其他语句。但是,无论如何,我将重新编写该项目中的所有代码以移除单个连接对象。

@AndrewMorton 的其他评论 https://ubitsoft.com/t-sql-beautilyzer/ 中提供的 link 也很有帮助。实际上,我一直在寻找一种无需底层数据库即可独立检查 SQL 查询的方法。