在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文档所描述的,系统存储过程的使用非常简单,如下所示

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';

如果存在对应表的同义词,那么使用系统存储过程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';

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

SQL Server修改数据库对象所有者(Owner)浅析的更多相关文章

  1. SQL Server 修改数据库

    1. 可视化界面修改数据库 (1)右击数据库,然后选择属性. (2)在工具选项卡中,选择[文件]页,可以更改所有者,文件大小,自增量等参数. 2.  使用ALTER Database修改数据库 (1) ...

  2. SQL SERVER 修改数据库名称(包括 db.mdf 名称的修改)

    刚开始学习SQL SERVER 2005,弄了一个上午修改数据库名,主要是需要修改db.mdf 和db_log.ldf的名字,总算解决了.在这里记下,以后再要修改了就别忘了. 假设原来数据库名为db, ...

  3. 通过SQL Server 2008数据库复制实现数据库同步备份

    SQL Server 2008数据库复制是通过发布/订阅的机制进行多台服务器之间的数据同步,我们把它用于数据库的同步备份.这里的同步备份指的是备份服务器与主服务器进行 实时数据同步,正常情况下只使用主 ...

  4. 【转】通过SQL Server 2008数据库复制实现数据库同步备份

    SQL Server 2008数据库复制是通过发布/订阅的机制进行多台服务器之间的数据同步,我们把它用于数据库的同步备份.这里的同步备份指的是备份服务器与主服务器进行实时数据同步,正常情况下只使用主数 ...

  5. SQLServer2008修改sa密码的方法与SQL server 2008数据库的备份与还原

    sa密码的修改转载自:http://blog.csdn.net/templar1000/article/details/20211191 SQL server 2008数据库的备份与还原转自 :htt ...

  6. SQL Server 2012 数据库笔记

    慕课网 首页 实战 路径 猿问 手记     Python 手记 \ SQL Server 2012 数据库笔记 SQL Server 2012 数据库笔记 2016-10-25 16:29:33 1 ...

  7. SQL Server中数据库文件的存放方式,文件和文件组

    原文地址:http://www.cnblogs.com/CareySon/archive/2011/12/26/2301597.html   SQL Server中数据库文件的存放方式,文件和文件组 ...

  8. C# VS2010结合SQL Server 2008数据库编程实现方法

    SQL Server 数据库在C#编程中经常用到,如何实现在具体项目中数据库和具体应用的结合是我们经常遇到的问题,我们这次主要针对如何使用SQL Server 数据库展开,下面是具体的操作以及简单的代 ...

  9. (5.1)sql server系统数据库

    关键词:mssql系统数据库,sql server系统数据库,tempdb的作用 master:它包含一个系统表集合,是整个实例的中央存储库,维护登录账户,其他数据库,文件分布,系统配置设置,磁盘空间 ...

随机推荐

  1. 1Z0-053 争议题目解析86

    1Z0-053 争议题目解析86 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 86.Your production database is running in archivel ...

  2. 初次体验百度eCharts遇到的问题和解决方法

    前言 上周在厌烦Highchart下,体验了下百度的eCharts,支持IE6.7.8+外,对数据在线编辑还有工具栏支持,体验时遇到了几个小问题,最近两天在尝试得到了一个解决方法. Tooltip时单 ...

  3. VS Code - Debugger for Chrome调试JavaScript的两种方式

    VS Code - Debugger for Chrome调试JavaScript的两种方式 最近由于出差的缘故,博客写的不是很多,一直想写一篇VS Code - Debugger for Chrom ...

  4. HTTP2特性预览和抓包分析

    背景 近年来,http网络请求量日益添加,以下是httparchive统计,从2012-11-01到2016-09-01的请求数量和传输大小的趋势图: 当前大部份客户端&服务端架构的应用程序, ...

  5. WCF学习系列三--【WCF Interview Questions – Part 3 翻译系列】

    http://www.topwcftutorials.net/2012/10/wcf-faqs-part3.html WCF Interview Questions – Part 3 This WCF ...

  6. Facebook Paper使用的第三方库

    Facebook Paper使用的第三方库 第三方库名 简介 链接 ACE code editor https://github.com/ajaxorg/ace Appirater 用户评分组件 ht ...

  7. 【开源】SoDiaoEditor 可能是目前最好用的开源电子病历编辑器(B/S架构)

    此刻我的内心是忐忑的,这个标题给了我很大的压力,虽然很久以前我就在github上搜索一圈了,也没发现有其他更好的开源电子病历编辑器,如各位亲发现有更好的,烦请知会我一声. 该编辑器其实已经憋了很久了, ...

  8. 背水一战 Windows 10 (14) - 动画: 线性动画, 关键帧动画

    [源码下载] 背水一战 Windows 10 (14) - 动画: 线性动画, 关键帧动画 作者:webabcd 介绍背水一战 Windows 10 之 动画 线性动画 - ColorAnimatio ...

  9. MySQL数据库中delimiter的作用概述

    以下的文章主要是向大家描述的是MySQL数据库中delimiter的作用是什么?我们一般都认为这个命令和存储过程关系不大,到底是不是这样的呢?以下的文章将会给你相关的知识,望你会有所收获. 其实就是告 ...

  10. perl use FileHandle;打开多个文件

    use FileHandle;my %fh; my @filehandlename=("A","B","C"); ##文件句柄的名字: fo ...