SQL - 使用动态函数计算列

时间:2012-05-30 10:31:00

标签: sql sql-server sql-server-2005

我正在尝试创建一组我要写入文件的数据,它本质上是一个由来自多个不同表格,某些列的各个字段组成的报告需要对它们进行一些处理,有些可以选择。

不同的用户可能希望对某些列执行不同的处理,并且将来,我可能需要为计算列添加其他功能。

我考虑使用最干净/最灵活的方法来存储和使用这些计算列可能需要的所有不同功能,我脑子里有两个想法,但我和#39;我希望可能有一个更明显的解决方案,我错过了。

对于一个简单的,有点奇怪的例子,一个Staff表:

Employee |    DOB           |   VacationDays
Frank    |    01/01/1970    |   25
Mike     |    03/03/1975    |   24
Dave     |    05/02/1980    |   30

我想我最终会得到像

这样的查询
SELECT NameFunction(Employee, optionID),
       DOBFunction(DOB, optionID),
       VacationFunction(VacationDays, optionID),
from Employee

使用用户定义的函数,其中optionID将在函数内的case语句中用于决定要执行的处理。

或者我想使用其他功能的查找表来定制返回数据的方式:

ID  |    Name                  |   Description
1   |    ShortName             |   Obtains 3 letter abbreviation of employee name
2   |    LongDOB               |   Returns DOB in format ~ 1st January 1970
3   |    TimeStampDOB          |   Returns Timestamp for DOB
4   |    VacationSeconds       |   Returns Seconds of vaction time
5   |    VacationBusinessHours |   Returns number of business hours of vacation

哪个看起来更整洁,但我不确定我是如何制定查询的,大概是使用动态SQL?有没有合理的选择?

这些功能将在几千行上使用。

我发现的最接近的答案是在这个帖子中: Call dynamic function name in SQL

我不是动态SQL的忠实粉丝,虽然在这种情况下我认为这可能是获得结果的最好方法吗?

任何回复都表示赞赏, 谢谢, 克里斯

3 个答案:

答案 0 :(得分:1)

我会选择第二个解决方案。您甚至可以在查找表中使用真实存储的proc名称。

create proc ShortName (
    @param varchar(50)
)as
begin
    select 'ShortName: ' + @param
end
go

declare @proc sysname = 'ShortName'

exec @proc 'David'

正如您在上面的示例中所看到的,exec的第一个参数(即过程名称)可以是一个参数。这说明了关于动态sql的所有常见警告......

答案 1 :(得分:1)

最后,你应该选择哪个更快,所以你应该尝试两种方式(以及任何其他人可能提出的方式)并在此之后做出决定。

我更喜欢第一个选项,只要你的函数没有对表的额外选择。如果它们不会在不同的报告中重复使用,您可能甚至不需要用户定义的函数。

我更喜欢使用Dynamic SQL ony来提高查询的性能,例如添加动态排序或添加/删除复杂的WHERE条件。

但这些都是主观意见,最好的是尝试,比较和决定。

答案 2 :(得分:1)

实际上,这不是什么更快的问题。这是一个使代码更清晰的问题,特别是对于添加新功能(新列,新列格式,重新排序)。

不要将您的第二种方法视为“使用动态SQL”,因为这往往会产生负面含义。相反,将其视为数据驱动的方法。您希望构建一个表,描述用户可以获取的列以及格式。这很棒!然后,用户可以提供列列表,您将拥有一个神奇的存储过程,将来自用户的信息与元数据表中的信息相结合,并生成所需的结果。

我是数据驱动方法的忠实粉丝,动态SQL是迄今为止我发现的最好的SQL工具。