2012-05-30 80 views
4

我试图创建一组数据,我将写出一个文件,它本质上是一个由多个不同表中的各个字段组成的报表,某些列需要要对它们进行一些处理,可以选择一些。SQL - 使用动态函数计算列

不同的用户可能会希望对某些列执行不同的处理,未来我可能需要为计算列添加其他函数。

我在考虑最干净/最灵活的方法来存储和使用我可能需要这些计算列的所有不同功能,我有两个想法在我的脑海中,但我希望有可能是我失踪的更明显的解决方案。

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

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的一个巨大的风扇,但在这种情况下,我想可能是得到结果的最佳方式,我之后?

任何答复赞赏, 谢谢, 克里斯

回答

1

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

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

declare @proc sysname = 'ShortName' 

exec @proc 'David' 

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

+0

感谢这个例子,我将创建一些测试表/函数来实验和检查我的结果。 谢谢! (如果我有代表,会赞成)。 – Chris

1

最后,你应该走与哪一个更快,所以你应该尝试两种方式(和任何其他方式有人可能会提出),并决定之后。

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

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

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

+0

幸好我可能会在这两种情况下创建函数,并将查找表添加为它们上方的图层,因此快速测试第一个替代方法应该不会太麻烦。 谢谢(还没有足够的代表upvote呢)。 – Chris

1

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

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

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

+0

感谢您的回复,您对我正在努力实现的目标,灵活性和可读性感到很满意(所以下一个人在他们想要改变的事情时不必做同样的事情)。 我会看看我如何继续! (再次,会upvote,但仍然获得代表)。 – Chris