3

我有这个程序

ALTER PROCEDURE [dbo].GetHerdByUserProc(@user int)
As 
    begin
        Declare
            @GroupId uniqueidentifier,
            @UserTrade bit

        Set @GroupId = (select tbUser.group_id from tbUser where Userid = @user)
        Set @UserTrade = (select tbUser.isTrade from tbUser where Userid = @user)
        if @GroupId IS NOT NULL and @UserTrade = '1'
        Begin 
            select HerdId from tbUserHerds where tbUserHerds.UserId in (select Userid from tbUser where tbUser.Group_Id = @GroupId)
            return;
        END
        If @GroupId IS NOT NULL
        Begin   
            select HerdId from tbUserHerds where tbUserHerds.UserId = @user
            return;
        End
        return;
    End

它正确返回一个列表,除了我还想在返回的列表上运行一个查询,据我所知,我无法编写查询,例如

Select * from GetHerdByUserProc 80

所以我正在寻找将其转换为表值查询的最佳方法。

我已经改变了说'Create Function x(@user int) Returns Table As'

但这似乎不起作用,它开始向我尖叫错误。

有任何想法吗?数据库服务器是 MSSQL2008

4

4 回答 4

3

根据您的语法,我现在假设使用 SQL Server。

BOL中,内联函数的语法应该是...

--Transact-SQL Inline Table-Valued Function Syntax 
CREATE FUNCTION [ schema_name. ] function_name 
( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type 
    [ = default ] [ READONLY ] } 
    [ ,...n ]
  ]
)
RETURNS TABLE
    [ WITH <function_option> [ ,...n ] ]
    [ AS ]
    RETURN [ ( ] select_stmt [ ) ]
[ ; ]

使用这种格式,您不能使用SET, DECLARE, IF, etc. 您可以使用的只是一条 SQL 语句。 [如果您需要使用程序流,请查看多语句表值函数。]

这是一个单独的主题,但内联表值函数比它们的多语句等效函数具有许多性能效率。几乎总是,如果你可以内联,你应该这样做。

碰巧的是,您可以在没有IF语句的情况下编写逻辑,而只使用一条 SQL 语句。这给出了以下内联表值函数...

CREATE FUNCTION [dbo].GetHerdByUserProc(@user int)
RETURNS TABLE
RETURN
  SELECT
    herd.HerdID
  FROM
    tbUser          AS user
  INNER JOIN
    tbUser          AS group
      ON group.group_id = user.group_id
  INNER JOIN
    tbUserHerds     AS herd
      ON herd.UserID = group.UserID
  WHERE
        user.userID   = @userID
    AND user.isTrade  = 1
    AND user.group_id IS NOT NULL

  UNION ALL

  SELECT
    herd.HerdID
  FROM
    tbUser          AS user
  INNER JOIN
    tbUserHerds     AS herd
      ON herd.UserID = user.UserID
  WHERE
        user.userID    = @userID
    AND user.isTrade  <> 1
    AND user.group_id IS NOT NULL

UNION ALLWHERE条款的结合有效地IF为您做陈述。 (请注意,如果 user.isTrade 可以是NULL,您需要更改user.isTrade <> 1为更像ISNULL(user.isTrade, 0) <> 1.)

潜在地,您甚至可以将其简化为单个查询,尽管我会对其进行测试以查看它是否实际上更有效......

RETURN
  SELECT
    herd.HerdID
  FROM
    tbUser          AS user
  INNER JOIN
    tbUser          AS group
      ON (group.group_id = user.group_id AND user.isTrade = 1)
      OR (group.user_id  = user.userID)
  INNER JOIN
    tbUserHerds     AS herd
      ON herd.UserID = group.UserID
  WHERE
    user.userID = @userID
  • 如果group_id为 NULL,则第一次连接永远不会成功。
  • 然后两个 IF 模块由OR.
于 2012-11-01T09:33:29.927 回答
1

您可以将 PROC 的结果存储在临时表中:

INSERT INTO #temptbl EXEC [dbo].GetHerdByUserProc(80)
于 2012-11-01T09:21:22.910 回答
1

您需要在定义中定义表的结构,然后将值插入到声明表变量中...

create function x
(
    @user int 
)
returns @t
( 
   herdid int
)
as
begin
    insert @t (herdid)
    select HerdId from tbUserHerds where tbUserHerds.UserId = @user
    -- or whatever...
    return 
end

请参阅http://msdn.microsoft.com/en-us/library/ms191165(v=sql.105).aspx

于 2012-11-01T09:21:38.867 回答
0

您可以简单地使用 CASE 语句编写 sql 查询。CASE 语句是处理条件查询的最简单方法。

 Declare @GroupId uniqueidentifier,@UserTrade bit

 select HerdId 
 from tbUserHerds 
 where 
 1 = CASE 
    WHEN (select tbUser.group_id from tbUser where Userid = @user) IS NOT NULL 
    THEN 
        CASE 
            WHEN tbUserHerds.UserId = @user THEN 1 
            ELSE 0 
        END

    WHEN 
            (select tbUser.group_id from tbUser where Userid = @user) IS NOT NULL      and           (select tbUser.isTrade from tbUser where Userid = @user) = '1'
    THEN 
        CASE 
            WHEN tbUserHerds.UserId in (select Userid from tbUser     where tbUser.Group_Id = (select tbUser.group_id from tbUser where Userid = @user)) THEN 1 
            ELSE 0 
        END
END
于 2012-11-01T18:54:56.147 回答