Tsql T-SQL多语句表值函数

Tsql T-SQL多语句表值函数,tsql,sql-server-2008-r2,user-defined-functions,table-valued-parameters,Tsql,Sql Server 2008 R2,User Defined Functions,Table Valued Parameters,我真的需要一些帮助来编写使用以下逻辑的多语句表值函数: 接受varchar参数作为输入 如果参数以开头,请运行select语句 如果未返回任何行,请运行select语句 如果参数不是以开头,请运行select语句 如果未返回任何行,请运行select语句 返回一个输出表,根据参数,它将是上面的结果集之一 到目前为止,我的情况如下: CREATE FUNCTION dbo.CheckAccess (@UserName varchar(30)) RETURNS @AccessTable TABL

我真的需要一些帮助来编写使用以下逻辑的多语句表值函数:

  • 接受varchar参数作为输入
  • 如果参数以开头,请运行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.

我知道如何使用临时表在存储过程中相当容易地做到这一点,但由于它们不是函数中的选项,所以我有点困难。如果有人能提供一些建议,我将非常感激。提前感谢。

而不是像这样的布尔检查

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

通常,EXISTS表达式不需要特定的结果,它只需要检查是否返回NULL,因为找不到任何行,或者无论返回什么内容,是否都可以返回。它是一个布尔表达式,计算结果为是或否。“1”就足够了。前两条错误消息与此有关

下一个问题是,按定义的CASE表达式只能定义一个字段,并且只能定义一个字段。它无法返回所需的两个字段。这就是最后一条错误消息可能涉及的内容,函数定义为返回两个字段。现在可以编写两个大小写表达式,用逗号分隔

不过,我会为您的逻辑建议一种不同的方法:在IF语句中,执行子IF,比如嵌套IF。我没有对此进行测试,只是一个想法:

   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)
或者另一个可能会更好的想法,但我不确定这是否满足您对字段“访问”100%的要求。如果表格中有@username,那么访问字段中是否会有内容

   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(另外)只考虑一个后续语句。如果要运行多个语句,则需要按照这样的开头和结尾封装它们

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

您可以使用
@@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

   --@@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;
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

   --@@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;