执行视图告诉我我对它的某些功能没有权限

问题描述

我创建了一个使用视图检索数据的受限用户,因此它无法访问整个数据库

但是当我授予他对预期视图的“选择”权限时,它返回一个错误,表明它对视图中使用的某些函数没有权限。虽然它在其他一些功能上没有问题。

如果我授予他对这些函数的“执行”权限,那么它工作正常,但我的问题是为什么我需要授予他对某些函数的执行权限而其他函数不需要它们?。

我看不出从一开始就起作用的功能和需要额外权限的功能之间有什么区别。它们都是同一 dbo 架构上的普通用户函数

所有涉及的对象(视图、表和函数)都属于相同的数据库和架构:dbo。

为了使视图仅具有视图的权限,我应该注意什么?.

这是视图(这是我继承的一个巨大的丑陋视图):

CREATE VIEW [dbo].[EXCEL_LLIBRETA_MAGICA_COMANDES_PENDENTS_V] AS 

-- Aquesta consulta esta basada en COMANDES_PENDENTS,i l'hen expandit per a afegir el Representant,utilitzar la funció f_comanda_bloquejada per a calcular BloqAdmon,...

SELECT LiniesComandesvendes.NumeroOrdre,CapsaleraComandesvendes.Numero,--Isnull( LiniesComandesvendes.ColorExterior,'')+'-'+Isnull(convert(varchar,convert(float,liniesComandesvendes.GruixExterior)),'') ColorExterior,--Isnull(LiniesComandesvendes.ColorInterior,LiniesComandesvendes.GruixInterior)),'') ColorInterior,Isnull(Isnull(dbo.f_consum_color_Exterior(LiniesComandesvendes.NumeroOrdre),LiniesComandesvendes.ColorExterior),Isnull(dbo.f_consum_Gruix_Exterior(liniesComandesvendes.NumeroOrdre),liniesComandesvendes.GruixExterior))),Isnull(Isnull(dbo.f_consum_color_Interior(LiniesComandesvendes.NumeroOrdre),LiniesComandesvendes.ColorInterior),Isnull(dbo.f_consum_Gruix_Interior(liniesComandesvendes.NumeroOrdre),LiniesComandesvendes.GruixInterior))),/*max(LiniesComandesvendes.LongitudSolape) LongitudSolape,*/
       max(case when Isnull(LongitudSolape,0)>0 and Isnull(LongitudSolape,0)<9999 then RIGHT('    '+CONVERT(VARCHAR(4),Floor(LongitudSolape)),4)+' DEL' 
                else case when Isnull(LongitudSolapeTra,0)>0 and Isnull(LongitudSolapeTra,Floor(LongitudSolapeTra)),4)+' TRA' 
                          else '' 
                     end 
           end) LongitudSolape,dbo.f_RetornaReferenciaFabricant(Articles.ReferenciaFabricant,CapsaleraComandesvendes.Client)  ReferenciaFabricant,CapsaleraComandesvendes.Referencia,CapsaleraAgenda.Nom,CapsaleraComandesvendes.Data,OrdresFabricacio.Estat,OrdresFabricacio.DataFabricacio,sum(LiniesComandesvendes.quantitatMetres) quantitatMetres,sum( LiniesComandesvendes.quantitatMetres - dbo.f_quantitatFabricadaLCV(LiniesComandesvendes.identificadorLinia) )  quantitatMetresPendentsFab,case when dbo.f_ordre_te_Inserts(LiniesComandesvendes.NumeroOrdre)=1 then '# INSERTS #' else '' end +
       convert(varchar(250),case when OrdresFabricacio.DataEntrega is not null then '#'+CONVERT(varchar(8),OrdresFabricacio.dataEntrega,3)+'#' 
                                 else '' 
                            end +
                            OrdresFabricacio.observacions) observacions,dbo.f_comanda_confirmada( CapsaleraComandesvendes.Numero ) confirmada_client,max(LiniesComandesvendes.perfilExterior)perfilExterior,max(LiniesComandesvendes.perfilInterior) perfilInterior,case when dbo.f_comanda_bloquejada(CapsaleraComandesvendes.Numero) = 1 then 1 else 0 end as BloqAdmon,--convert(bit,dbo.f_comanda_bloquejada(CapsaleraComandesvendes.Numero)) BloqAdmon,CASE WHEN iSNULL(OrdresFabricacio.esperarMinims,0)=1 THEN 'S' ELSE 'N' END esperar_fer_minims,AgendaRepresentant.Nom as Representant,coalesce(CapsaleraComandesvendes.DataEntrega,OrdresFabricacio.DataEntrega) as DataEntrega,OrdresFabricacio.revisada,OrdresFabricacio.observacions as ObservacionsOrdre,substring(CapsaleraComandesvendes.Observacions,1,1000) as ObservacionsComanda,substring(CapsaleraComandesvendes.ObservacionsEnvio,1000) as ObservacionsEnvio

FROM GESTIO1.dbo.Articles Articles,GESTIO1.dbo.CapsaleraAgenda CapsaleraAgenda,GESTIO1.dbo.CapsaleraComandesvendes CapsaleraComandesvendes
     LEFT OUTER JOIN CapsaleraAgenda as AgendaRepresentant on AgendaRepresentant.Codi = CapsaleraComandesvendes.Representant
     LEFT OUTER JOIN CLIENTS on CLIENTS.agenda=Isnull(CapsaleraComandesvendes.facturara,CapsaleraComandesvendes.client),GESTIO1.dbo.LiniesComandesvendes LiniesComandesvendes,gestio1.dbo.OrdresFabricacio OrdresFabricacio

WHERE CapsaleraComandesvendes.Numero = LiniesComandesvendes.Numero AND
      Articles.Codi = LiniesComandesvendes.Article AND 
      CapsaleraComandesvendes.Client = CapsaleraAgenda.Codi AND 
      --LiniesComandesvendes.Numero = OrdresFabricacio.comanda  
      LiniesComandesvendes.NumeroOrdre = OrdresFabricacio.NumeroOrdre AND
      LiniesComandesvendes.Numero>=2500000 AND 
      OrdresFabricacio.DataFabricacio Is Null AND
      ( Isnull(LiniesComandesvendes.QuantitatServida,0)<LiniesComandesvendes.Quantitat  OR Isnull(CapsaleraComandesvendes.facturada_sense_servir,0)=1  ) AND
      CapsaleraComandesvendes.finalitzada='N' AND
      CapsaleraComandesvendes.data>'1/1/2011' AND
      ( Articles.ReferenciaFabricant like 'CT%' or
       Articles.ReferenciaFabricant like 'CP%' or 
       Articles.ReferenciaFabricant like 'ST%' or 
       Articles.ReferenciaFabricant like 'F%' or 
       Articles.ReferenciaFabricant like 'OD%' or 
       Articles.ReferenciaFabricant like 'RH%' or 
       Articles.ReferenciaFabricant like 'CL%'  or 
       Articles.ReferenciaFabricant like 'XT%' or 
       Articles.ReferenciaFabricant like 'YT%' or 
       Articles.ReferenciaFabricant like 'AW%' or 
       Articles.ReferenciaFabricant like 'LR-[0-9]%' ) AND
      Isnull(Articles.tipusProducte,'') not in ('CP','RM','AL','TR','CO') AND
      Isnull(OrdresFabricacio.fabricacioExterna,0)<>1
 
group by LiniesComandesvendes.NumeroOrdre,''),CapsaleraComandesvendes.Client),CapsaleraComandesvendes.autoritzarFabricacio,clients.impagats,capsaleraComandesvendes.situacioRisc,OrdresFabricacio.DataEntrega,OrdresFabricacio.observacions,0)=1 THEN 'S' ELSE 'N' END,AgendaRepresentant.Nom,OrdresFabricacio.DataEntrega),1000),1000)

GO

这是不需要获得执行权限的功能之一。

ALTER function [dbo].[f_quantitatFabricadaLCV](@identificador integer) returns decimal(18,2) as
BEGIN

Declare @quantitatFabricada decimal(18,2)

    Select @quantitatFabricada=sum(PP2.quantitat) 
    from PartesProduccioComandes PP2 
         LEft outer join PartesProduccioOrdres PPO on PPO.Identificador=PP2.OrdreParte 
         Left outer join PartesProduccioCapsalera PPC on (PPC.Parte=PPO.Parte)  
    where PP2.idLiniaComanda=@identificador
             and PP2.seleccionat=1 and PPC.estat in ('F','Z') 
   
   return Isnull( @quantitatFabricada,0)         
END             

这是需要获得执行权限才能打开视图的函数示例之一。

ALTER FUNCTION [dbo].[f_consum_color_exterior]  ( @numeroOrdre integer) 
RETURNS varchar(10)
BEGIN 
  Declare @COL varchar(10)

            SELECT  top 1 
            @Col=Articles.color
            from OrdresFabricacioConsum
                 INNER JOIN ORDRESFabricacio on (OrdresFabricacioConsum.NumeroOrdre=ORDRESFAbricacio.numeroOrdre)                        
                 INNER JOIN Articles on (Articles.codi=OrdresFabricacioConsum.article)
                 INNER JOIN tipusBobines TB on (TB.tipusBobina=articles.tipusBobina)
            Where Isnull(articles.tipusBobina,'')<>'' and Articles.Codi<>'#PENDIENTE#'
                  and intExt='E' and OrdresFabricacioConsum.numeroOrdre=@NumeroOrdre and Isnull(Articles.gruix,0)<>0 and idLiniaComanda is null AND iSNULL(OrdresFabricacio.tipusOrdre,0)<>3
            order by OrdresFabricacioConsum.identificador   

  return @col                           
END

谢谢。

编辑:

现在我已经在 dbo 模式上创建了一个 dbExecutor 角色,因此视图可以执行任何功能。我不喜欢他们也可以执行任何存储过程,但至少被分配给他们似乎无法检索过程列表的架构。

create ROLE [db_executor]
GO

GRANT EXECUTE on SCHEMA::DBO TO db_executor
GO

解决方法

系统表all_objects 在主级别使用对系统对象的引用。这就是我认为的原因。

普通用户永远不要访问系统表!

这就是 SQL 标准 (la norme SQL) 强加 l'utilisation des vues INFORMATION_SCHEMA qui sont d'ordre "public" 的原因

En tout état de Cause,récrivez votre requête commesuit :

SELECT TABLE_SCHEMA AS OBJECT_SCHEMA,TABLE_NAME AS OBJECT_NAME,TABLE_TYPE AS OBJECT_TYPE
FROM   INFORMATION_SCHEMA.TABLES 
UNION ALL
SELECT ROUTINE_SCHEMA AS OBJECT_SCHEMA,ROUTINE_NAME AS OBJECT_NAME,ROUTINE_TYPE
FROM   INFORMATION_SCHEMA.ROUTINES