2016-09-01 2 views
1

Я создал функцию в SQL Server для выполнения динамического SQL-запроса и возврата значения. Я получаю сообщение об ошибке при вызове функции в SQL запросе:Команда SQL Server execute (sp_executesql) в функции SQL

Только функции и некоторые расширенные хранимые процедуры могут быть выполнены из функции

Функции: (возвращает количество пользователей, связанные с @ModuleName)

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

SET @Query = 'SELECT @UsersUsingModule = Count(UR.UserId) '+ 
     'FROM  '[email protected]+'.[dbo].[aspnet_UsersInRoles] AS UR '+ 
     'INNER JOIN '[email protected]+'.[dbo].[aspnet_Roles] AS R ON UR.RoleId = R.RoleId '+ 
     'INNER JOIN '[email protected]+'.[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 

Запрос:

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 

Помогите мне, если есть лучший подход!

+0

Посмотрите (http://stackoverflow.com/questions/15180561/getting-an-error-when-executing-a-dynamic-sql-within-a-function-sql-server» это'). Может помочь :) –

ответ

4

По определению ФУНКЦИЯ никогда не допускается к содержимому таблицы ALTER. Здесь в этом только SELECT, я понимаю, но IMHO FUNCTION не предназначены для этого. ЗАПОМНИТЕ ПРОЦЕДУРЫ предназначены для выполнения этого трюка.

Если вы все еще хотите продолжать делать то, что собираетесь намереваться, тогда вам, возможно, придется использовать некоторые хаки, как указано на сайте this, которые вообще нецелесообразны в более долгосрочной перспективе.

Вы можете сравнить this вопрос для аналогичного обсуждения!

Надеюсь, это поможет в ваших решениях!

3

В основном функция используется для целей расчета, что-то вроде запроса выбора. Вы не можете выполнять процедуры внутри функции. В этом случае вы пытаетесь использовать процедуру 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  '[email protected]+'.[dbo].[aspnet_UsersInRoles] AS UR '+ 
     'INNER JOIN '[email protected]+'.[dbo].[aspnet_Roles] AS R ON UR.RoleId = R.RoleId '+ 
     'INNER JOIN '[email protected]+'.[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 
Смежные вопросы