问个奇怪的问题:master数据库中sysobjects的内容中也存储着它自己的结构吗?

blue_morning 2013-03-08 06:06:19
通常情况下,我们通过查询SQL Server的Meta表:sysobjects,sys.columns 等来了解我们自己的数据库结构或解决一些特殊的问题。

但sysobject本身也存储着它的结构吗?如果不是它存储在哪呢?(第一个问题)

例如在SQLServer2005中进行如下查询:
select * from sysobjects where name = 'sysobjects'
select * from sys.columns where object_id = -105

第一个查询可以返回结果,-105是我电脑上的sysobjects id值,但第二个查询不会返回任何数据(通常情况下,经应该返回表的字段结构)。

----------------------------------------------------------------------

我为什么会这么问?

因为我写的程序中想使用Meta来做一些事,比如我建立一个与sys.columns类似的表(SysColumnsMapping),把sys.columns的内容同步过来,再加上一些其它的字段:ChinaName,DispalyFormatStr等等。

ChinaName字段名可以用在用户Post数据前,根据它的is_nullable判断用户是否填写,并调用ChinaName中的内容自动化提示用户哪个数据没有填写。

DisplayFormatStr可以让这个字段在不同控件显示时自动的定义它会如何显示,而不需要我在每一个具体的控件上去设置。这些工作在WinForm程序中合理使用Meta可以实现自动化,省去很多硬编码。

事实上,我要做的事远不止加上ChinaName,DispalyFormatStr这两个字段那么简单,比如:我可以用SysColumnsMapping中扩展出来的定义,通过选择字段直接生成一个ASP.NET的GridView控件的HTML代码或是某个Form文件中控件的文本代码。

但是:我在编写时发现二个很困惑我的东西,因SysColumnsMapping这个表也存储着SysColumnsMapping的字段结构,在实际编写中,一是SysColumnsMapping表结构因需求修改,改动就是底朝天。二、这种结构方式是合理的吗?因为它看起来更像先有鸡还是蛋的问题,或是一只鸡和蛋在这个世界上同时出现了。

SysColumnsMapping 这种自身包容的结构,我的设计对吗?(第二个问题)这也是我要去搞清为什么sysobject本身也存储着它的结构。

感谢你看完我这个太长的问题。



...全文
521 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
blue_morning 2013-03-17
  • 打赏
  • 举报
回复
昨天仔细的再想了一遍这个问题,其实是否自包含并不是关键。 系统基表中更定有一个表SysColunm存储着所有用户表的字段结构,而我们所有对用户表字段结构的修改都是通过标准SQL(这也是Profiler只能跟踪到的东西)再交由SQLServer的内部引擎去操作SysColunm。 SysColumn表中如果存储着它的字段结构,那么这些数据也是不会让用户修改的,否则就得到上面的推断:修改它的数据内容,就会变更它自身的字段结构。这明显不合理。 而最合理的方法:就是在SysColumn中不要去存储它自身的字段结构数据。 这些想法,来自和你们的讨论交流。当然Vidor简单轻率的回答也刺激了我不断的深入思考这个问题。 DBA_Huangzj:我喜欢你严谨的态度,虽然对我没有什么帮助还是非常感谢你。
blue_morning 2013-03-15
  • 打赏
  • 举报
回复
确实我无法在SQLServer2005上看到基表的内容或结构,使用DAC连接也不行。我觉得这个问题只能保留争议了。 另外两位:我知道那是个视图,但这不是问题的关键对吗?难道要去讨论这个视图中到底哪个表是关键表,然后从这个表开始讨论它是否自包含吗?而事实上,我们都可能不知道关键表是哪个。 特别的 Vidor: 一、我使用SysColunmMapping表,按我的需求扩展对字段结构元数据的定义、并从sys.columns中复制字段结构数据过来,这样就不可避免SysColunmMapping向sys.columns同步字段结构数据的问题(而且我还需要保证我在SysColunmMapping中存储的数据受sys.columns变化的影响最小),这是为什么上面提及object_id和colunm_id会变化的根本原因。因为我得用某个字段来求这两个表的交,并,差集并尽可能的减少同步带来的影响。当然,如果你觉得用Name字段完全可以胜任,那么你就不用向下看了。 二、插入一个非空字段是指: 表A(F1(int, pk), F3(int null),F4(int null) 的结构改为 表A(F1(int, pk), F2(int not null), F3(int null),F4(int null) 我像这样搞下去,好像是要去争论如何搞一个元数据同步问题了。让我们回到正题: Vidor你要是觉得通过DAC,Profiler等各种你简单一句话就能好像能解决问题的方法来说明: SQLServer2005中存在着一个MagicTable:它保存着其它表的字段结构,也保存着自己的字段结构(简称自包含),也就是意味着修改它的数据内容,就会变更它的字段结构(这正是让我头痛无比的地方)。那么请证明给我看。 用你强大的技术力量把我轰成渣吧。
Vidor 2013-03-13
  • 打赏
  • 举报
回复
sys.sysobjects是一个视图,就一条语句包含什么,什么都不包含,数据来自系统表的。
Vidor 2013-03-13
  • 打赏
  • 举报
回复
代码框架我还是做过的,就不知道是不是你现在要想实现的功能。 插入一个非空字段:没听说过有这功能,只能append一个字段,追踪下MS界面设计器是如何插入一个字段的,或许能解释为什么object_id和column_id会面目全非。 MS没有任何建议说开发中不要使用元数据,明确指出属内部使用的除外。兼容视图在未来的N个版本MS都不会删除,因为还有大量基于兼容性视图开发的程序在跑。 至于基表是否自包含,无需猜测,DAC连接就可以查证。
blue_morning 2013-03-13
  • 打赏
  • 举报
回复
DBA_Huangzj:sys.sysobjects包含自身结构。这个怎么证明?
blue_morning 2013-03-13
  • 打赏
  • 举报
回复
谢谢两位:如果是自包含,那么开发的代价是很大的。 Vidor:为什么要有SysColunmMapping是因为SQLServer2005的系统视图中,object_id和colunm_id不是生成后就固定不变,如果你尝试过做这事你就知道。而我要做的是扩展Meta表的字段结构,所以需要SysColunmMapping 如果你没有做过,那么你建一个表,查看它的字段结构。再向表插入一个非空字段保存后再查看后就能发现objtct_id和colunm_id已经面目全非。也许SQLServer设计时就没有考虑过用户使用元数据来开发。如果基表自包含,那么他处理用户表和基表的逻辑应该相同,但我使用下来我感觉完全不同(如本段这个简单的例子),所以我推测基表不会自包含。
發糞塗牆 2013-03-13
  • 打赏
  • 举报
回复
还是那句,sysobjects其实是一个视图,真正的数据在底层无法看到的表上。所以你也可以认为它不包含。
Vidor 2013-03-11
  • 打赏
  • 举报
回复
sys.sysobjects肯定是自包含的,基表也是自包含的,尽管基表一般情况下不可见。 sys.columns不返回系统级的信息,sysobjects不是用户定义的,所以不可见: select * from sys.system_columns where object_id = -105 select * from sys.all_columns where object_id = -105 我不明白是为什么要SysColumnsMapping,而且是同步syscolumns的数据,看你的描述是开发类似代码生成器的东西,在系统视图的基础上定义自己的视图就是了。
發糞塗牆 2013-03-11
  • 打赏
  • 举报
回复
比较准确的回答(不过我知道不是你想要的):sys.sysobjects包含自身结构,但是你并不能看到,因为在别的表里面
blue_morning 2013-03-09
  • 打赏
  • 举报
回复
感谢你的回复,因为本来我觉得我这个问题可能没有人回复的,因为它问得太偏了。 当然,我也没有完全看懂你回复我的SQL。但我想把问题简化下: 你觉得sys.sysobjects会是一个自包含的结构吗?就像我问题中的SysColumnsMapping表一样?
發糞塗牆 2013-03-08
  • 打赏
  • 举报
回复
系统视图、目录视图、兼容性视图这些一开始的设计原因主要是给SQLServer或者DBA用于管理使用,而不是开发程序的时候用的,微软建议如果有开发需要,可以使用information视图。但是不知道能不能满足你的要求。
發糞塗牆 2013-03-08
  • 打赏
  • 举报
回复
你应该有留意第一个查询中的xtype,是V,而不是S(也就是系统表),从2005以后,这些在2000被成为系统表的“表”其实是系统视图,而它们是引用一些你无法访问的表,所以自然id=-105的也不会查得出来。下面是sysobjects的源代码:
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE VIEW sys.sysobjects AS
 SELECT name, id,
 xtype = type collate database_default,
 uid = convert(smallint, nsid),
 info = convert(smallint, 0),
 status = convert(int, 0),
 base_schema_ver = convert(int, 0),
 replinfo = convert(int, 0),
 parent_obj = pid,
 crdate = created,
 ftcatid = convert(smallint, case type
  when 'U' then OBJECTPROPERTY(id, 'TableFulltextCatalogId')
  else 0 end),
 schema_ver = convert(int, 0),
 stats_schema_ver = convert(int, 0),
 type = convert(char(2), case type
  when 'UQ' then 'K' when 'PK' then 'K'
  else type collate database_default end),
 userstat = convert(smallint, case type when 'S' then 1 when 'U' then 1 else 0 end),
 sysstat = convert(smallint, case type
  when 'S' then 1 when 'V' then 2 when 'U' then 3 when 'P' then 4 when 'RF' then 4
  when 'X' then 4 when 'D' then 6 when 'R' then 7 when 'TR' then 8
  when 'PK' then 9 when 'UQ' then 9 when 'C' then 10 when 'F' then 11
  else 0 end),
 indexdel = convert(smallint, 0),
 refdate = created,
 version = convert(int, 0),
 deltrig = convert(int, case type
  when 'U' then OBJECTPROPERTY(id,'TableDeleteTrigger')
  when 'TR' then pid else 0 end),
 instrig = convert(int, case type
  when 'U' then OBJECTPROPERTY(id,'TableInsertTrigger')
  else 0 end),
 updtrig = convert(int, case type
  when 'U' then OBJECTPROPERTY(id,'TableUpdateTrigger')
  else 0 end),
 seltrig = convert(int, 0),
 category = convert(int, case when type = 'D' and pid <> 0 then 2048 else 0 end
  + case when type = 'P' and (status & 256) <> 0 then 16 else 0 end
  + (status & 1)*2 + (status & 16)*2),
 cache = convert(smallint, 0)
 FROM sys.sysschobjs
 WHERE nsclass = 0 AND pclass = 1 AND has_access('CO', id) = 1
 UNION ALL
 SELECT name, id = object_id,
 xtype = type collate database_default,
 uid = convert(smallint, schema_id),
 info = convert(smallint, 0),
 status = convert(int, 0),
 base_schema_ver = convert(int, 0),
 replinfo = convert(int, 0),
 parent_obj = sysconv(int, 0),
 crdate = create_date,
 ftcatid = convert(smallint, 0),
 schema_ver = convert(int, 0),
 stats_schema_ver = convert(int, 0),
 type = type collate database_default,
 userstat = convert(smallint, 0),
 sysstat = convert(smallint, case type when 'V' then 2 when 'P' then 4 when 'X' then 4 else 0 end),
 indexdel = convert(smallint, 0),
 refdate = create_date,
 version = convert(int, 0),
 deltrig = convert(int, 0),
 instrig = convert(int, 0),
 updtrig = convert(int, 0),
 seltrig = convert(int, 0),
 category = convert(int, 2),
 cache = convert(smallint, 0)
 FROM sys.system_objects$
GO
你可以试一下,sys.system_objects$你是无法访问的

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧