经过我多次验证,终于找到了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;

Sybase查询表结构的方法(类似于Oracle的Desc)
原文:http://blog.csdn.net/jub5blog/article/details/46334433