none
为什么一个数据库表在SQL Server中存在,却会返回“无效的对象名称”和“对该对象的操作没有权限”的错误? RRS feed

  • 问题

  • 假设在一个数据库CheckpointTest中有两个用户:UserA是db_owner,默认架构是dbo; UserB是拥有创建表的权限,默认架构是Marketing。
    2011年9月19日 5:02
    版主

答案

  • 情况一:用户UserB通过下面的语句新建了一个数据库表:
    Create TABLE Tb1(id1 INT) 

    当UserA通过下面的语句去查询这个表格:
    select * from Tb1 

    结果发现查询分析报出以下错误:

    Msg 208, Level 16, State 1, Line 1
    Invalid object name 'Tb1'.

    这个错误信息提示,当前数据库中不存在'Tb1'这个对象。而当UserB去执行同样的SELECT语句,却能成功运行。为什么UserA查询去UserB创建的表'Tb1'会发生对象不存的错误?

    在SQL Server中,当一个用户去创建一个对象时,没有指定对象的架构,那么数据库会自动地把当前用户的默认架构作为新建对象的架构。结合上面的情况,UserB创建的表Tb1的架构是Marketing。也就是说,它的完整名称应该是’Marketing. Tb1’。而如果用户只使用对象名去查询这个表,数据库首先会从当前用户默认架构下去查找这个对象。如果不存在,数据库会从’dbo’架构下去查找这个对象。对UserB而言,它查询的是’Marketing.Tb1’,而对UserA而言,它查询的始终是’dbo.Tb1’,虽然它对’Marketing.Tb1’有查询权限。很明显,刚才创建的表是’Marketing.Tb1’,所以UserA查询的时候,数据库找不到’dbo.Tb1’这个对象,所以提示’dbo.Tb1’这个对象是非法的。

    解决方法这个问题的方法是使用完整的对象名称’架构名称.对象名称’。UserA可执行下面的语句查询这个表格:

    select * from Marketing.Tb1 




    2011年9月19日 5:04
    版主
  • 情况二:用户UserA通过以下语句新建了一个数据库表:

    Create TABLE Tb2(id2 INT)
    

    用户UserB通过下面的SELECT语句去查询这个表格:

    select * from Tb2
    
    

    查询分析器报出以下错误:
    Msg 229, Level 14, State 5, Line 1
    The SELECT permission was denied on the object 'Tb1', database 'CheckpointTest', schema 'dbo'.

    这个错误信息提示的是,当前用户UserB没有权限对数据库'CheckpointTest‘中,架构'dbo’下的数据库表'Tb1'执行SELECT.根据第一中情况,我们知道,UserA创建的表对象的完整名称'dbo.Tb2’。当UserB去查询的时候,数据库首先会根据当前用户的默认架构去查找'Marketing.Tb2’这个对象,结构发现这个对象不存在,而在另个一个架构('dbo’)下面找到了'Tb2’这个表名,所以最后返回的是'dbo.Tb2’这个对象。但是UserB在这个数据库中只有创建表的权限,它的SELECT权限只针对它默认架构的对象,而对其他架构下的对象没有任何操作权限。因此就出现了以上的错误信息。
    解决这个问题的方法是将架构对'dbo’的查询权限赋给用户UserA:

    GRANT SELECT ON SCHEMA :: dbo TO UserB WITH GRANT OPTION;
    
    


    在数据库的使用中,对象的创建和引用的时候指定完整的对象名,正确使用架构以及分配用户权限,可以避免以上一些类似的错误。

    参考:http://www.sqlservercentral.com/articles/Advanced/understandingobjectownership/1966/

    2011年9月19日 5:07
    版主

全部回复

  • 情况一:用户UserB通过下面的语句新建了一个数据库表:
    Create TABLE Tb1(id1 INT) 

    当UserA通过下面的语句去查询这个表格:
    select * from Tb1 

    结果发现查询分析报出以下错误:

    Msg 208, Level 16, State 1, Line 1
    Invalid object name 'Tb1'.

    这个错误信息提示,当前数据库中不存在'Tb1'这个对象。而当UserB去执行同样的SELECT语句,却能成功运行。为什么UserA查询去UserB创建的表'Tb1'会发生对象不存的错误?

    在SQL Server中,当一个用户去创建一个对象时,没有指定对象的架构,那么数据库会自动地把当前用户的默认架构作为新建对象的架构。结合上面的情况,UserB创建的表Tb1的架构是Marketing。也就是说,它的完整名称应该是’Marketing. Tb1’。而如果用户只使用对象名去查询这个表,数据库首先会从当前用户默认架构下去查找这个对象。如果不存在,数据库会从’dbo’架构下去查找这个对象。对UserB而言,它查询的是’Marketing.Tb1’,而对UserA而言,它查询的始终是’dbo.Tb1’,虽然它对’Marketing.Tb1’有查询权限。很明显,刚才创建的表是’Marketing.Tb1’,所以UserA查询的时候,数据库找不到’dbo.Tb1’这个对象,所以提示’dbo.Tb1’这个对象是非法的。

    解决方法这个问题的方法是使用完整的对象名称’架构名称.对象名称’。UserA可执行下面的语句查询这个表格:

    select * from Marketing.Tb1 




    2011年9月19日 5:04
    版主
  • 情况二:用户UserA通过以下语句新建了一个数据库表:

    Create TABLE Tb2(id2 INT)
    

    用户UserB通过下面的SELECT语句去查询这个表格:

    select * from Tb2
    
    

    查询分析器报出以下错误:
    Msg 229, Level 14, State 5, Line 1
    The SELECT permission was denied on the object 'Tb1', database 'CheckpointTest', schema 'dbo'.

    这个错误信息提示的是,当前用户UserB没有权限对数据库'CheckpointTest‘中,架构'dbo’下的数据库表'Tb1'执行SELECT.根据第一中情况,我们知道,UserA创建的表对象的完整名称'dbo.Tb2’。当UserB去查询的时候,数据库首先会根据当前用户的默认架构去查找'Marketing.Tb2’这个对象,结构发现这个对象不存在,而在另个一个架构('dbo’)下面找到了'Tb2’这个表名,所以最后返回的是'dbo.Tb2’这个对象。但是UserB在这个数据库中只有创建表的权限,它的SELECT权限只针对它默认架构的对象,而对其他架构下的对象没有任何操作权限。因此就出现了以上的错误信息。
    解决这个问题的方法是将架构对'dbo’的查询权限赋给用户UserA:

    GRANT SELECT ON SCHEMA :: dbo TO UserB WITH GRANT OPTION;
    
    


    在数据库的使用中,对象的创建和引用的时候指定完整的对象名,正确使用架构以及分配用户权限,可以避免以上一些类似的错误。

    参考:http://www.sqlservercentral.com/articles/Advanced/understandingobjectownership/1966/

    2011年9月19日 5:07
    版主