0

在我们的应用程序中,我们将允许用户使用其他数据库列的数字输入算术表达式 (+ - * /),然后应用程序对其进行解析并作为计算列写入数据库。

但是,允许用户创建可能导致表异常的表达式会出现一些问题select *,例如被零除、算术溢出以及我尚未遇到的其他可能的问题(尽管我认为这就是全部他们)。

让数据库抛出异常select *绝对是毁灭性的。如果他们有容易出错的数据,我宁愿尝试将他们的表达式重写为优雅地失败的东西。

对于除以零,解决方案非常简单:

add [Col] as case {divisor} when 0 then N'DIVIDE-BY-ZERO' else {expression} end

我的问题是我该怎么做算术溢出?在列中显示双层或明显错误的数据不是问题,但抛出异常会。

4

4 回答 4

1

由于您拥有解析技术,因此您可以重写表达式以使用一堆 CASE 语句捕获所有潜在问题 - 除以零、溢出、向上转换为不同类型等。

但我不会那样做,因为我不认为将这些作为模式的一部分放入数据库是一个好主意,除非这个工具是一个代码生成工具,并且用户负责审查和测试边缘的表达式就像它们包含在原始数据库设计中一样。

如果您已经在解析表达式,我也会在客户端编译它,并逐行处理错误。

使用TRY/CATCH捕获异常是一种全有或全无的情况,而不是逐行进行。

于 2009-12-21T19:05:06.717 回答
1

我讨厌看到你接受一个不能真正让你更接近目标的答案。

作为一个可能对您有所帮助的单独答案,您可以将计算列称为(确定性)标量 UDF。

例如,请参见此处

因此,如果您要创建计算列,请将列传递给生成的 UDF(或多个 UDF)并在那里完成工作。在标量 UDF 中,您可以使用大量代码来发现问题,但您仍然无法使用TRY/CATCH. 您可以在标量 UDF 中执行的操作是捕获案例并返回适当的答案(可能会冒泡 NULL)。

但是标量 UDF 的性能会很差(不确定非持久化内联计算列与 UDF 的对比,我们主要使用持久化),因此您可能需要认真考虑使列持久化,这将使用数据库中的空间和使插入和更新慢一点。这是一个很大的权衡。

于 2009-12-22T18:05:28.887 回答
0

如何捕获异常?似乎很难检测算术溢出的所有可能原因,更不用说一般的异常了。

在异常情况下,您可以返回与原始用户定义的结果集兼容的废话结果集:

begin try
    select exp(999)
end try
begin catch
    select 1
end catch 
于 2009-12-21T18:50:56.383 回答
0

如果性能很重要,请在插入、更新或删除数据时使用触发器或索引视图来存储计算。

如果性能不重要,请使用标量值函数。

于 2009-12-22T21:13:36.700 回答