是否可以在同一查询中同时使用过滤器和视图函数?

时间:2016-06-23 16:35:53

标签: sql sql-server user-defined-functions

我的表格有点像这样(请原谅不准确的定义):

CREATE TABLE JunctionTable( int Concrete1ID, int Concrete2ID, int someProperty)
CREATE TABLE Concrete1 ( int ID, int Prop1, int Prop2)
CREATE TABLE Concrete2 ( int ID, int Prop1, int Prop2, int Prop3, int Prop4)

每个具体表都有外键。

我有一些功能。一个函数 - FilterJunction - 用于在JunctionTable中获取满足特定条件的内容,另一个函数 - SomeViewofConcrete2 - 返回给定{{1}的Concrete2行的属性}}

Concrete2ID

请注意,CREATE FUNCTION [dbo].FilterJunction() Returns Table AS BEGIN RETURN (SELECT * FROM JunctionTable WHERE someProperty < 5) END CREATE FUNCTION [dbo].SomeViewOfConcrete2(@ID int) RETURNS TABLE BEGIN Return (SELECT Prop2, Prop4 FROM Concrete2 WHERE ID = @ID) END 最多只返回一行(在这种情况下,它应该肯定返回一行,因为我已经设置了相应的外键。)

所以最后我想运行以下查询:

SomeViewOfConcrete2

但是得到以下错误:

  

“无法找到列”dbo“或用户定义的函数或   聚合“dbo.SomeViewOfConcrete2”,或者名称不明确。“

虽然如果我尝试使用特定的SELECT ConcreteID1, ConcreteID2, [dbo].SomeViewOfConcrete2(Concrete2ID) FROM [dbo].FilterJunction() 分别运行SomeViewOfConcrete2,那么该查询运行完全正常。 (例如ConcreteID2

我认为问题是我无法告诉SQL该函数只返回一行,因此它不知道如何给出SELECT * FROM [dbo].SomeViewOfConcrete2(1)的预期结果集,但该错误消息肯定没有不能很好地说明这一点。

我能解决这个问题的一种方法就是:

ConcreteID1, ConcreteID2, Prop2, Prop4

但是这不使用SELECT ConcreteID1, ConcreteID2, Prop2, Prop4 FROM [dbo].FilterJunction() F JOIN CONCRETE2 C ON F.ConcreteID2 = C.ID 函数,因此不鼓励代码重用。

所以我道歉但我的问题有两点:

  1. 是否可以以鼓励代码重用过滤器和查看功能的方式设计查询?
  2. 为什么SQL会抛出它给出的错误而不是说别的?
  3. 感谢。

1 个答案:

答案 0 :(得分:4)

这是因为表值函数被设计为返回任意数量的行。你不能只把这样的表推成一列。但是,您可以非常有效地使用APPLY。

SELECT ConcreteID1
    , ConcreteID2
    , svc.Prop2 --or whatever columns from that function
    , svc.Prop4
FROM [dbo].FilterJunction() fj
cross apply [dbo].SomeViewOfConcrete2(fj.Concrete2ID) svc