文档章节

SQL Server修改数据库对象所有者(Owner)浅析

o
 osc_pn11u1x9
发布于 2018/08/06 08:38
字数 1783
阅读 16
收藏 0
go

精选30+云产品,助力企业轻松上云!>>>

原文: SQL Server修改数据库对象所有者(Owner)浅析

在SQL Server数据库中如何修改数据库对象(表、视图、存储过程..)的所有者(Owner)呢?一般我们可以使用系统提供的系统存储过程sp_changeobjectowner来修改。 我们先看看sp_changeobjectowner在MSDN的文档介绍吧

更改当前数据库中对象的所有者。
 
 
 
 
重要提示:此存储过程只针对 Microsoft SQL Server 2000 中可用的对象进行。后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。另请使用 ALTER SCHEMA 或 ALTER AUTHORIZATION。sp_changeobjectowner 同时更改架构和所有者。若要保持与早期版本 SQL Server 的兼容性,如果当前所有者和新所有者拥有的架构名称与它们的数据库用户名相同,则此存储过程将只更改对象所有者。
 
 
 
 
Transact-SQL 语法约定
 
语法
 
sp_changeobjectowner [ @objname = ] 'object' , [ @newowner = ] 'owner'
参数
 
 
 
 
[ @objname = ] 'object'
 
当前数据库中现有表、视图、用户定义函数或存储过程的名称。object 是 nvarchar(776),没有默认值。如果架构及其所有者具有相同的名称,则 object 可由现有对象所有者限定,格式为 existing_owner.object。
 
[ @newowner=] 'owner '
 
将成为对象的新所有者的安全帐户的名称。owner 的数据类型为 sysname,没有默认值。owner 必须是可访问当前数据库的有效数据库用户、服务器角色、Microsoft Windows 登录名或 Windows 组。如果新所有者是没有对应数据库级主体的 Windows 用户或 Windows 组,则将创建数据库用户。
 
返回代码值
 
0(成功)或 1(失败)
 
注释
 
sp_changeobjectowner 删除对象中的所有现有权限。在运行 sp_changeobjectowner 之后,必须重新应用要保留的任何权限。因此,建议首先编写现有权限的脚本,然后再运行sp_changeobjectowner。更改了对象的所有权之后,便可使用该脚本重新应用权限。在运行该脚本之前必须在权限脚本中修改对象所有者。有关数据库脚本的详细信息,请参阅编写数据库文档和脚本。
 
若要更改安全对象的所有者,请使用 ALTER AUTHORIZATION.若要更改架构,请使用 ALTER SCHEMA。
 
权限
 
要求具有 db_owner 固定数据库角色的成员身份,或 db_ddladmin 固定数据库角色和 db_securityadmin 固定数据库角色的成员身份,同时还需要对对象具有 CONTROL 权限。
 

如上MSDN文档所描述的,系统存储过程的使用非常简单,如下所示

clipboard

use test;
 
go
 
exec sp_changeobjectowner '[db_owner].[T1]','dbo';
 

 

批量修改数据库对象的所有者(owner)

    执行上面存储过程过后,表对象T1的所有者(owner)就从db_owner改为了dbo了。如果一个数据库里面的表对象非常多,那么使用该方法就非常的繁琐了。此时就可以使用sp_MSforeachtable来批量处理该工作。

use test;
 
go
 
exec sp_MSforeachtable 'exec sp_changeobjectowner ''?'',''dbo'' '
 

但是使用sp_MSforeachtable结合系统存储过程sp_changeobjectowner,只能修改数据库里面所有表对象的所有者(owner)。并不能修改视图、存储过程、用户函数的所有者。那么应该如何批量修改存储过程、视图、用户自定义函数的所有者呢? 其实也很简单,自己写个脚本将所有SQL Script脚本生成就OK了

SELECT  'exec sp_changeobjectowner '''  + USER_NAME(uid) +'.' + name + ''', ''dbo'';'  
from sys.sysobjects where xtype in ('V','P','F')

网上有个脚本对数据库所有对象所有者进行批量修改,已经相当全面了,在此就不重复造轮子了。

declare tb cursor local for
 
select 'sp_changeobjectowner ''['+replace(user_name(uid),']',']]')+'].['
 
+replace(name,']',']]')+']'',''dbo'''
 
from sysobjects
 
where xtype in('U','V','P','TR','FN','IF','TF') and status>=0
 
open tb
 
declare @s nvarchar(4000)
 
fetch tb into @s
 
while @@fetch_status=0
 
begin
 
exec(@s)
 
fetch tb into @s
 
end
 
close tb
 
deallocate tb
 
go
 

 

使用sp_changeobjectowner需要注意的地方

    在使用系统函数sp_changeobjectowner时,你都会收到一条提示信息“注意: 更改对象名的任一部分都可能会破坏脚本和存储过程。”,这个是因为系统函数sp_changeobjectowner虽然会修改数据库对象的所有者,但是,在视图、存储过程、用户自定义函数里面,如果你使用了owner.object_name这种写法,系统函数并不能检测到。所以当数据库对象修改过后,就有可能导致部分视图、存储过程出现错误,不太明白上面描述的,可以通过下面的例子理解一下。

USE Test;
GO
 
CREATE TABLE [db_owner].T1
(
ID   INT ,
NAME VARCHAR(20)
);
 
CREATE VIEW [db_owner].V_T1
AS
  SELECT * FROM T1;
 
CREATE VIEW [db_owner].V_T2
AS
  SELECT * FROM db_owner.T1;
 
CREATE PROCEDURE PRC_TEST_ONE
AS
 SELECT * FROM T1;
 
GO
 
CREATE PROCEDURE PRC_TEST_TWO
AS
 SELECT * FROM db_owner.T1;
GO

修改了表T1的所有者后,视图[db_owner].V_T2、存储过程PRC_TEST_TWO都会报错。 如下截图所示。这也就是提示信息“注意: 更改对象名的任一部分都可能会破坏脚本和存储过程。”所描述的情况。

exec sp_changeobjectowner 'db_owner.T1', 'dbo';

clipboard[1]

如果存在对应表的同义词,那么使用系统存储过程sp_changeobjectowner修改对象的所有者是会报错的。

CREATE TABLE [db_owner].T1
(
ID   INT ,
NAME VARCHAR(20)
)
 
CREATE SYNONYM T1
FOR [db_owner].T1
GO
 
exec sp_changeobjectowner 'db_owner.T1', 'dbo';

clipboard[2]

 

sp_changeobjectowner这个系统存储过程的定义如下所示:

CREATE PROCEDURE Sp_changeobjectowner @objname  NVARCHAR(517),
                                      -- may be "[owner].[object]"
                                      @newowner SYSNAME
-- must be entry from sysusers
AS 
    SET nocount ON 
    SET ansi_padding ON 
 
    DECLARE @objid  INT,
            @newuid SMALLINT 
 
    -- CHECK PERMISSIONS: Because changing owner changes both schema and 
    --        permissions, the caller must be one of:
    -- (1) db_owner
    -- (2) db_ddladmin AND db_securityadmin
    IF ( Is_member('db_owner') = 0 )
       AND ( Is_member('db_securityadmin') = 0
              OR Is_member('db_ddladmin') = 0 )
      BEGIN 
          RAISERROR(15247,-1,-1)
 
          RETURN ( 1 )
      END 
 
    -- RESOLVE OBJECT NAME (CANNOT BE A CHILD OBJECT: TRIGGER/CONSTRAINT) --
    SELECT @objid = Object_id(@objname, 'local')
 
    IF ( @objid IS NULL )
        OR (SELECT parent_obj
            FROM   sysobjects
            WHERE  id = @objid) <> 0
        OR Objectproperty(@objid, 'IsMSShipped') = 1
        OR Objectproperty(@objid, 'IsSystemTable') = 1
        OR Objectproperty(@objid, 'ownerid') IN ( 0, 3, 4 )
        OR --public, INFORMATION_SCHEMA, system_function_schema
       -- Check for Dependencies: No RENAME or CHANGEOWNER of OBJECT when exists:
       EXISTS (SELECT *
               FROM   sysdepends d
               WHERE  d.depid = @objid -- A dependency on this object 
                      AND d.deptype > 0 -- that is enforced
                      AND @objid <> d.id
                      -- that isn't a self-reference (self-references don't use object name)
                      AND @objid <>
                          -- And isn't a reference from a child object (also don't use object name)
                          (SELECT o.parent_obj
                           FROM   sysobjects o
                           WHERE  o.id = d.id))
      BEGIN 
          -- OBJECT NOT FOUND 
          RAISERROR(15001,-1,-1,@objname)
 
          RETURN 1
      END 
 
    -- RESOLVE NEW OWNER NAME (ATTEMPT ADDING IMPLICIT ROW FOR NT NAME) --
    --  Disallow aliases, and public cannot own objects --
    SELECT @newuid = uid
    FROM   sysusers
    WHERE  NAME = @newowner
           AND isaliased = 0
           AND uid NOT IN ( 0, 3, 4 )
    --public, INFORMATION_SCHEMA, system_function_schema
 
    IF @newuid IS NULL 
      BEGIN 
          EXECUTE Sp_msadduser_implicit_ntlogin
            @newowner
 
          SELECT @newuid = uid
          FROM   sysusers
          WHERE  NAME = @newowner
                 AND isaliased = 0
                 AND NAME <> 'public' 
      END 
 
    IF @newuid IS NULL 
      BEGIN 
          RAISERROR(15410,-1,-1,@newowner)
 
          RETURN ( 1 )
      END 
 
    -- CHECK IF CHANGING OWNER OF OBJECT OR ITS CHILDREN WOULD PRODUCE A DUPLICATE
    IF EXISTS (SELECT *
               FROM   sysobjects
               WHERE  uid = @newuid
                      AND NAME IN (SELECT NAME
                                   FROM   sysobjects
                                   WHERE  id = @objid
                                           OR parent_obj = @objid))
      BEGIN 
          RAISERROR(15505,-1,-1,@objname,@newowner)
 
          RETURN ( 1 )
      END 
 
    -- DO THE OWNER TRANSFER (WITH A WARNING) --
    RAISERROR(15477,-1,-1)
 
    BEGIN TRANSACTION 
 
    -- Locks Object and increments schema_ver.
    DBCC lockobjectschema(@objname)
 
    -- drop permissions (they'll be incorrect with new owner) --
    DELETE syspermissions
    WHERE  id = @objid
 
    UPDATE sysobjects
    SET    uid = @newuid
    WHERE  id = @objid
 
    UPDATE sysobjects
    SET    uid = @newuid
    WHERE  parent_obj = @objid
 
    COMMIT TRANSACTION 
 
    RETURN 0 -- sp_changeobjectowner
 
go 

其他方式修改数据库对象的所有者

    使用ALTER SCHEMA修改数据库对象的所有者。如下所示:

    ALTER SCHEMA dbo TRANSFER db_owner.T1;

    GO

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
SQLServer修改表所有者

当用spadduser 对数据库进行添加用户之后.却出现了此对象 '表名' 无效的现象? 执行这个语句,就可以把当前库的所有表的所有者改为dbo exec spmsforeachtable 'spchangeobjectowner ''?'', ''d......

仰天一笑
2014/10/23
0
0
SQL2000中修改表的所有者

通过本地所设置的SQL帐号和密码登录SQL查询分析器,使用如下命令就可以很轻松地修改表的所有者, use 数据库 go EXEC sp_changeobjectowner ‘原表的所有者.表名’ , 现在的所有者 F5运行就可...

jackguo
2013/07/10
77
0
SQLServer更改用户定义的数据库角色

更改用户定义的数据库角色注意事项 需具有以下一项或多项权限或成员身份才能运行此命令: 对角色具有 ALTER 权限 对数据库具有 ALTER ANY ROLE 权限 具有 db_securityadmin 固定数据库角色的...

osc_sgs114rq
2019/01/03
0
0
SQL Server的命名规则

1.标识符 在SQL Server中,服务器、数据库和数据库对象(如表、视图、列、索引、触发器、过程、约束和规则等)都有标识符,数据库对象的名称被看成是该对象的标识符。大多数对象要求带有标识...

太阳笑了博客
2016/12/23
695
0
SQLServer之创建Transact-SQL DDL触发器

DDL触发器原理 DDL 触发器用于响应各种数据定义语言 (DDL) 事件。 这些事件主要与以关键字 CREATE、ALTER、DROP、GRANT、DENY、REVOKE 或 UPDATE STATISTICS 开头的 Transact-SQL 语句对应。...

osc_ocdr1dy6
2018/10/17
3
0

没有更多内容

加载失败,请刷新页面

加载更多

2020年中国数据存储容量最大单,杉岩数据中标2EB

【全球财经观察 | 新闻速递】这个是猛料!2020年中国数据存储容量第一单:2EB,被杉岩数据中标。具体为中标某省数据中心云存储资源池的2EB容量级分布式存储项目,由20万块磁盘打造的超级海量...

osc_n08oztl3
6分钟前
0
0
不看一下TOP20的云排名,你都不好意思说自己懂云

不看一下TOP20的云排名,你都不好意思说自己懂云 《2019年中国公有云厂商发展状况白皮书》 第二部分 2019年中国公有云厂商整体发展状况概述 既然TOP5排名、TOP10排名出现了新状况,那么2019年...

osc_p1q9onsn
8分钟前
0
0
maven标准settings文件【转载】

<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://......

LifeCode520
9分钟前
0
0
使用 export timeout = -1来免除ssh时间过长被强制下线的困扰

长时间连接ssh没有操作,可能会被强制下线,这时候,我们使用以下命令就可以免除次困扰: export timeout = -1,便不再会被强制下线了。 有的人写攻略说要写入conf配置文件里,这样确实不用每...

osc_sb30h1xb
9分钟前
0
0
实用性网站大全

本文阅读仅需三分钟,希望这篇帖子对您有帮助 大多数人不是一开始就是大神、大牛的,都是从菜鸟阶段过来的,所以咱们得沉得住气,低调沉稳的打磨,因为我很赞同郭德纲的那句话:没成功之前,...

osc_cdixgndu
11分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部