【问题标题】:How can I grab results from a query even if an SQL exception occurs during command.executeReader()?即使在 command.executeReader() 期间发生 SQL 异常,如何从查询中获取结果?
【发布时间】:2012-12-27 00:06:35
【问题描述】:

我有这段代码有时有效,有时无效。正在执行的查询不是我自己编写的,但我被告知我所要做的就是对数据库运行它以获得我需要的结果。这是我的代码:

try {
  using (SqlDataReader dr = cmd.ExecuteReader()) {
    while (dr.Read()) {
      try {
        list.Add(dr.GetString(3) + " " + dr.GetInt32(4).ToString() + " " + dr.GetString(5) + " " + dr.GetDecimal(8).ToString());
      } catch (Exception e) {
        list.Add("fail");
      }
    }
  }
} catch (SqlException sqlException) {
  Debug.WriteLine(sqlException.Message);
}

我有时收到的错误是我无法删除表,因为我没有权限或表不存在。其他时候查询执行没有任何问题,我可以检索我的结果并将其存储在一个列表中。

当我在 SQL Server 2008 中运行查询时,有时我确实会遇到错误,但结果仍然会显示,并且符合我的预期。所以我的问题是:无论何时感觉似乎都会出现错误,我如何才能获取这些结果?

这里有一小部分给我带来麻烦的查询:

IF  EXISTS (SELECT * from tempdb..sysobjects where name like '#TABLE%')  
DROP #TABLE

我正在运行的查询中有许多这样的 if 语句,并且无法预测哪一个会导致错误。所以我现在所做的是将 DROP #TABLE 包围在一个 try-catch 块中,这样至少我仍然可以在我的 silverlight 程序中检索结果。我会和我的上级联系,问他为什么查询会自发返回这些错误..

【问题讨论】:

  • 您应该真正与您的 DBA 一起找出为什么有时会发生此错误。没有充分理由而忽略错误是个坏主意。
  • 似乎是只读查询中的删除表错误?遵循 cdhowie 的建议并检查您的查询是否存在 sql 注入漏洞
  • 这似乎是一个 sql 注入,顺便说一句,你为什么要删除该表,它是一个临时表
  • 您正在搜索“#TABLE”开头的表。换句话说,如果存在名为“#TABLE_test”的表,这将返回 true。但随后您尝试删除名为“#TABLE”的表。 “如果#TABLE_test 存在,则删除#TABLE”。您知道为什么有时会出错吗?
  • @Cyborgx37,这对我来说有点道理。令我困惑的是,查询有时如何完美运行而没有问题,有时会导致错误?换句话说:我理解你的评论,但怎么会有一个表 #TABLE 有时存在而有时不存在

标签: c# silverlight


【解决方案1】:

编辑

没关系,我看到了问题。我忘记了临时表名称附加了额外的字符以防止不同进程之间的命名冲突(例如#TABLE___...___0000000064E2)。

我的猜测是存储过程在某些情况下会创建一个名为“#TABLE”的临时表,而您发布的那段 SQL 代码旨在执行清理。单独运行时,这可能工作正常。

当存储过程由多个客户端同时运行时,或者如果先前的查询之一以某种方式未能执行清理(可能是由于中途出现错误),问题可能开始出现。在这种情况下,会产生误报(存储过程认为清理是必要的,但它实际上看到的是另一个进程创建的临时表)。然后您会收到错误,因为没有与当前进程关联的#TABLE。

无论如何,将语句包装在 try-catch 中似乎是一种不错的方法。更好的方法是对代码进行彻底检查,可能设置某种标志以帮助指示清理是必要的,或者使用公用表和某种事务键(删除与当前事务关联的所有记录,而不是删除表)。

您可能还想考虑使用表变量而不是临时表。

见:
http://social.msdn.microsoft.com/Forums/en-US/sqltools/thread/02337dd5-5cfd-40d8-b529-12dc557d6a7e/

或者,您也可以考虑完全跳过 DROP 语句:
Temporary Table Scope?


为了回答您的原始问题,我不知道有任何方法可以在 SQL 查询引发异常后检索结果,而不是通过 .NET 程序集。 SQL Server Management Studio 使用了一些重型、定制的 API,这些 API 可能不值得您学习和使用。


忽略以下内容
(留作参考)

如果可以,请尝试将 SQL 查询更改为

IF  EXISTS (SELECT * from tempdb..sysobjects where name = '#TABLE')
DROP #TABLE

(将like '#TABLE%'更改为= '#TABLE'

like 语句没有任何意义...是否有其他表以“#TABLE”开头都没关系...您只想知道是否有一个名为确切“#TABLE”的表。

我的猜测是,这是其中一种逻辑被改变的情况,但只是中途改变,可能是两个不同的人。

【讨论】:

  • 我今天早些时候确实尝试过,它导致了以下错误:数据库中已经有一个名为“#TABLE”的对象。
  • 我不知道这是否被认为是好的做法,但是在 SQL 查询中使用 try-catch 块之后,我现在可以 100% 地从我的 silverlight 程序中检索我的查询结果。
  • 这会稍微影响你的表现。此外,如果您有意外的异常,try/catch 会简单地将其丢弃。但是,这似乎是一个罕见的问题,我个人认为这是可以接受的。
  • @rage - 查看更新的答案。您还有其他几个可能更容易的选择。尤其是最后一个(根本不删除临时表)。
  • 我尝试不删除表,但我继续收到错误。难道我必须尝试删除表以防其他查询将它们抛在后面?目前我对数据库和 SQL 的了解还很浅,但我很确定这就是为什么删除临时表的 if 语句位于我正在处理的可怕查询的开头的原因。
猜你喜欢
  • 1970-01-01
  • 2020-09-23
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
  • 2015-01-08
  • 1970-01-01
  • 1970-01-01
  • 2018-10-22
相关资源
最近更新 更多