2

我有這個程序轉換存儲過程,表值查詢

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 

所以我正在尋找最好的方式將其轉換爲表值查詢。

我已經改變了ALTER說'Create Function x(@user int) Returns Table As'

但是,這並不縫工作,它開始向我大聲尖叫錯誤。

任何想法?數據庫服務器是MSSQL2008

+0

*** *** SQL只是*結構化查詢語言* - 許多數據庫系統中使用的語言,但沒有AA數據庫產品......像這樣的東西是非常特定於供應商 - 所以我們真的需要知道你正在使用的數據庫系統**(以及哪個版本)。 –

回答

2

根據你的語法,我要承擔的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語句。 [如果你需要使用程序流程,看多語句表值函數。]

這是一個獨立的主題,但內聯表值函數有超過他們的多語句equivilents 許多性能效率。幾乎總是,如果你可以做到內聯,你應該這樣做。

碰巧,您可以在不使用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模擬。
1

您可以在PROC的結果存儲在一個臨時表:

INSERT INTO #temptbl EXEC [dbo].GetHerdByUserProc(80) 
+0

爲什麼選擇倒票?將sp的結果存儲到臨時表中將允許OP對結果集運行查詢,而無需重寫代碼。 – SchmitzIT

+0

它並不需要是一個SP,則OP不希望的SP,你不能調用從SQL Statment內的SP,所以它很難將自己加入到自身*(以及很多其他丟失的功能)*,這隻能在SP調用樹的一個級別完成*(如果外部SP也使用這個技巧,它將失敗)*。大多數情況下,事實上,它並沒有回答這個問題,有機磷,當它是完美的交代,和完全合理的,甚至是推薦的,這就是爲什麼我加入你的第二個-1。 * [你甚至不解釋爲什麼這應該在你的答案被使用,但您的評論不會去實現這一] * – MatBailie

+1

的OP明確指出:「據我所知,我不能使用類似」從GetHerdByUserProc 80 SELECT * 」我的回答表明,有辦法實現他想要的東西,而無需重寫一切。 – SchmitzIT

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

+0

真正的'多statement' TVFs。我想明確指出'Inline' TVFs不同,而有不同的限制,好處。 – MatBailie

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