經過我多次驗證,終於找到了Sybase中查詢數據庫結構的方法了。
在此之前,我就很不解這Sybase數據庫怎麼就沒有和Oracle、MySql一樣簡便的方法呢
desc 表名;
在網上查詢之後,得到一個結果。
sp_help 表名;
怎麼辦呢?看存儲過程源碼,把我們想要的結果截取出來吧。
sp_help存儲過程在sybsystemprocs庫中,
源碼:
/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */ /* 4.8 1.1 06/14/90 sproc/src/help */ /* ** Messages for "sp_help" 17570 ** ** 17460, "Object must be in the current database." ** 17461, "Object does not exist in this database." ** 17570, "Operating System File" ** 17571, "---------------------" ** 17573, "Object is Remote/External" ** 17574, "-------------------------" ** 17575, "Object existed prior to Omni" ** 17576, "Lock scheme is Allpages" ** 17577, "Lock scheme is Datapages" ** 17578, "Lock scheme is Datarows" ** 17579, "Lock scheme Unknown or Corrupted" ** 17581, "Trigger is disabled." ** 17582, "Trigger is enabled." ** 18571, "The attribute '%1!' is not applicable to tables with allpages lock scheme." ** 17589, "computed column" ** 19456, "Object is a computed column in table '%1!'." ** 19457, "Object is a function-based index key in table '%1!'." */ /* ** IMPORTANT NOTE: ** This stored procedure uses the built-in function object_id() in the ** where clause of a select query. If you intend to change this query ** or use the object_id() or db_id() builtin in this procedure, please read the ** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules ** pertaining to object-id's and db-id's outlined there, are followed. */ CREATE PROCEDURE dbo.sp_help @objname varchar(767) = NULL /* object name we're after */ as declare @typeid int /* type of object in systypes */ declare @basetypeid int /* base type in systypes */ declare @lenfactor int /* length factor */ declare @sysstat smallint /* the type of the object */ declare @OS_file varchar(255) /* physical file for ext tab */ declare @msg varchar(1024) declare @sptlang int declare @len1 int, @len2 int, @len3 int, @len4 int, @len5 int, @len6 int, @sysstat2 int, @valstat2 int declare @sqltext varchar(1024) /* SQL to execute using execute ** immediate. */ declare @and_access int /* cache bits in OBJECT.sysstat2 */ declare @or_access int /* cache bits in OBJECT.sysstat2 */ declare @sqlj_proc int /* indicates a sqlj proc */ declare @opt_ind_status int /* status of optimistic index lock */ declare @opt_ind_value int /* user input value of optimistic index lock */ declare @opt_ind_lock int /* Server constant for optimistic index lock */ declare @opt_text_dealloc int declare @opt_text_value int declare @opt_ind2_ascinserts int /* Server constant for ascinserts */ declare @encrypted_col int /* indicates encrypted col */ , @decrypt_def int /* indicates decrypt default col */ , @inrowlob int /* status2: whether column is LOB 'in row' */ , @thiskey varchar(30) /* index key column of ** virtually hashed table. */ declare @notruncate int /* indicates no truncation for varbinary columns */ declare @indid int declare @new_char_value varchar(255) /* hash factors of virtually ** hashed table. */ declare @num_keys int /* #index keys columns. */ declare @key_count int, @msgnum int, @valstat3 int, @sysstat3 int, @sep varchar(2), @sysopt_name varchar(100) declare @tab_lob_cmplvl tinyint /* LOB compression level for table */ declare @objtype char(2) /* object type in sysobjects */ declare @db_stat4 int declare @db_dealloc_ftp int /* Dealloc FTP after NULL update */ declare @tab_keep_ftp int /* Keep FTP after NULL update */ declare @tab_dealloc_ftp int /* Dealloc FTP after NULL update */ if @@trancount = 0 begin set chained off end set transaction isolation level 1 select @sptlang = @@langid if @@langid != 0 begin if not exists ( select * from master.dbo.sysmessages where error between 17100 and 17109 and langid = @@langid) select @sptlang = 0 end set nocount on /* ** If no @objname given, give a little info about all objects. ** Note: 0x80f is the mask for sysstats (=2063decimal). ** 800 is used by Stratus for external tables. */ select @sqlj_proc = hextoint("0x2000000") if @objname is NULL begin -- { /* ** Instead of Triggers are sub_types of trigger ** type; so first check for sysstat to be 8, then build the ** prefix of "instead of" for the trigger if needed. */ select Name = o.name, Owner = user_name(uid), Object_type = (case when ((o.sysstat & 15) = 8) then (case when (o.type = "IT") then "instead of " else null end) else null end ) + (m.description + x.name) into #sphelp1rs from sysobjects o, master.dbo.spt_values v, master.dbo.spt_values x, master.dbo.sysmessages m where o.sysstat & 2063 = v.number and ((v.type = "O" and (o.type != "XP" and ((o.sysstat2 & @sqlj_proc) = 0 or o.type = "U" or o.type = "S")) and (o.type != "RS")) /* precomputed result set */ or (v.type = "O1" and o.type = "XP") or (v.type = "O2" and (o.sysstat2 & @sqlj_proc) != 0 and o.type != "U" and o.type != "S") or (v.type = "O1" and o.type ="RS") /* precomputed result set */ or (v.type = "EK" and o.type = "EK")) and v.msgnum = m.error and isnull(m.langid, 0) = @sptlang and ((m.error between 17100 and 17109) or (m.error between 17587 and 17589) or (m.error between 18903 and 18904) or (m.error = 17588 or m.error = 17139 or m.error = 17015)) and x.type = "R" and o.userstat & -32768 = x.number exec sp_autoformat @fulltabname = #sphelp1rs, @orderby = "order by 3 desc, 1 asc" drop table #sphelp1rs select User_type = s.name, Storage_type = st.name, Length = s.length, Nulls = s.allownulls, Default_name = object_name(s.tdefault), Rule_name = object_name(s.domain), Access_Rule_name = object_name(s.accessrule) into #sphelp2rs from systypes s, systypes st where s.type = st.type and s.usertype > 99 and st.name not in ("sysname", "longsysname", "nchar", "nvarchar") and st.usertype < 100 exec sp_autoformat @fulltabname = #sphelp2rs, @orderby = "order by 1" drop table #sphelp2rs /* Display list of Java classes installed in this database */ print "" select Class_name = x.xtname, Jar_name = isnull(j.jname, '') into #sphelp3rs from sysxtypes x, sysjars j where x.xtcontainer *= j.jid exec sp_autoformat @fulltabname = #sphelp3rs, @orderby = "order by 1" drop table #sphelp3rs /* Display list of Java JARs installed in this database */ print "" exec sp_autoformat @fulltabname = sysjars, @selectlist = "'Jar_name' = jname", @orderby = "order by 1" print "" return (0) end -- } /* ** If this is a 4-part object name, mangle the name appropriately. ** [Note: this must be run in tempdb for successful results.] */ if @objname like "%.%.%.%" begin select @objname = str_replace(@objname, '.', '_') end /* ** Make sure the @objname is local to the current database. */ if @objname like "%.%.%" and substring(@objname, 1, charindex(".", @objname) - 1) != db_name() begin /* 17460, "Object must be in the current database." */ raiserror 17460 return (1) end /* ** Now check to see if the @objname is in sysobjects. It has to be either ** in sysobjects or systypes. */ if not exists (select * from sysobjects where id = object_id(@objname)) /* ** It wasn't in sysobjects so we'll check in systypes. */ begin -- { select @typeid = usertype, @basetypeid = type from systypes where name = @objname /* ** Time to give up -- @objname is not in sysobjects or systypes. */ if @typeid is NULL begin /* 17461, "Object does not exist in this database." */ raiserror 17461 return (1) end /* ** Get length factor: types based on unichar/univarchar ** are 2 bytes per character. */ if (@basetypeid in (select type from systypes where name in ('unichar', 'univarchar'))) select @lenfactor = @@unicharsize else select @lenfactor = 1 /* ** Print help about a data type */ select Type_name = s.name, Storage_type = st.name, Length = s.length/ @lenfactor, Nulls = s.allownulls, Prec = s.prec, Scale = s.scale, Default_name = object_name(s.tdefault), Rule_name = object_name(s.domain), Access_Rule_name = object_name(s.accessrule), Ident = s.ident into #sphelp4rs from systypes s, systypes st where s.usertype = @typeid and s.type = st.type and st.name not in ("timestamp", "sysname", "longsysname", "nchar", "nvarchar") and st.usertype < 100 exec sp_autoformat @fulltabname = #sphelp4rs, @selectlist = "Type_name, Storage_type,Length,Prec,Scale,Nulls,Default_name,Rule_name,Access_Rule_name,'Identity' = Ident" drop table #sphelp4rs return (0) end -- } /* ** It's in sysobjects so print out the information. */ /* ** Define status bit values for O2_ACCESS_CONTROL ** and O2_OR_ACCESS_CONTROL. */ select @and_access = hextoint("0x1000000"), @or_access = hextoint("0x4000000") select Name = o.name, Owner = user_name(uid), /* ** Decode object type, and figure out if its an access rule ** type. Access rules are sub-types of the rule type; so ** first check for sysstat to be 7. Build the prefix of ** 'AND access', or 'OR access', or '' strings. The prefix ** will be concatenated to the string 'rule' as obtained ** from the other tables. ** Meanwhile, Instead of Triggers are sub_types of trigger ** type; so first check for sysstat to be 8, then build the ** prefix of "instead of" for the trigger if needed. */ Object_type = (case when ((o.sysstat & 15) = 7) then (case when ( ((o.sysstat2 & @and_access) > 0) and ((o.sysstat2 & @or_access) > 0)) then "OR access" when ((o.sysstat2 & @and_access) > 0) then "AND access" else null end ) when ((o.sysstat & 15) = 8) then (case when (o.type = "IT") then "instead of " else null end) else null end ) + (m.description + x.name) , Object_status = convert(varchar(255), ' ') , Create_date = o.crdate into #sphelp5rs from sysobjects o, master.dbo.spt_values v, master.dbo.spt_values x, master.dbo.sysmessages m where o.id = object_id(@objname) and o.sysstat & 2063 = v.number and ((v.type = "O" and (o.type != "XP" and ((o.sysstat2 & @sqlj_proc) = 0 or o.type = "U" or o.type = "S")) and (o.type != "RS")) or /* precomputed result set */ (v.type = "O1" and o.type = "XP") or (v.type = "O2" and (o.sysstat2 & @sqlj_proc) != 0 and o.type != "U" and o.type != "S") or (v.type = "O1" and o.type = "RS") or /* precomputed result set */ (v.type = "EK" and o.type = "EK")) and v.msgnum = m.error and isnull(m.langid, 0) = @sptlang and ((m.error between 17100 and 17199) or (m.error between 17587 and 17589) or (m.error between 18903 and 18904) or (m.error = 17588 or m.error = 17015)) and x.type = "R" and o.userstat & -32768 = x.number /* ** Set Object_status based on sysstat2 to show any special status the object may have. ** Currently only object status 'deallocate first text page' or 'keep first text page' ** would be displayed based on both table level (by sp_chgattribute) and db level (by ** sp_dboption) settings as below. ** ** 'deallocate first text page' will be displayed when ** o column sysstat2 of sysobjects entry has value 536870912 ** o or column sysstat2 of sysobjects entry neither has value 536870912 nor ** -2147483648, but column status4 of sysdatabases entry (for current ** database) has value -2147483648. ** ** otherwise, 'keep first text page' will be displayed. ** ** Table level setting for option dealloc_first_txtpg (sysstat2 in sysobjects) ** 0x2000000 ---- 536870912, deallocate first text page after NULL update ** 0x8000000 ---- -2147483648, keep first text page after NULL update ** ** DB level setting for option 'deallocate first text page' (status4 in sysdatabases) ** 0x8000000 ---- -2147483648, deallocate first text page after NULL update */ select @db_dealloc_ftp = hextoint('0x80000000') select @tab_dealloc_ftp = hextoint('0x20000000') select @tab_keep_ftp = hextoint('0x80000000') select @sysstat2 = sysstat2, @objtype = type from sysobjects where id = object_id(@objname) /* ** Only check user tables */ if (@objtype = 'U') begin select @db_stat4 = status4 from master.dbo.sysdatabases where dbid = db_id() if ((@sysstat2 & @tab_dealloc_ftp != 0) or ((@sysstat2 & @tab_keep_ftp = 0) and (@db_stat4 & @db_dealloc_ftp != 0))) begin select @valstat2 = @tab_dealloc_ftp end else begin select @valstat2 = @tab_keep_ftp end select @msgnum = msgnum, @sysopt_name = name, @sep = '' from master.dbo.spt_values where type = 'O2' and number = @valstat2 if (@msgnum != 17119) begin select @sysopt_name = isnull(description, @sysopt_name) from master.dbo.sysmessages where error = @msgnum and isnull(langid, 0) = @sptlang update #sphelp5rs set Object_status = ltrim(Object_status + @sep + @sysopt_name) from #sphelp5rs a, sysobjects o where a.Name = o.name and o.sysstat & 15 = 3 and o.id = object_id(@objname) end end -- } /* Set Object_status based on sysstat3 to show any special status the object may have */ select @sysstat3 = sysstat3, @objtype = type from sysobjects where id = object_id(@objname) select @valstat3 = min(number), @sep = '' from master.dbo.spt_values where type = 'O3' and number > 0 and number & @sysstat3 = number while (@valstat3 is not null) begin -- { select @msgnum = msgnum, @sysopt_name = name from master.dbo.spt_values where type = 'O3' and number = @valstat3 /* We do not allow PRS objects to be defined on other PRS ** objects. Even if we plan to support this in future, this ** will be a major design change and sp_help will have to be ** updated accordingly to allow that. The bit 0x40 in sysstat3 ** is currently overridden to check if PRS objects are defined ** on any object. */ if not (@objtype = 'RS' and @msgnum = 17119) begin select @sysopt_name = isnull(description, @sysopt_name) from master.dbo.sysmessages where error = @msgnum and isnull(langid, 0) = @sptlang update #sphelp5rs set Object_status = ltrim(Object_status + @sep + @sysopt_name) from #sphelp5rs a, sysobjects o where a.Name = o.name and o.sysstat & 15 in (3, 4) and o.sysstat3 & @valstat3 = @valstat3 end select @valstat3 = min(number), @sep = ', ' from master.dbo.spt_values where type = 'O3' and number > @valstat3 and number & @sysstat3 = number end -- } /* ** If the object type is precomputed result set then set Object_status ** information with the following properties: ** a. Refresh Policy: immediate/manual ** b. State: enabled/disabled ** c. QRW State: enabled/disabled for QRW */ if @objtype = 'RS' begin -- { /* #sphelp5rs will only have 1 row corresponding to a PRS */ update #sphelp5rs set Object_status = /* Save existing Object_status information */ (case when (Object_status != "") then Object_status + ", " else null end) + /* refresh policy */ (case when ((@sysstat3 & 8) = 8) then "manual" when ((@sysstat3 & 16) = 16) then "immediate" end) + ", " + /* state */ (case when ((@sysstat3 & 32) = 32) then "disabled" else "enabled" end) + ", " + /* query rewrite state */ (case when ((@sysstat3 & 64) = 64) then "disabled for QRW" else "enabled for QRW" end) end -- } update #sphelp5rs set Object_status = (select description from master.dbo.sysmessages where error = 17661 and isnull(langid, 0) = @sptlang) where datalength(Object_status) < 2 exec sp_autoformat @fulltabname = #sphelp5rs drop table #sphelp5rs /* ** Objects have the following value for sysstat & 15: ** 0 - any/illegal object ** 1 - system table ** 2 - view ** 3 - user table ** 4 - sproc ** 5 - predicate ** 6 - default ** 7 - rule ** 8 - trigger ** 9 - referential constraint ** 10 - sql function ** 11 - extended type ** 12 - sqlj function ** 13 - computed column ** 14 - partition condition ** 15 - encryption key ** ** ** If the object is a system table, view, or user table, we want to check ** out the objects columns here. */ select @sysstat = sysstat, @sysstat2 = sysstat2 from sysobjects where id = object_id(@objname) /* ** Fix of bug 91669: ** For the current design, a view having nameless column may be created, ** e.g. create view view1 as select sum(column1) from table1. ** In this case, c.name is NULL. Using builtin function isnull() to ** make the following query work. */ select @encrypted_col = hextoint("0x00000080") , @decrypt_def = hextoint("0x00001000") , @inrowlob = hextoint("0x00040000") , @notruncate = hextoint("0x00200000") -- Report on the following "table" objects: -- 1: System tables -- 2: Views -- 3: User tables -- if (@sysstat & 15) in (1, 2, 3) begin select Column_name = isnull(c.name, 'NULL'), Col_order = colid, Type = isnull(convert(char(30), x.xtname), isnull(convert(char(30), get_xtypename(c.xtype, c.xdbid)), t.name)), Length = c.length, In_row_Len = c.inrowlen, Prec = c.prec, Scale = c.scale, Nulls = convert(bit, (c.status & 8)), Not_compressed = convert(bit, (isnull(c.status2, 0) & 131072)), Lob_compression_level = c.lobcomp_lvl, Default_name = object_name(c.cdefault), Rule_name = object_name(c.domain), Access_Rule_name = object_name(c.accessrule), Computed_Column_object = case when (c.status3 & 1) = 1 then object_name(c.computedcol)+ " (functional index key)" when (c.status2 & 32) = 32 then object_name(c.computedcol)+" (materialized)" when (c.status2 & 16) = 16 then object_name(c.computedcol)+" (virtual)" else object_name(c.computedcol) end, rtype = t.type, utype = t.usertype, xtype = c.xtype, Ident = convert(bit, (c.status & 0x80)), Encrypted = case when (c.status2 is null) then 0 when (c.status2 & @encrypted_col) > 0 then 1 end, Decrypt_Default_name = case when (c.status2 is null) then NULL when (c.status2 & @decrypt_def) > 0 then (select object_name(a.object) from sysattributes a where a.class = 25 and a.attribute = 1 and a.object_info1 = c.id and a.object_info2 = c.colid) else NULL end, Object_storage = case when ((isnull(c.status2,0) & @inrowlob) != 0) then "in row" when (c.xstatus is null) then NULL when (c.xstatus & 1) = 1 then "off row" else "in row " end, Varbinary_is_truncated = case when (c.status2 is null) then NULL when (c.status2 & @notruncate) > 0 then 0 else 1 end into #helptype from syscolumns c, systypes t, sysxtypes x where c.id = object_id(@objname) and c.usertype *= t.usertype and c.xtype *= x.xtid /* ** We truncate extended type names >30 characters to 30, ** and print them with a trailing "+" character. */ update #helptype set Type = substring(Type, 1, 29) + "+" where xtype is not null and substring(Type, 29, 1) != " " /* Handle National Characters */ update #helptype set Length = Length / @@ncharsize where (rtype = 47 and utype = 24) or (rtype = 39 and utype = 25) /* Handle unichar/univarchar */ update #helptype set Length = Length / @@unicharsize where rtype in (select type from systypes where name in ('unichar', 'univarchar')) /* Handle unsigned types by outputing user syntax */ update #helptype set Type = "unsigned " + substring(Type, charindex("u", Type) + 1, 30) where utype in (44, 45, 46) /* ** Construct the SQL query against #helptype. Be careful not to ** exceed 255 characters, or the string will get truncated. */ select @sqltext = "Column_name,Type, Length" /* Display in-row length only if there are any in-row LOBs */ if exists (select 1 from #helptype where In_row_Len is not null) begin /* Convert bytes to unichars for length of unitext */ update #helptype set In_row_Len = In_row_Len / @@unicharsize where rtype in (select type from systypes where name = 'unitext') select @sqltext = @sqltext + ",In_row_Len " end select @sqltext = @sqltext + ", Prec,Scale,Nulls,Not_compressed,Default_name,Rule_name,Access_Rule_name,Computed_Column_object,'Identity' = Ident" /* Display the Object_storage only if there are object columns. */ if exists (select * from #helptype where Object_storage is not null) begin select @sqltext = @sqltext + ", Object_storage " end /* ** Display the Encrypted column status only if there are encrypted ** columns. */ if exists (select * from #helptype where Encrypted != 0) begin select @sqltext = @sqltext + ", Encrypted " end /* ** Display the Decrypt_Default_name only if there ** are encrypted columns that have decrypt default values */ if exists (select * from #helptype where Decrypt_Default_name is not null) begin select @sqltext = @sqltext + ", Decrypt_Default_name" end /* ** Display Lob compression level only if there are compressed LOB ** columns. */ if exists (select * from #helptype where Lob_compression_level is not null) begin select @sqltext = @sqltext + ", Lob_compression_level" end /* ** Display the varbinary truncation only if there ** is any varbinary column. */ if exists (select * from #helptype where Type = "varbinary" or (Type = "binary" and Nulls = 1)) begin select @sqltext = @sqltext + ", Varbinary_is_truncated" /* Update the field non-varbinary types */ update #helptype set Varbinary_is_truncated = NULL where (Type != "varbinary" and (Type != "binary" or Nulls = 0)) or Computed_Column_object is not null end exec sp_autoformat @fulltabname = #helptype, @selectlist = @sqltext, @orderby = "order by Col_order asc" drop table #helptype end /* ** If this is a table object that has computed columns, display the ** computed column information. */ if (@sysstat & 15) in (1, 3) begin if exists (select 1 from syscolumns where id = object_id(@objname) and computedcol is not null and (status3 & 1) !=1) begin print "" execute dbo.sp_helpcomputedcolumn @objname, 0 end end /* ** For procedures and sqlj functions, the parameters of the procedures ** are stored in syscolumns. */ if @sysstat & 15 in (4, 10, 12) begin exec sp_help_params @objname end /* ** If the object is an external table, show which OS file it's using. */ if @sysstat & 2063 = 2051 begin select @OS_file = name from sysindexes where id = object_id(@objname) and indid in (0,1) /* ** 17570, "Operating System File" ** 17571, "---------------------" */ print "" exec sp_getmessage 17570, @msg out print @msg exec sp_getmessage 17571, @msg out print @msg print @OS_file print "" end /* ** If the object is an Omni-managed table, show its storage location. */ if (@sysstat2 & 1024 = 1024) begin declare @dbname varchar(255), @site varchar(255), @owner varchar(255), @tabname varchar(255), @retcode int exec @retcode = sp_namecrack @objname, @site output, @dbname output, @owner output, @tabname output select @OS_file = char_value from sysattributes where class = 9 and attribute = 1 and object_cinfo = @tabname /* ** 17573, "Object is Remote/External" ** 17574, "-------------------------" */ print "" exec sp_getmessage 17573, @msg out print @msg exec sp_getmessage 17574, @msg out print @msg print @OS_file print "" if (@sysstat2 & 2048 = 2048) begin /* ** 17575, "Object existed prior to Omni" */ exec sp_getmessage 17575, @msg out print @msg print "" end end /* ** If the object is a table, display sysattributes information ** if there is any. It could be in the current database under ** type "T". */ if @sysstat & 15 in (1, 3) begin /* Create temporary table for sysattributes data */ create table #sphelpattr ( class varchar(255), class_id smallint, attribute varchar(255), attribute_id smallint, int_value int NULL, char_value varchar(255) NULL, comments varchar(255) NULL ) /* ** The join with master..sysattributes here is to ** get the string descriptions for the class and attribute. ** These should never be more than 30 chars, so it's okay to ** truncate them. */ insert #sphelpattr (class, class_id, attribute, attribute_id, int_value, char_value, comments) select c.char_value, t.class, a.char_value, t.attribute, t.int_value, t.char_value, t.comments from sysattributes t, master.dbo.sysattributes c, master.dbo.sysattributes a where t.object_type = "T" and t.object = object_id(@objname) and c.class = 0 and c.attribute = 0 and a.class = 0 and a.attribute = 1 and t.class = c.object and t.class = a.object and t.attribute = a.object_info1 /* ** If the table is virtually hashed, then print the list of index key ** columns and their correspondig hash factors as char_value. */ if(exists(select attribute from #sphelpattr where attribute = 'hash key factors')) begin /* The table is Virtually Hashed */ exec sp_getmessage 19586, @msg out print @msg print "" select @new_char_value = "" select @num_keys = keycnt from sysindexes where id = object_id(@objname) select @key_count = 1 select @indid = min(indid) from sysindexes where id = object_id(@objname) and indid > 0 and indid < 255 set nocount on /* ** Get the list of index key columns. */ while (@key_count <= @num_keys) begin select @thiskey = index_col(@objname, @indid, @key_count) if (@thiskey is NULL) begin break end if(@key_count > 1) begin select @new_char_value = @new_char_value + ", " end select @new_char_value = @new_char_value + @thiskey /* ** In current 'char_value', we have an array of hash ** factors of type 'double' that was written to ** 'char_value' as byte string. ** Hence to get the array of hash factors back: ** ** 1. Divide 'char_value' into disjoint substrings, ** each of length 8 (sizeof double). ** 2. Convert the substring into binary type. ** 3. Convert the binary value into 'double'. ** ** Once obtained the value, convert it to character ** type and append to @new_char_value */ select @new_char_value = @new_char_value + ":" + convert(varchar(255), convert(double precision, convert(binary, substring(char_value, @key_count * 8 - 7, 8)))) from #sphelpattr where attribute = 'hash key factors' select @key_count = @key_count + 1 end /* ** Append the 'max_hash_key' to @new_char_value */ select @new_char_value = @new_char_value + ", max_hash_key" select @new_char_value = @new_char_value + "=" + convert(varchar(255), convert(double precision, convert(binary, substring(char_value, @key_count * 8 - 7, 8)))) from #sphelpattr where attribute = 'hash key factors' update #sphelpattr set char_value = @new_char_value where attribute = 'hash key factors' end /* ** It's possible a cache is deleted without doing an unbind first. After ** a server reboot the binding is marked 'invalid' (int_value = 0). ** If we have such an invalid binding, don't show it in the output. */ delete from #sphelpattr where class_id = 3 and attribute_id = 0 and int_value = 0 if exists (select * from #sphelpattr) begin exec sp_autoformat @fulltabname = #sphelpattr, @selectlist = "'attribute_class' = class, attribute, int_value,char_value, comments" end drop table #sphelpattr end /* ** If the object is a procedure, display sysattributes information ** if there is any. */ if @sysstat & 15 = 4 begin if exists (select * from sysattributes where object_type = "P" and object = object_id(@objname)) begin /* ** The join with master..sysattributes here is to ** get the string descriptions for the class ** (master.dbo.sysattributes c) and attribute ** (master.dbo.sysattributes a). */ select attribute_class = convert(varchar(512), c.char_value), attribute = convert(varchar(512), a.char_value), t.int_value, char_value = convert(varchar(512), t.char_value), t.comments into #sphelp6rs from sysattributes t, master.dbo.sysattributes c, master.dbo.sysattributes a where t.object_type = "P" and t.object = object_id(@objname) and c.class = 0 and c.attribute = 0 and a.class = 0 and a.attribute = 1 and t.class = c.object and t.class = a.object and t.attribute = a.object_info1 exec sp_autoformat @fulltabname = #sphelp6rs drop table #sphelp6rs end end /* ** If the object is a table, check out the indexes. */ if @sysstat & 15 in (1, 3) execute dbo.sp_helpindex @objname /* ** If the object is a table or view, check out the keys. */ if @sysstat & 15 in (1, 2, 3) execute dbo.sp_helpkey @objname /* ** If the object is a table, check out the slices/partitions */ if @sysstat & 15 in (1, 3) execute dbo.sp_helpartition @objname /* ** If the object is a trigger, it is either enabled or disabled */ if @sysstat & 15 in (0,8) begin /* ** 1048676 <==> 0x100000 <==> insert trigger disabled ** 2097152 <==> 0x200000 <==> delete trigger disabled ** 4194304 <==> 0x400000 <==> update trigger disabled */ if exists (select 1 from sysobjects trig, sysobjects tab where trig.id = object_id(@objname) and trig.deltrig = tab.id and ((trig.id = tab.deltrig and tab.sysstat2 & 2097152 <> 0) or (trig.id = tab.updtrig and tab.sysstat2 & 4194304 <> 0) or (trig.id = tab.instrig and tab.sysstat2 & 1048576 <> 0))) exec sp_getmessage 17581, @msg out else exec sp_getmessage 17582, @msg out print @msg end /* ** If the object is a table, display the table level LOB compression level */ if @sysstat & 15 in (1, 3) begin select @tab_lob_cmplvl = lobcomp_lvl from sysobjects where id = object_id(@objname) select @msg = "Table LOB compression level " + convert(varchar(3), @tab_lob_cmplvl) print @msg if exists (select 1 from sysattributes where object_type="TI" and object_info1 & 4096 = 4096 and object = object_id(@objname)) begin select @msg = "Table " + @objname + " has columns dropped by no datacopy method." print @msg end end /* ** Print the lock scheme information for the table objects */ if @sysstat & 15 in (1, 3) begin /* ** the bits 0x2000, 0x4000 & 0x8000 represents any ** explicit lock scheme bits that can be set, so ** get them out ( 0x2000 + 0x4000 + 0x8000 = 57344) */ select @sysstat2 = (sysstat2 & 57344) from sysobjects where id = object_id(@objname) /* ** The value 0, refers that no lock scheme is ** specified (old style tables) so they support only ** allpages locking */ if (@sysstat2 in (0, 8192, 16384, 32768)) begin if (@sysstat2 = 8192 or @sysstat2 = 0) begin /* 17576, "Lock scheme is Allpages" */ exec sp_getmessage 17576, @msg out print @msg /* 18571, "The attribute '%1!' is */ /* not applicable to tables with */ /* allpages lock scheme." */ exec sp_getmessage 18571, @msg out print @msg, 'exp_row_size' /* 18571, "The attribute '%1!' is */ /* not applicable to tables with */ /* allpages lock scheme." */ exec sp_getmessage 18571, @msg out print @msg, 'concurrency_opt_threshold' end if ( @sysstat2 = 16384 ) begin /* 17577, "Lock scheme is Datapages" */ exec sp_getmessage 17577, @msg out print @msg /* 18983, "The '%1!' attribute is not applicable ** to tables with datarow or datapage lock schemes. */ exec sp_getmessage 18983, @msg out print @msg, 'ascinserts' end if (@sysstat2 = 32768) begin /* 17578, "Lock scheme is Datarows" */ exec sp_getmessage 17578, @msg out print @msg /* 18983, "The '%1!' attribute is not applicable ** to tables with datarow or datapage lock schemes. */ exec sp_getmessage 18983, @msg out print @msg, 'ascinserts' end /* Server defined value for ascinserts ** if ascinserts is set, then master..sysindexes.status2=64 */ select @opt_ind2_ascinserts = 64 print " " select exp_rowsize "exp_row_size", res_page_gap "reservepagegap", fill_factor "fillfactor", maxrowsperpage "max_rows_per_page", isnull(identitygap, 0) "identity_gap", (case when ((@opt_ind2_ascinserts & status2) > 0) then 1 else 0 end ) "ascinserts" from sysindexes where id = object_id(@objname) and indid <= 1 /* Server defined constant for optimistic index lock */ select @opt_ind_lock = 268435456 /* Server defined constant for dealloc first txtpg */ select @db_dealloc_ftp = hextoint('0x80000000') select @tab_dealloc_ftp = hextoint("0x020000000") select @tab_keep_ftp = hextoint('0x80000000') /* Get db level status */ select @db_stat4 = status4 from master.dbo.sysdatabases where dbid = db_id() select @opt_ind_status = (sysstat2 & @opt_ind_lock), @opt_text_dealloc = (sysstat2 & (@tab_dealloc_ftp | @tab_keep_ftp)) from sysobjects where id = object_id(@objname) if (@opt_ind_status = 0) select @opt_ind_value = 0 else select @opt_ind_value = 1 if ((@opt_text_dealloc = @tab_dealloc_ftp) or ((@opt_text_dealloc = 0) and (@db_stat4 & @db_dealloc_ftp != 0))) select @opt_text_value = 1 else if (@opt_text_dealloc = @tab_keep_ftp) select @opt_text_value = 2 else select @opt_text_value = 0 /* ** Currently, the following information will be same ** for all partitions, only need to print once for ** one of the partitions */ select distinct conopt_thld "concurrency_opt_threshold", @opt_ind_value "optimistic_index_lock", @opt_text_value "dealloc_first_txtpg" from systabstats where id = object_id(@objname) and indid <= 1 return (0) end else begin /* 17579, "Lock scheme Unknown or Corrupted" */ exec sp_getmessage 17579, @msg out print @msg return (1) end end /* ** If the object is computed column, display ** computed column information. ** We just simply follow the way sp_helpcomputedcolumn works. */ if (@sysstat & 15) = 13 begin declare @count int, @total int, @row_id int, @config_parm int, @mode int, @tab_name varchar(767) select @tab_name = object_name(id), @mode = status3 & 1 from syscolumns where computedcol = object_id(@objname) /* ** Create temporary table to stored computed column info */ create table #helpcpc (colname varchar(255), computedcol int, property varchar(15) null, row_id numeric identity) /* ** Get info on computed columns */ if @mode != 1 begin insert into #helpcpc(colname, computedcol, property) select name, computedcol, case when (status2 & 32 = 32) then "materialized" else "virtual" end from syscolumns where computedcol = object_id(@objname) and status3 & 1 != 1 order by colid end /* ** Get Info on functional index keys */ else begin insert into #helpcpc(colname, computedcol) select name, computedcol from syscolumns where computedcol = object_id(@objname) and status3 & 1 = 1 order by colid end /* ** Display the header */ if @mode != 1 begin exec sp_getmessage 19456, @msg output end else begin exec sp_getmessage 19457, @msg output end print "" print @msg, @tab_name print "" /* ** If the configuration parameter 'allow select on syscomments.text' ** is set to 0, then the user can access the text ONLY in the ** following cases ** ** 1. if the user has sa_role ** 2. if the object is owned by the user ** */ select @config_parm = value from master.dbo.syscurconfigs where config = 258 if @config_parm = 0 and user_id() != 1 begin /* ** The object needs to be owned by the user */ if not exists (select name from sysobjects where uid = user_id() and id = object_id(@objname)) begin /* ** Inform the user the text cannot be displayed and ** print the rest info before return */ if @mode != 1 begin exec sp_getmessage 19334, @msg output print @msg exec sp_autoformat #helpcpc, "'Column_Name' = colname, Property = property" end else begin exec sp_getmessage 19335, @msg output print @msg exec sp_autoformat #helpcpc, "'Internal_Index_Key_Name' = colname" end drop table #helpcpc return(0) end end /* ** Now display the text */ create table #helptxt (text varchar(255), row_id numeric (10) identity) create table #helpname (colname varchar(255), property varchar(15) null) select @count = 1 select @total = max(row_id) + 1 from #helpcpc while @count < @total begin insert into #helpname(colname, property) select colname, property from #helpcpc where row_id = @count if @mode != 1 begin exec sp_autoformat #helpname, "'Column_Name' = colname, Property = property" end else begin exec sp_autoformat #helpname, "'Internal_Index_Key_Name' = colname" end /* ** See if the object is hidden (SYSCOM_TEXT_HIDDEN will be set) */ if exists (select 1 from syscomments m, #helpcpc h where (m.status & 1 = 1) and m.id = h.computedcol and h.row_id = @count) begin exec sp_getmessage 19337, @msg output print @msg print "" delete #helpname select @count = @count + 1 continue end insert #helptxt (text) select text from syscomments, #helpcpc where row_id = @count and id = computedcol order by colid2, colid print "" if @mode != 1 begin exec sp_autoformat #helptxt, "Text = text" end else begin select @row_id = min(row_id) from #helptxt update #helptxt set text = right(text, char_length(text)-4) where row_id = @row_id select @row_id = max(row_id) from #helptxt update #helptxt set text = left(text, char_length(text)-13) where row_id = @row_id exec sp_autoformat #helptxt, "Expression = text" end print "" select @count = @count + 1 delete #helpname delete #helptxt end drop table #helpcpc, #helpname, #helptxt end return (0)
我們發現在源碼的556行“if (@sysstat & 15) in (1, 2, 3)”有我們想要的結果,這段IF語句是將表結果查詢之後插入一個臨時表#helptype中,然後再進行查詢出來的。
我們不要那麼麻煩,只取裡面的三列:字段名,字段類型,字段長度。
當然你想封裝成存儲過程也可以的,但不能使用desc就是。
select isnull(c.name, 'NULL') '字段名', <span style="white-space:pre"> </span>t.name '字段類型', <span style="white-space:pre"> </span>c.length '字段長度' from syscolumns c, systypes t, sysxtypes x where c.id = object_id('表名') <span style="white-space:pre"> </span>and c.usertype *= t.usertype <span style="white-space:pre"> </span>and c.xtype *= x.xtid;