对象不存在或使用'sp_changeobjectowner'无效

时间:2011-09-22 18:51:11

标签: sql sql-server sql-server-2008

我使用下面的SQL语句(SQL 2008 R2)将表模式从dbo更改为db_owner:

DECLARE @old sysname, @new sysname, @sql varchar(1000)

SELECT
  @old = 'db_owner'
  , @new = 'dbo'
  , @sql = '
  IF EXISTS (SELECT NULL FROM INFORMATION_SCHEMA.TABLES
  WHERE
      QUOTENAME(TABLE_SCHEMA)+''.''+QUOTENAME(TABLE_NAME) = ''?''
      AND TABLE_SCHEMA = ''' + @old + '''
  )
  EXECUTE sp_changeobjectowner ''?'', ''' + @new + ''''

EXECUTE sp_MSforeachtable @sql

我需要通过切换旧名称和新名称来更改它,但是我收到错误:

  

Msg 15001,Level 16,State 1,Procedure sp_changeobjectowner,第75行   对象'[db_owner]。[language_link]'不存在或无效   此操作的对象。

该表确实存在,甚至使用旧的db_owner。有什么方法可以解决这个问题吗?

这是一个关于如何告诉它仍然由db_owner拥有的屏幕截图。只有一些表格被正确移回:

enter image description here

1 个答案:

答案 0 :(得分:1)

您确定要使用sp_changeobjectowner吗? (从SQL 2005开始,对象实际上不再拥有所有者。)您是如何验证db_owner.language_link存在的?就个人而言,我会使用ALTER SCHEMA,我也倾向于目录视图(sys.tables)而不是information_schema.tables。最后,我不会使用未记录和不受支持的sp_MSforeachtable - 我已经强调了sp_MSforeachdb的问题,这些问题可能是潜在问题,因为代码非常相似。

DECLARE
    @old SYSNAME = N'db_owner',
    @new SYSNAME = N'dbo',
    @sql NVARCHAR(MAX) = N'';

SELECT @sql += CHAR(13) + CHAR(10) + 'ALTER SCHEMA ' + @new 
    + ' TRANSFER ' + QUOTENAME(SCHEMA_NAME([schema_id]))
    + '.' + QUOTENAME(name) + ';'
    FROM sys.tables AS t
    WHERE SCHEMA_NAME([schema_id]) = @old
    AND NOT EXISTS (SELECT 1 FROM sys.tables WHERE name = t.name
    AND SCHEMA_NAME([schema_id]) = @new);

PRINT @sql;
--EXEC sp_executesql @sql;

编辑添加代码以查找两个模式共有的对象。并将已经在新架构中的那些移动到一些虚拟架构:

CREATE SCHEMA dummy AUTHORIZATION dbo;
GO
DECLARE 
    @old SYSNAME = N'db_owner',
    @new SYSNAME = N'dbo',
    @sql NVARCHAR(MAX) = N'';

SELECT @sql += CHAR(13) + CHAR(10) + 'ALTER SCHEMA dummy TRANSFER '
    + QUOTENAME(@new) + '.' + QUOTENAME(t1.name) + ';'
    FROM sys.tables AS t1
    INNER JOIN sys.tables AS t2
    ON t1.name = t2.name
    WHERE t1.schema_id = SCHEMA_ID(@new)
    AND t2.schema_id = SCHEMA_ID(@old);

PRINT @sql;
-- EXEC sp_executesql @sql;

但实际上它听起来像是搞砸了,需要手动清理......

编辑添加证据,因为OP似乎确信此代码无效,因为无法将内容移入dbo架构。不,不是这样,只是不可能移动dummy.floob - > dbo.floob如果已经有一个名为dbo.floob的对象。请注意,可能不是表格!

CREATE DATABASE schema_test;
GO
USE schema_test;
GO
CREATE SCHEMA floob AUTHORIZATION dbo;
GO
CREATE TABLE dbo.x(a INT);
CREATE TABLE dbo.y(a INT);
GO

从dbo移动所有表格 - > floob:

DECLARE
    @old SYSNAME = N'dbo',
    @new SYSNAME = N'floob',
    @sql NVARCHAR(MAX) = N'';

SELECT @sql += CHAR(13) + CHAR(10) + 'ALTER SCHEMA ' + @new 
    + ' TRANSFER ' + QUOTENAME(SCHEMA_NAME([schema_id]))
    + '.' + QUOTENAME(name) + ';'
    FROM sys.tables AS t
    WHERE SCHEMA_NAME([schema_id]) = @old
    AND NOT EXISTS (SELECT 1 FROM sys.tables WHERE name = t.name
    AND SCHEMA_NAME([schema_id]) = @new);

EXEC sp_executesql @sql;
GO
SELECT SCHEMA_NAME([schema_id]),name FROM sys.tables;

结果:

enter image description here

将所有表格从floob移回 - > DBO:

DECLARE
    @old SYSNAME = N'floob',
    @new SYSNAME = N'dbo',
    @sql NVARCHAR(MAX) = N'';

SELECT @sql += CHAR(13) + CHAR(10) + 'ALTER SCHEMA ' + @new 
    + ' TRANSFER ' + QUOTENAME(SCHEMA_NAME([schema_id]))
    + '.' + QUOTENAME(name) + ';'
    FROM sys.tables AS t
    WHERE SCHEMA_NAME([schema_id]) = @old
    AND NOT EXISTS (SELECT 1 FROM sys.tables WHERE name = t.name
    AND SCHEMA_NAME([schema_id]) = @new);

EXEC sp_executesql @sql;
GO
SELECT SCHEMA_NAME([schema_id]),name FROM sys.tables;

结果:

enter image description here