经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MS SQL Server » 查看文章
SQL Server执行sp_changeobjectowner遇到"Msg 15001, Level 16,..."错误探究
来源:cnblogs  作者:潇湘隐者  时间:2021/3/1 9:10:33  对本文有异议

在SQL Server中使用sp_changeobjectowner存储过程修改对象所有者(Owner)时,可能会遇到下面错误信息,当然对象klb.[k3]这个表确实是存在的。如下所示:

 

注意:个人测试环境为SQL Server 2014的标准版,如有不同情况,请以实际环境为准。

 

  1. USE AdventureWorks2014;
  1. GO
  1. EXEC sp_changeobjectowner 'klb.k3', 'dbo';
  1. GO

 

Msg 15001, Level 16, State 1, Procedure sp_changeobjectowner, Line 81

Object 'klb.[V_Test]' does not exist or is not a valid object for this operation.

 

 

clip_image001

 

 

当然你再次执行的话,可能会遇到同样的错误提示,但是Line的值有所变化,变成了99.  (这里是因为在脚本第二处抛出错误)

 

Msg 15001, Level 16, State 1, Procedure sp_changeobjectowner, Line 99

Object 'klb.[k3]' does not exist or is not a valid object for this operation.

 

 

我们获取sp_changeobjectowner存储过程的定义如下:

 

  1. SET QUOTED_IDENTIFIER ON
  1. SET ANSI_NULLS ON
  1. GO
  1. create procedure sys.sp_changeobjectowner
  1.     @objname    nvarchar(776),        -- may be "[owner].[object]"
  1.     @newowner    sysname                -- must be entry from sysusers
  1. as
  1.     Set nocount      on
  1.     Set ansi_padding on
  1.     declare    @objid        int,
  1.             @newuid        int,
  1.             @ret        int,
  1.             @oldowner    sysname,
  1.             @stmtS        nvarchar(4000)
  1.  
  1.     -- CHECK PERMISSIONS: Because changing owner changes both schema and
  1.     --    permissions, the caller must be one of:
  1.     -- (1) db_owner
  1.     -- (2) db_ddladmin AND db_securityadmin
  1.     if (is_member('db_owner') = 0) and
  1.         (is_member('db_securityadmin') = 0 OR is_member('db_ddladmin') = 0)
  1.     begin
  1.         EXEC %%System().AuditEvent(ID = 1094864724, Success = 0, TargetLoginName = NULL, TargetUserName = @newowner, Role = NULL, Object = @objname, Provider = NULL, Server = NULL)
  1.         raiserror(15247,-1,-1)
  1.         return (1)
  1.     end
  1.     else
  1.     begin
  1.         EXEC %%System().AuditEvent(ID = 1094864724, Success = 1, TargetLoginName = NULL, TargetUserName = @newowner, Role = NULL, Object = @objname, Provider = NULL, Server = NULL)
  1.     end
  1.  
  1.     if parsename(@objname, 1) is null
  1.     begin
  1.         raiserror(15253, -1, -1, @objname)
  1.         return (1)
  1.     end
  1.  
  1.     BEGIN TRANSACTION
  1.  
  1.     -- RESOLVE OBJECT NAME (CANNOT BE A CHILD OBJECT: TRIGGER/CONSTRAINT) --
  1.     select @objid = object_id(@objname, 'local')
  1.     if not (@objid is null)
  1.     begin
  1.         EXEC %%Object(MultiName = @objname).LockMatchID(ID = @objid, Exclusive = 1, BindInternal = 0)
  1.         if (@@error <> 0)    -- lock failed
  1.             select @objid = null
  1.     end
  1.     if (@objid is null) OR
  1.         (select parent_obj from sysobjects where id = @objid) <> 0 OR
  1.         ObjectProperty(@objid, 'IsSystemTable') = 1 OR
  1.         parsename(@objname, 3) is not null OR
  1.         parsename(@objname, 4) is not null OR
  1.         exists (select * from sys.objects where object_id = @objid and schema_id in (3,4))  OR -- INFORMATION_SCHEMA, sys
  1.         -- Check for Dependencies: No RENAME or CHANGEOWNER of OBJECT when exists:
  1.         EXISTS (SELECT * FROM sysdepends d WHERE
  1.             d.depid = @objid        -- A dependency on this object
  1.             AND d.deptype > 0        -- that is enforced
  1.             AND @objid <> d.id        -- that isn't a self-reference (self-references don't use object name)
  1.             AND @objid <>            -- And isn't a reference from a child object (also don't use object name)
  1.                 (SELECT o.parent_obj FROM sysobjects o WHERE o.id = d.id)
  1.             )
  1.     begin
  1.         -- OBJECT NOT FOUND
  1.         COMMIT TRANSACTION
  1.         raiserror(15001,-1,-1,@objname)
  1.         return 1
  1.     end
  1.  
  1.     -- object's schema name must be the same as the schema owner's name
  1.     if not exists (select so.name
  1.         from sys.objects so
  1.         join sys.schemas ss on so.schema_id = ss.schema_id
  1.         join sys.database_principals su on ss.principal_id = su.principal_id
  1.         where object_id = @objid and so.principal_id is null and ss.name = su.name)
  1.     begin
  1.         -- OBJECT NOT FOUND
  1.         COMMIT TRANSACTION
  1.         raiserror(15001,-1,-1,@objname)
  1.         return 1
  1.     end
  1.    
  1.     select @oldowner = ssch.name from sys.schemas ssch join sys.objects so on (so.schema_id = ssch.schema_id) where object_id = @objid
  1.     -- SHARE LOCK OLD SCHEMA, PREVENT DROP OF THE OWNER WHILE TXN ACTIVE --
  1.         -- (rollback could cause phantom owner) --
  1.     EXEC %%ObjectSchema (Name = @oldowner).Lock(Exclusive = 0) -- should succeed due to object lock above
  1.  
  1.     -- SHARE LOCK NEW SCHEMA --
  1.     EXEC %%ObjectSchema (Name = @newowner).Lock(Exclusive = 0) -- may fail, check below anyway
  1.  
  1.     -- RESOLVE NEW OWNER NAME (ATTEMPT ADDING IMPLICIT ROW FOR NT NAME) --
  1.     --  Disallow aliases, and public cannot own objects --
  1.     if @@error = 0 -- lock success, indicate new owner may exist, verify further
  1.         select @newuid = schema_id from sys.schemas where name = @newowner
  1.                             and schema_id not in (3,4) -- INFORMATION_SCHEMA, sys
  1.  
  1.     if @newuid is null -- indicate lock failed
  1.     begin
  1.         EXEC @ret = sys.sp_MSadduser_implicit_ntlogin @newowner
  1.         if (@ret = 0) -- success
  1.             select @newuid = schema_id from sys.schemas where name = @newowner
  1.             -- Member locked by sp_MSadduser_implicit_ntlogin
  1.     end
  1.  
  1.     if @newuid is null OR
  1.         -- the schema name and its owner name must be the same
  1.         not exists (select ss.name
  1.             from sys.schemas ss
  1.             join sys.database_principals su on ss.principal_id = su.principal_id
  1.             where ss.name = @newowner and ss.name = su.name)
  1.     begin
  1.         -- Implicit login added above is not rolled back
  1.         -- This is same as SQL 2000
  1.         COMMIT TRANSACTION
  1.         raiserror(15411, -1, -1, @newowner)
  1.         return (1)
  1.     end
  1.  
  1.     select @stmtS = 'ALTER SCHEMA '
  1.     select @stmtS = @stmtS + quotename(@newowner)
  1.     select @stmtS = @stmtS + ' TRANSFER '
  1.     if parsename(@objname, 2) is not null
  1.         select @stmtS = @stmtS + quotename(parsename(@objname, 2)) + '.'
  1.     select @stmtS = @stmtS + quotename(parsename(@objname, 1))
  1.  
  1.     exec (@stmtS)
  1.     IF @@ERROR <> 0
  1.     BEGIN
  1.         -- Nested transaction is used by alter schema statement
  1.         COMMIT TRANSACTION
  1.         return (1)
  1.     END
  1.  
  1.     COMMIT TRANSACTION
  1.     -- WARNING AFTER THE OWNER TRANSFER --
  1.     raiserror(15477,-1,-1)
  1.     return (0)    -- sp_changeobjectowner
  1.  
  1. GO

通过分析存储过程,我们发现在两个地方可能抛出Msg 15001的错误信息,如下所示

 

  1. if (@objid is null) OR
  1.     (select parent_obj from sysobjects where id = @objid) <> 0 OR
  1.     ObjectProperty(@objid, 'IsSystemTable') = 1 OR
  1.     parsename(@objname, 3) is not null OR
  1.     parsename(@objname, 4) is not null OR
  1.     exists (select * from sys.objects where object_id = @objid and schema_id in (3,4))  OR -- INFORMATION_SCHEMA, sys
  1.     -- Check for Dependencies: No RENAME or CHANGEOWNER of OBJECT when exists:
  1.     EXISTS (SELECT * FROM sysdepends d WHERE
  1.         d.depid = @objid        -- A dependency on this object
  1.         AND d.deptype > 0        -- that is enforced
  1.         AND @objid <> d.id        -- that isn't a self-reference (self-references don't use object name)
  1.         AND @objid <>            -- And isn't a reference from a child object (also don't use object name)
  1.             (SELECT o.parent_obj FROM sysobjects o WHERE o.id = d.id)
  1.         )
  1. begin
  1.     -- OBJECT NOT FOUND
  1.     COMMIT TRANSACTION
  1.     raiserror(15001,-1,-1,@objname)
  1.     return 1
  1. end

 

 

  1. -- object's schema name must be the same as the schema owner's name
  1. if not exists (select so.name
  1.     from sys.objects so
  1.     join sys.schemas ss on so.schema_id = ss.schema_id
  1.     join sys.database_principals su on ss.principal_id = su.principal_id
  1.     where object_id = @objid and so.principal_id is null and ss.name = su.name)
  1. begin
  1.     -- OBJECT NOT FOUND
  1.     COMMIT TRANSACTION
  1.     raiserror(15001,-1,-1,@objname)
  1.     return 1
  1. end

 

然后我们分析发现在第二个SQL会因为不满足条件,抛出错误信息,具体分析截图所示

 

clip_image002

 

其实从脚本的注释信息object's schema name must be the same as the schema owner's name我们已经知道,这个脚本有个逻辑,判断对象的schema name和schema owner's name是否一致,如果不一致的话,就会抛出错误信息。而这里遇到这个问题是因为我们下面脚本恰恰修改了klb这个schema的schema owner,所以才导致了这个错误出现。

 

  1. USE AdventureWorks2014;
  1. GO
  1. ALTER AUTHORIZATION ON SCHEMA::[klb]  TO [dbo];

 

 

clip_image003

 

这里将klb的schema owner修改回来,然后执行sp_changeobjectowner就会OK了。

 

  1. USE AdventureWorks2014;
  1. GO
  1. ALTER AUTHORIZATION ON SCHEMA::[klb]  TO [klb];
  1. GO
  1. USE AdventureWorks2014;
  1. GO
  1. EXEC sp_changeobjectowner 'klb.[k3]', 'dbo';
  1. GO

原文链接:http://www.cnblogs.com/kerrycode/p/14446167.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号