SQL Server 在 SQL 函数中执行 (sp_executesql) 命令

Sam*_*ami 6 sql sql-server stored-procedures sql-function

我在 SQL Server 中创建了一个函数来执行动态 SQL 查询并返回一个值。在 SQL 查询中调用函数时出现错误:

只能从函数内部执行函数和一些扩展存储过程

功能:(返回与@ModuleName 关联的用户数)

DECLARE @Query NVARCHAR(MAX)
DECLARE @Result int
DECLARE @UsersUsingModule AS NVARCHAR(99)

SET @Query = 'SELECT @UsersUsingModule = Count(UR.UserId) '+
        'FROM       '+@UserDBName+'.[dbo].[aspnet_UsersInRoles] AS UR '+
        'INNER JOIN '+@UserDBName+'.[dbo].[aspnet_Roles] AS R ON UR.RoleId = R.RoleId '+
        'INNER JOIN '+@UserDBName+'.[dbo].[aspnet_Users] AS U ON UR.UserId = U.UserId '+
        'WHERE      LOWER(RoleName) IN ( '+
            'SELECT LOWER([Role]) '+
            'FROM   ADMIN_ROLEACCESS '+
            'WHERE  LOWER(ModuleName) = LOWER(@ModuleName) '+
        ')'

        EXEC sp_executesql @Query, N'@ModuleName nvarchar(max), @UsersUsingModule INT OUTPUT', @ModuleName, @UsersUsingModule OUTPUT

SELECT @Result =  CAST(@UsersUsingModule as INT)
RETURN @Result
Run Code Online (Sandbox Code Playgroud)

询问:

SELECT      
    M.ID as [ModuleID], M.ModuleName, CC.UserLicenses,
    dbo.fncRolesWithModule(M.ModuleName) AS [Roles],
    [dbo].[fncUsersUsingModule](M.ModuleName, 'USERS_Demo2016')
FROM        
    ADMIN_ClientsContracts as CC
INNER JOIN  
    ADMIN_Modules as M ON CC.ModuleID = M.ID
WHERE
    CC.Isactive = 1
Run Code Online (Sandbox Code Playgroud)

如果有更好的方法,请告诉我!

Unn*_*n R 6

函数用于计算,类似于SELECT查询。您无法在函数内执行存储过程。在这种情况下,您尝试使用sp_executesql函数内部的过程,这会导致此问题。

如果您想执行相同的步骤,您可以使用如下过程而不是函数。

CREATE PROCEDURE dbo.GetUserModule
@UserDBName NVARCHAR(50),
@ModuleName NVARCHAR(150)

AS

BEGIN

DECLARE @Query NVARCHAR(MAX)
DECLARE @Result int
DECLARE @UsersUsingModule AS NVARCHAR(99)

SET @Query = 'SELECT @UsersUsingModule = Count(UR.UserId) '+
        'FROM       '+@UserDBName+'.[dbo].[aspnet_UsersInRoles] AS UR '+
        'INNER JOIN '+@UserDBName+'.[dbo].[aspnet_Roles] AS R ON UR.RoleId = R.RoleId '+
        'INNER JOIN '+@UserDBName+'.[dbo].[aspnet_Users] AS U ON UR.UserId = U.UserId '+
        'WHERE      LOWER(RoleName) IN ( '+
            'SELECT LOWER([Role]) '+
            'FROM   ADMIN_ROLEACCESS '+
            'WHERE  LOWER(ModuleName) = LOWER(@ModuleName) '+
        ')'

        EXEC sp_executesql @Query, N'@ModuleName nvarchar(max), @UsersUsingModule INT OUTPUT'
                           , @ModuleName
                           , @UsersUsingModule OUTPUT

        SELECT @Result =  CAST(@UsersUsingModule as INT)
    RETURN @Result

END
Run Code Online (Sandbox Code Playgroud)


N00*_*mer 5

根据定义,永远不允许FUNCTION更改表内容。这里它只是一个选择,我理解,但恕我直言,函数不是为此设计的。存储过程就是为了实现这个目的而设计的。

如果您仍然想继续做您想做的事情,那么您可能必须使用网站中提到的一些技巧,从长远来看,这些技巧根本不可取。

大家可以关注这个问题进行类似的讨论!

希望这可以帮助!