0

我真的可以使用一些幫助編寫使用以下邏輯多語句表值函數:T-SQL多語句表值函數

  • 接受一個varchar參數爲輸入
  • 如果參數與A開始,運行SELECT語句
  • 如果沒有行返回,運行SELECT語句
  • 如果該參數不具有啓動,運行SELECT語句
  • 如果沒有行返回,運行select語句
  • 返回一個輸出表,該表將結果集的一個從取決於參數

到目前爲止上面,這是我有:

CREATE FUNCTION dbo.CheckAccess 
(@UserName varchar(30)) 
RETURNS @AccessTable TABLE (User varchar(max), Access varchar(max)) 
AS 

BEGIN 
    IF LEFT(@UserName,1) = 'A' 
     INSERT INTO @AccessTable 
     SELECT 
      CASE 
      WHEN EXISTS (SELECT User, Access FROM dbo.AccessTable1 WHERE User = @UserName) 
      THEN (SELECT User, Access FROM dbo.AccessTable1 WHERE User = @UserName) 
      ELSE (SELECT @UserName User, 'No Access' Access) 
      END 
    ELSE 
     INSERT INTO @AccessTable 
     SELECT 
      CASE 
      WHEN EXISTS (SELECT User, Access FROM dbo.AccessTable2 WHERE User = @UserName) 
      THEN (SELECT User, Access FROM dbo.AccessTable2 WHERE User = @UserName) 
      ELSE (SELECT @UserName User, 'No Access' Access) 
      END 
RETURN 
END; 

不知道我很想念這裏,但我收到了以下錯誤:

Msg 116, Level 16, State 1, Procedure CheckAccess, Line 90 
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS. 
Msg 116, Level 16, State 1, Procedure CheckAccess, Line 92 
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS. 
Msg 213, Level 16, State 1, Procedure CheckAccess, Line 11 
Column name or number of supplied values does not match table definition. 

我知道如何在存儲過程中做到這一點很容易,使用臨時表,但由於它們一在功能上不是一個選項,我有點困難。如果有人可以提供一些建議,我會很感激。提前致謝。

回答

0

,而不是像這樣

EXISTS (SELECT User, Access FROM dbo.AccessTable1 WHERE User = @UserName) 

一個布爾檢查嘗試

EXISTS (SELECT 1 FROM dbo.AccessTable1 WHERE User = @UserName) 

通常一個EXISTS表達式不需要特定的結果,它只是需要請檢查是否返回NULL,因爲沒有行可能是無論發現什麼,都可能會返回一些東西。這是一個布爾表達式,其值爲yes或no。 '1'就足夠了。前兩個錯誤消息是關於這個的。

下一個問題是CASE表達式的定義只能定義一個字段和一個字段。它不能返回所需的兩個字段。這就是最後的錯誤信息是可以提供的,函數被定義爲返回兩個字段。您現在可以編寫兩個CASE表達式,用逗號分隔。

我會爲你的邏輯提出一個不同的方法,但是:在你的IF語句中,你可以做一些子IFs,比如嵌套的IFs。我沒有測試過這一點,只是一個想法:

IF LEFT(@UserName,1) = 'A' 
    IF EXISTS (SELECT 1 FROM dbo.AccessTable1 WHERE User = @UserName) 
     INSERT INTO @AccessTable 
     SELECT User, Access FROM dbo.AccessTable1 WHERE User = @UserName 
    ELSE (SELECT @UserName User, 'No Access' Access) 

    ELSE 
    IF EXISTS (SELECT 1 FROM dbo.AccessTable2 WHERE User = @UserName) 
     INSERT INTO @AccessTable 
     SELECT User, Access FROM dbo.AccessTable2 WHERE User = @UserName 
    ELSE (SELECT @UserName User, 'No Access' Access) 

或propably性能更好其他的想法,但我不知道這是否符合你的場「訪問」 100%的要求。如果@ username存在於表中,那麼總是會在Access字段中出現?

IF LEFT(@UserName,1) = 'A' 
     SELECT 
     ISNULL(User,@UserName) User 
     ,ISNULL(Access,'No Access') Access 
     FROM dbo.AccessTable1 WHERE User = @UserName 
    ELSE 
     SELECT 
     ISNULL(User,@UserName) User 
     ,ISNULL(Access,'No Access') Access 
     FROM dbo.AccessTable2 WHERE User = @UserName 

一個額外的評論:IF(也ELSE)將只考慮一個以下語句。如果有一個以上的語句來運行,你需要通過向encapsule他們開始和結束,像這樣

IF @fact=1 
    BEGIN 
    statement 1 
    . 
    . 
    statement n 
    END 
ELSE 
    BEGIN 
    statement 1 
    . 
    . 
    statement n 
    END 
1

可以使用@@rowcount服務器變量爲簡化功能:

CREATE FUNCTION dbo.CheckAccess 
    (@UserName varchar(30)) 
    RETURNS @AccessTable TABLE (User varchar(max), Access varchar(max)) 
AS 

BEGIN 
    IF LEFT(@UserName,1) = 'A' 
     INSERT INTO @AccessTable 
     SELECT User, Access FROM dbo.AccessTable1 WHERE User = @UserName 
    ELSE 
     INSERT INTO @AccessTable 
     SELECT User, Access FROM dbo.AccessTable2 WHERE User = @UserName 

    [email protected]@rowcount gives number of records inserted/affected from immediately previous query 
    IF @@RowCount = 0 
     INSERT INTO @AccessTable 
     SELECT @UserName User, 'No Access' Access 

    RETURN 

END;