症 状:当一个非sysadmin 固定服务器角色成员(非DBA用户),在查询分析器或程序中(asp,vb等),新建一个数据库对象时,数据库对象的所有者为当前的登录的用户。如果程序下一次更改为以DBA身份或者其它身份运行时,就会提示找不到该数据库对象。
例如: 如果用户Andrew 不是固定服务器角色 sysadmin 的成员,而只是固定数据库角色 db_owner 的成员,并创建表 T1,则 T1 属于 Andrew,并限定为 Andrew.T1。其它用户在查询分析器或程序中用SQL语句访问该表时需要在表前面加上所有者:
select * from Andrew.T1
而不能直接
select * from T1
不然会提示找不了表对象。
(另注:用企业管理器或者查询分析中的左边列表中访问就不需要加所有者名,因为图形操作直接加进去了)
原 因:因为Andrew用户不是固定服务器角色 sysadmin 的成员时,他建的表T1就不是dbo所拥有,其他用户要操作该用户所创建的表T1时,就必须指定T1表的所有者名称。例如:Andrew.T1
解决方法:
一、只要建的表是dbo所有的,就不需要加表的所有者名。
新建表时指定dbo 所有者方法:
1、用固定服务器角色 sysadmin 的成员(例:sa)登陆建立表。
2、在企业管理器里用本地windows认证登陆建立表。企业管理器对新建一个表时,已经默认为dbo
3、其它用户登陆时创建表时用
create table dbo.good(
)
在表前面加dbo来创建。
二、只要是表的所有者操作表也不用在表前面加所有者名。
三、解决孤立用户的方法也能解决。
四、改变表的所有者为dbo。
一些参考资源内容:
DBO是每个数据库的默认用户,具有所有者权限,即DbOwner
通过用DBO作为所有者来定义对象,能够使数据库中的任何用户引用而不必提供所有者名称。
比如:你以User1登录进去并建表Table,而未指定DBO,
当用户User2登进去想访问Table时就得知道这个Table是你User1建立的,要写上User1.Table,如果他不知道是你建的,则访问会有问题。
如果你建表时把所有者指给了Dbo,则别的用户进来时写上Dbo.Table就行了,不必知道User1。
不光表是如此,视图等等数据库对象建立时也要如此才算是好。
建表、存储过程、视图等数据库对象时,其对应的所有者是创建它的用户。则除了该用户其他登录用户要引用这些东东时,都要加上前缀,很是麻烦。而且,程序因此易出错,你查来查去问题确出谡猓 朔涯闶奔洹?
数据库对象:表,视图,存储过程等、
症 状:当一个非sysadmin 固定服务器角色成员(非DBA用户),在查询分析器或程序中(asp,vb等),新建一个数据库对象时,数据库对象的所有者为当前的登录的用户。如果程序下一次更改为以DBA身份或者其它身份运行时,就会提示找不到该数据库对象。
原 因:如果当前用户不是所有者,则当前用户使用过程时必须指定所有者名称,如果当前用户或 dbo 拥有该对象,则不需要所有者名称
解决方案:
1. 采用指定拥有者的对象 eg: EXECUTE user1.proc1
2. 更改数据库对象的所有者
命令:EXEC sp_changeobjectowner ’object_name’, ’ owner’
知识点:
数据库对象的命名规则如下所示:
[[[server_name.][database_name].][owner_name].]object_name
database_name 的默认值是当前数据库;owner_name 的默认值是当前用户。如果当前用户不是所有者,则当前用户使用过程时必须指定所有者名称。因为所有者名称是对象名称的一部分,所以两个不同的用户可以在相同的数据库中拥有对象名称相同的过程(例如 user1.proc1 和 user2.proc1)。
{该命名规则的唯一例外是系统过程,这些过程可以从任何数据库执行。系统过程驻留于 master 数据库,由系统管理员所有,其名称以 sp_ 打头。系统过程引用当前数据库的系统表}
对于由数据库的许多用户使用的过程,由 dbo创建该过程是最方便的。这使得所有用户都可以在不指定所有者名称的情况下找到该过程。
如果过程不在执行它的数据库中,则可以通过使用数据库名称完全限定过程名称来避免该错误,如下例所示:
EXECUTE database_1.user1.proc1
如果您或 dbo拥有该过程,则不需要所有者名称。例如:
EXECUTE database_1..proc1
建议: 在程序中或查询分析器中以非DBA身份登录数据库时,创建一个数据库对象时,请指定数据库对象所有者为:dbo (在SQL企业管理器中无需设定,企业管理器对新建一个表时,已经默认为dbo) 。
Eg: CREATE TABLE [dbo].[11111111111111] (
[Name] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[Password] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[Email] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[Dept] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,
)
GO
以下是CREATED TABLE时的说明(摘自SQL ONLINE HELP):
owner 默认为与 database_name 所指定的数据库中的当前连接相关联的用户 ID。如果 CREATE TABLE 语句由 sysadmin 固定服务器角色成员或 database_name 所指定的数据库中的 db_dbowner 或 db_ddladmin 固定数据库角色成员执行,则 owner 可以指定与当前连接的登录相关联的用户 ID 以外的其它用户 ID。如果与执行 CREATE TABLE 语句的登录相关联的用户 ID 仅具有创建表的权限,则 owner 必须指定与当前登录相关联的用户 ID。sysadmin 固定服务器角色成员或别名为 dbo 用户的登录与用户 ID dbo 相关联;因此,由这些用户创建的表的默认所有者为 dbo。不是由上述两种角色的登录创建的表所有者默认为与该登录相关联的用户 ID。
dbo 是具有在数据库中执行所有活动的暗示性权限的用户。将固定服务器角色 sysadmin 的任何成员都映射到每个数据库内称为 dbo 的一个特殊用户上。另外,由固定服务器角色 sysadmin 的任何成员创建的任何对象都自动属于 dbo。
例如,如果用户 Andrew 是固定服务器角色 sysadmin 的成员,并创建表 T1,则表 T1 属于 dbo,并以 dbo.T1 而不是 Andrew.T1 进行限定。相反,如果 Andrew 不是固定服务器角色 sysadmin 的成员,而只是固定数据库角色 db_owner 的成员,并创建表 T1,则 T1 属于 Andrew,并限定为 Andrew.T1。该表属于 Andrew,因为该成员没有将表限定为 dbo.T1。
无法删除 dbo 用户,且此用户始终出现在每个数据库中。
只有由 sysadmin 固定服务器角色成员(或 dbo 用户)创建的对象才属于 dbo。由任何其他也不是 syadmin 固定服务器角色成员的用户(包括 db_owner 固定数据库角色成员)创建的对象:
属于创建该对象的用户,而不是 dbo。
用创建该对象的用户名限定。
怎么样把sql server 2000的用户表的所有者,改成dbo,而不是用户名
exec sp_changeobjectowner '[bbsdb].[dv_style]',[dbo]
更改当前数据库中对象的所有者
备份、恢复数据库时,往往会出现所有者是原来的用户,这样当你在新的系统中使用
时,会出现表名无效的错误提示,而加入原来的用户名,又会出现用户已经存在的错误,
所以最好的方法就是修改成dbo:
怎么样把sql server 2000的用户表的所有者,改成dbo,而不是用户名。
(附修改存储过程的方法,在查询器中执行:
EXEC sp_changeobjectowner 'usera.hishop_creatorder', 'dbo'),就把 usera的存储过程改为dbo所有了。
可以使用 sp_changedbowner 更改数据库的所有者。
方法一:右键点击该表-》设计表,在上面的一排小图标中,点最后一个“条件约束”,点“表”页,在里面更改所有者。(若没有条件约束的小图标,可以点右键,能看到一个“check约束”的选项)
方法二:利用脚本直接执行,用系统帐号或者超户登陆到该数据库,然后执行下面语句:
sp_configure 'allow updates','1'
go
reconfigure with override
go
update sysobjects set uid=1 where uid<>1
go
sp_configure 'allow updates','0'
go
reconfigure with override
/*批量替换
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
*/