Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我应该使用T-SQL函数、视图还是存储过程?_Sql_Stored Procedures_Function_Select_Union All - Fatal编程技术网

我应该使用T-SQL函数、视图还是存储过程?

我应该使用T-SQL函数、视图还是存储过程?,sql,stored-procedures,function,select,union-all,Sql,Stored Procedures,Function,Select,Union All,我有一个关于重用表数据的问题,但是视图在这种情况下不起作用,因为我有一个需要传入的参数。基本上,系统的这一部分需要向程序发送travellerid,并返回该特定Traveler的安排人列表。大约有7条业务规则用于确定可以返回哪些排列程序,它们是互斥的,因此为了适应这些可选规则,我在派生查询中使用了一系列联合。这很好,在相当大的数据库中性能似乎也不错,但是我需要在系统的其他4个部分中重用这些规则(联合) 我最初试图用这些联合创建一个视图,但由于每个联合中的逻辑不同,参数要求也不同,所以我想也许函数

我有一个关于重用表数据的问题,但是视图在这种情况下不起作用,因为我有一个需要传入的参数。基本上,系统的这一部分需要向程序发送
travellerid
,并返回该特定Traveler的安排人列表。大约有7条业务规则用于确定可以返回哪些排列程序,它们是互斥的,因此为了适应这些可选规则,我在派生查询中使用了一系列联合。这很好,在相当大的数据库中性能似乎也不错,但是我需要在系统的其他4个部分中重用这些规则(联合)

我最初试图用这些联合创建一个视图,但由于每个联合中的逻辑不同,参数要求也不同,所以我想也许函数可以解决这个问题?如果我创建了一个函数,将
@travellerid
作为参数,并根据业务规则返回
arrangerid
列表,这是一个理想/快速的解决方案吗?我目前正在外部查询中使用UNIONALL和DISTINCT,因为事实证明,在数据唯一性方面,这比使用UNION要快得多

具有以下业务规则的当前过程(SQL Server 2008):

我最初试图用这些联合创建一个视图,但由于每个联合中的逻辑不同,参数要求也不同,所以我想也许函数可以解决这个问题?如果我创建了一个函数作为param@travellerid,并根据业务规则返回ArrangeId列表,这是一个理想/快速的解决方案吗

您正在考虑过程化/OO编程,但SQL是基于集合的。
一个函数可以工作,但可以确保在您将该函数用于决策标准/等时不能使用索引。非物化视图只是稍微好一点;在SQL Server中,可以选择使用索引视图(也称为物化视图),但它们受到了众所周知的约束。这与模块化编程的概念背道而驰,但SQL工作得越好,因为您尝试将其模块化的次数越少,并且只使用实际需要的内容

我重新编写了您的查询,但注意到dv.preferred列在外部查询中被引用,但在内部查询中不存在。由于
dv
是各种表和逻辑的集合,因此返回的
id
值在内部查询之外没有任何实际值,因为您需要知道值来自哪个表。这就是说,这里是:

SELECT t.id, t.firstname, t.lastname, ti.name AS title /*, dv.preferred */
  FROM TRAVELLER t
  JOIN title ti ON t.titleid = ti.id
 WHERE (EXISTS(SELECT NULL -- Get Preferred Arrangers linked to Department Groups
                 FROM departmentGroup dg 
                 JOIN department_departmentGroup ddg ON ddg.departmentGroupId = dg.id 
                                                    AND ddg.departmentid = @departmentid
                WHERE dg.arrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Preferred Arrangers linked to Cost Centre Groups
                FROM costCentreGroup cg 
                JOIN costcentre_costCentreGroup ccg ON ccg.costCentreGroupId = cg.id 
                                                   AND ccg.costcentreid = @costcentreid
               WHERE cg.arrangerid = t.id)
    OR EXISTS(SELECT NULL -- If Cost Centre Group has a linked department and this department matches the travel arrangers department then return these travel arrangers as well     
                FROM costCentreGroup cg1
                JOIN costcentre_costCentreGroup ccg1 ON ccg1.costCentreGroupId = cg1.id 
                                                    AND ccg1.costcentreid = @costcentreid
                JOIN traveller t3 ON t3.departmentid = cg1.departmentid    
                                 AND  t3.accesslevelid > 1
               WHERE t3.id = t.id)
    OR EXISTS(SELECT NULL  -- Get Direct linked travel arrangers    
                FROM travelarranger_traveller t1
               WHERE t1.travellerid = @travellerid
                 AND t1.travelarrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Cost Centre linked arrangers
                FROM travelArranger_costcentre tc 
               WHERE tc.costcentreid = @costcentreid
                 AND tc.travelarrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Department linked arrangers
                FROM travelArranger_department td 
               WHERE td.departmentid = @departmentid
                 AND td.travelarrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Company flagged arrangers 
                FROM traveller t2
                JOIN company c ON t2.companyid = c.id
                              AND t2.accesslevelid > 1       
               WHERE (   (c.allowTravelArrangerDepartmentAccess = 1 AND t2.departmentid = @departmentid)
                      OR (c.allowTravelArrangerCostCentreAccess = 1 AND t2.costcentreid = @costcentreid))
                 AND t2.id = t.id))
   AND t.accessLevelid > 1 -- arranger or manager
   AND t.isenabled = 1
ORDER BY /*dv.preferred DESC,*/ t.lastname, t.firstname;

如果父记录附加了多个子记录,则使用子查询(IN、EXISTS)将缓解使用联接时出现的重复问题。

感谢您的快速详细响应。很抱歉,我已经从每个工会中删除了“首选”标志,因为它不是必需的,并且我在外部选择中留下了对它的引用。忽略这一点,就像你已经做过的那样。随着查询的重写,它仍然有效地使我处于与以前相同的位置,因此我不能重用这些规则。这些6/7 select查询是我以前使用过的,它们构成了核心业务规则,并且在系统中的其他5个过程中使用了相同的精确语句,如果添加新的规则,这些查询将变得更难维护。此外,对于每个EXISTS子句中的select NULL,我也有点困惑?我原以为它是在每个子查询中检查是否存在的ID。因此,在您看来,考虑到一个指定的安排人可能会返回多达4000名旅行者,为加入目的创建一个可重用的函数是否会降低性能?谢谢@Phil Rasmussen:正如我所解释的,您希望重用我将重新声明的逻辑:这是一个用于良好执行SQL的基础。从维护的角度来看,您很容易做到的事情,实际上可能会导致性能不佳。这取决于你是否值得权衡。@Phil Rasmussen:SELECT子句在EXISTS子句中并不重要——你可以使用SELECT 1/0,它会因数学错误而失败,但不会因为我所说的原因。好的,关于权衡,我可能只是尝试一下,在EXISTS和基于UNION的子查询旁边运行一些性能测试,看看它有多大的不同。我想,当涉及到SQL时,归根结底是关于性能的,尽管当您不得不多次重复相同的冗长代码时,它确实会变得混乱。再次感谢。
SELECT t.id, t.firstname, t.lastname, ti.name AS title /*, dv.preferred */
  FROM TRAVELLER t
  JOIN title ti ON t.titleid = ti.id
 WHERE (EXISTS(SELECT NULL -- Get Preferred Arrangers linked to Department Groups
                 FROM departmentGroup dg 
                 JOIN department_departmentGroup ddg ON ddg.departmentGroupId = dg.id 
                                                    AND ddg.departmentid = @departmentid
                WHERE dg.arrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Preferred Arrangers linked to Cost Centre Groups
                FROM costCentreGroup cg 
                JOIN costcentre_costCentreGroup ccg ON ccg.costCentreGroupId = cg.id 
                                                   AND ccg.costcentreid = @costcentreid
               WHERE cg.arrangerid = t.id)
    OR EXISTS(SELECT NULL -- If Cost Centre Group has a linked department and this department matches the travel arrangers department then return these travel arrangers as well     
                FROM costCentreGroup cg1
                JOIN costcentre_costCentreGroup ccg1 ON ccg1.costCentreGroupId = cg1.id 
                                                    AND ccg1.costcentreid = @costcentreid
                JOIN traveller t3 ON t3.departmentid = cg1.departmentid    
                                 AND  t3.accesslevelid > 1
               WHERE t3.id = t.id)
    OR EXISTS(SELECT NULL  -- Get Direct linked travel arrangers    
                FROM travelarranger_traveller t1
               WHERE t1.travellerid = @travellerid
                 AND t1.travelarrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Cost Centre linked arrangers
                FROM travelArranger_costcentre tc 
               WHERE tc.costcentreid = @costcentreid
                 AND tc.travelarrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Department linked arrangers
                FROM travelArranger_department td 
               WHERE td.departmentid = @departmentid
                 AND td.travelarrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Company flagged arrangers 
                FROM traveller t2
                JOIN company c ON t2.companyid = c.id
                              AND t2.accesslevelid > 1       
               WHERE (   (c.allowTravelArrangerDepartmentAccess = 1 AND t2.departmentid = @departmentid)
                      OR (c.allowTravelArrangerCostCentreAccess = 1 AND t2.costcentreid = @costcentreid))
                 AND t2.id = t.id))
   AND t.accessLevelid > 1 -- arranger or manager
   AND t.isenabled = 1
ORDER BY /*dv.preferred DESC,*/ t.lastname, t.firstname;