通过Function在SQL Server中重用查询及其结果

时间:2014-08-20 15:58:53

标签: sql sql-server sql-server-2008-r2 sql-function

我有一个应该在许多场景中重用的查询。此查询接收一些参数。 因为它必须重用,所以它不能是存储过程。因此,它是作为一个函数创建的(不是视图,因为它需要一些参数)。 这是迄今为止最好的方法,对吧? 问题是此查询返回需要一些后期处理的数据,即在其他一些查询中重用。我正面临着在其他查询中重用它们的问题。

实施例: 函数GetMyFirstData返回多个列,包括FootNoteSymbol列。我应该创建另一个函数(GetFootnoteText)来返回关于这些脚注的文本(以及其他一些细节)。 我应该如何创建第二个函数作为参数接收第一个函数FootNoteSymbol返回的GetMyFirstData(多个)?

我正在避免使用存储过程,因为这些结果很可能会在其他查询中重用。 此外,FootNoteSymbol也在许多其他函数中返回,具有不同的返回结构(因此我无法创建TableType,因为结构不固定 - 但FootNoteSymbol是常见的所有这些)。

使用SQL Server 2008 R2。

返回数据的函数:

CREATE FUNCTION GetMyFirstData
(
  @Param1 int,
  @Param2 int
)
RETURNS @Return TABLE
(
  Col1 int,
  Col2 int,
  FootnoteSymbol int,
  Col3 int,
  Col4 int
)
AS
  BEGIN
    SELECT Col1, Col2, FootnoteSymbol, Col3, Col4
    FROM MyData
    RETURN;
  END

CREATE FUNCTION GetMySecondData
(
  @Param1 int,
  @Param2 int
)
RETURNS @Return TABLE
(
  Col1 int,
  FootnoteSymbol int,
  Col2 int
)
AS
  BEGIN
    SELECT Col1, FootnoteSymbol, Col2
    FROM MyOtherData
    RETURN;
  END

应获取脚注文字的功能:

CREATE FUNCTION GetFootnoteText
(
  @FootnoteSymbol --this is the issue, how to reuse the footnotesymbols from the other functions
)
RETURNS @Return TABLE
(
  Symbol int,
  Text text,
  OtherDetail nvarchar(200)
)
AS
  BEGIN
    SELECT Symbol, Text, OtherDetail
    FROM MyFootnotes
    WHERE Symbol in --this is the issue, how to reuse the footnotesymbols from the other functions
    RETURN;
  END

谢谢!

2 个答案:

答案 0 :(得分:1)

据我所知(我引用你的@SeanLange评论"你知道你的表是什么样的,数据是什么样的,规则是什么以及预期的结果是什么。我在另一方面也看不出任何一个。")你对关系数据库的工作原理有一个基本的错误理解。要解决问题"这里使用标准的关系数据库实践提出的问题我不会把它分成多个函数(因为那里没有增益)而是我会创建一个执行JOIN以获取所需数据的SP。像这样:

CREATE PROCEDURE GetData
(
  @Param1 int,
  @Param2 int
)
AS
  BEGIN
    SELECT MyData.Col1,
           MyData.Col2,
           MyFootnotes.Text, 
           MyFootnotes.OtherDetail, 
           MyData.Col3,
           MyData.Col4
    FROM MyData
    JOIN MyFootnotes ON MyData.FootnoteSymbol = MyFootnotes.Symbol
  END

你没有显示你如何使用参数,所以我无法解决这个问题,但我可以猜测。让我们说这个函数中的参数用在where子句中以限制结果。 (Col1 = @ Param1和Col2 = @ Param2)但在另一种情况下,你有不同的限制(例如Col3 = @ Param1和Col4 = @Param2)。

在这种情况下,最好的方法是创建一个在每个SP中共享和限制的视图。我不会使用函数,因为我认为它们没有价值(并且@RemusRusanu指出问题的可能性很大)。像这样:

CREATE VIEW MyData AS
    SELECT MyData.Col1,
           MyData.Col2,
           MyFootnotes.Text, 
           MyFootnotes.OtherDetail, 
           MyData.Col3,
           MyData.Col4
    FROM MyData
    JOIN MyFootnotes ON MyData.FootnoteSymbol = MyFootnotes.Symbol

CREATE PROCEDURE GetData1
(
  @Param1 int,
  @Param2 int
)
AS
  BEGIN
    SELECT * 
    FROM MyData
    WHERE  MyData.Col1,
           MyData.Col2,
           MyFootnotes.Text, 
           MyFootnotes.OtherDetail, 
           MyData.Col3,
           MyData.Col4
    FROM MyData
    WHERE Col1=@Param1 and Col2=@Param2
  END

CREATE PROCEDURE GetData2
(
  @Param1 int,
  @Param2 int
)
AS
  BEGIN
    SELECT * 
    FROM MyData
    WHERE  MyData.Col1,
           MyData.Col2,
           MyFootnotes.Text, 
           MyFootnotes.OtherDetail, 
           MyData.Col3,
           MyData.Col4
    FROM MyData
    WHERE Col3=@Param1 and Col4=@Param2
  END

我知道作为一名在非关系系统中工作的程序员,这并不直观。不过相信我,这会给你带来最好的结果。这就是您的服务器软件预期使用的方式,多年来它一直在调整,以这种方式使用视图为您提供快速的结果。

答案 1 :(得分:1)

DO。不。做。这一点。

重用代码是一个崇高的目标,但SQL不是它的语言。您的方法会导致许多记录在案的性能问题。一些快速链接Query Performance and multi-statement table valued functionsImproving query plans with the SCHEMABINDING option on T-SQL UDFsCompute Scalars, Expressions and Execution Plan Performance

我希望我有一个很好的选择,但我没有。视图可以重复使用查询。但是,在我见过的每一次交流中,尝试编写SQL表值函数总是以灾难告终。

不要这样做。

至少坚持Inline Table Value Functions;

  
      
  • RETURNS子句仅包含关键字表。您不必定义返回变量的格式,因为它是由RETURN子句中SELECT语句的结果集的格式设置的。
  •   
  • 没有由BEGIN和END分隔的function_body。
  •   
  • RETURN子句在括号中包含一个SELECT语句。 SELECT语句的结果集形成函数返回的表。内联函数中使用的SELECT语句与视图中使用的SELECT语句具有相同的限制。
  •   
  • 表值函数只接受常量或@local_variable参数
  •