Sybase自动生成数据库内所有表的DDL语句的存储过程

 提供一个能够自动生成Sybase数据库内所有表的表结构、索引语法的存储过程。

存储过程名字:sp_gettabledll 下载

过程语法如下:

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

if exists(select 1 from sysobjects where name = 'sp_gettabledll' and type = 'P')
  drop procedure sp_gettabledll
go

create procedure sp_gettabledll 
@tblname varchar(30) = null, 
@prechar varchar(4) = null,   --$:no print 
@table_dll varchar(16384) = null out, 
@dbname varchar(32) = null, 
@droptg char(1) = '1', 
@prxytx varchar(255) = null, 
@replace varchar(20) = null, 
@tabtype varchar(1) = 'A', --A:所有表;P:代理表;U:用户表 
@indextg varchar(3) = 'TPI',  --T:纯表;P:主键;I:纯索引;J:除主键外的纯索引(和TP使用与I相同,和I同时使用I失效) 
@table_seg varchar(32) = null, 
@index_seg varchar(32) = null 
as 
begin 
     set nocount on  
 
    if @tblname is null begin 
        declare @c_tblname varchar(30) 
        declare cur_1 cursor for 
        select name from sysobjects where type = 'U' order by name 
        open cur_1 
        fetch cur_1 into @c_tblname 
        while @@sqlstatus = 0 begin 
            exec sp_gettabledll  
                @tblname = @c_tblname, 
                @prechar = @prechar, 
                @dbname  = @dbname , 
                @droptg  = @droptg , 
                @prxytx  =  @prxytx , 
                @replace = @replace, 
                @tabtype = @tabtype, --A:所有表;P:代理表;U:用户表 
                @indextg = @indextg, --A:表和索引;T:纯表;I:纯索引 
                @table_seg = @table_seg, 
                @index_seg = @index_seg 
            fetch cur_1 into @c_tblname 
        end 
        close cur_1 
        deallocate cursor cur_1 
        return 
    end 
 
    declare @obj_id int 
    declare @sysstat2 int 
    declare @username varchar(30) 
 
     select @obj_id = id, @sysstat2 = sysstat2 ,@username  = user_name(uid) 
        from sysobjects where name = @tblname and type = 'U' 
    if @@rowcount <> 1 
    begin 
        print 'table %1! not exists', @tblname 
        goto err 
    end 
     if @sysstat2 & 1024 = 1024 begin 
        if upper(@tabtype) in ('U') 
            goto ok 
    end 
    else begin 
        if upper(@tabtype) in ('P') 
            goto ok 
    end 
 
    declare @colname varchar(30)        --列名 
    declare @typename varchar(30)       --类型名称 
    declare @usertype smallint          --类型ID 
    declare @length int                 --长度 
    declare @prec tinyint               --有效位数 
    declare @scale tinyint              --精度 
    declare @def_id int             --默认值id 
    declare @nulls tinyint              --空值 
    declare @ident tinyint              --标识列 
    declare @index_dll varchar(16384) 
 
    declare @def_text varchar(100) 
    declare @ide_text varchar(30) 
    declare @nul_text varchar(30) 
 
    declare @cns_text varchar(500) 
    declare @uni_pri varchar(40), @non_clu varchar(40), @non_uni varchar(40) 
 
    declare @lock_scheme varchar(100) 
 
    declare @keys varchar(500), @i int 
    declare @thiskey varchar(30) 
    declare @sorder char(4) 
    select @keys = "", @i = 1 
 
    declare @cns_name varchar(30), @status int, @indid int 
    declare @idx_name varchar(50) 
 
    declare @CRNW varchar(2)    --回车换行 
    declare @TAB char(1) 
 
    select @CRNW = convert(varchar(2), 0x0d0a) 
    select @TAB = convert(char(1), 0x09) 
 
    declare @dbname_dot varchar(35) 
    if ltrim(@dbname) is null 
        select @dbname = null,@dbname_dot = null 
    else 
        select @dbname = @dbname + '.',@dbname_dot = @dbname + '..' 
 
    declare @table_name varchar(30) 
    select @table_name = case when ltrim(@replace) is not null then @replace else @tblname end 
 
    declare @prefix_table varchar(2) 
    select @prefix_table = case when ltrim(@prxytx) is not null then 'r_' else null end 
 
    if charindex('T',@indextg) > 0 begin 
        if @droptg <> '0' 
            select @table_dll = "if exists(select 1 from "+@dbname_dot 
            +"sysobjects where name = '"+@prefix_table 
            +@table_name+"' and type = 'U')" 
            +@CRNW+@TAB+'drop table '+@dbname+@username + '.' 
            +@prefix_table 
            +@table_name+@CRNW 
            +case when @sysstat2 & 1024 = 1024 
                     then @TAB+'exec sp_dropobjectdef '+@table_name+@CRNW 
                when ltrim(@prxytx) is not null 
                    then @TAB+'exec sp_dropobjectdef r_'+@table_name+@CRNW 
                else null  
            end 
            +'go'+@CRNW 
        else 
            select @table_dll = null 
     
        if @sysstat2 & 1024 = 1024 begin 
            declare @OS_file varchar(255) 
            select @OS_file = char_value from sysattributes 
                    where class = 9 and attribute = 1 and 
                    object_cinfo = @tblname 
            if @@rowcount = 0 begin 
                print '取代理表前缀失败%1!', @tblname 
                goto err 
            end 
            select @table_dll = @table_dll+"exec sp_addobjectdef " 
            +@table_name 
            +", '"+@OS_file+"', 'table'"+@CRNW+ 
            "create existing table " + @dbname+@username + "." 
            +@table_name + " (" 
        end 
        else if ltrim(@prxytx) is not null 
             select @table_dll = @table_dll+"exec sp_addobjectdef r_" 
            +@table_name+", '"+@prxytx 
            +@table_name+"', 'table'"+@CRNW 
            +"create existing table " + @dbname+@username + ".r_" 
            +@table_name + " (" 
         else 
            select @table_dll = @table_dll+'create table ' + @dbname+@username + '.' 
            +@table_name + ' (' 
     
        --如果在sybsystemprocs数据库下提交,以下注释掉 
         
        declare @tablna varchar(255) 
         --select @tablna = tablna from knp_tabl where tablcd = @tblname 
        --if @@rowcount = 0 
            select @tablna = null 
        if ltrim(@tablna) is not null 
            select @table_dll = @table_dll + '    --'+@tablna 
     
        select @prechar = case when @prechar is not null then left(@prechar+space(4),4) else @prechar end 
        if @prechar <> '$' begin 
            if @prechar is not null begin 
                declare @temp_dll varchar(16384),@print_dll varchar(16384) 
                 select @temp_dll = @table_dll 
                select @temp_dll = @prechar + @temp_dll 
                while charindex(@CRNW,@temp_dll) > 0 and char_length(@temp_dll) <> charindex(@CRNW,@temp_dll)+1 begin 
                    select @print_dll = @print_dll + left(@temp_dll,charindex(@CRNW,@temp_dll) - 1) + @CRNW+@prechar 
                    select @temp_dll = substring(@temp_dll,charindex(@CRNW,@temp_dll)+char_length(@CRNW),char_length(@temp_dll)) 
                end 
                 select @print_dll = @print_dll + @temp_dll 
                print '%1!',@print_dll 
            end 
            else 
                print '%1!',@table_dll 
        end 
         
        select @table_dll = @table_dll + @CRNW 
     
         if ltrim(@table_seg) is null begin 
            select @table_seg = s.name 
                from sysobjects o, syssegments s, sysindexes i 
                    where o.id = object_id(@tblname) 
                        and i.id = o.id 
                         and i.indid < 2 
                        and i.segment = s.segment 
            if @@rowcount = 0 begin  
                print '表%1!所在的段不存在',@tblname 
                goto err 
            end 
        end 
    end 
 
    --确定表是否有完整性约束 
    declare @have_con char(1) 
    if exists (select 1 from sysindexes where id = @obj_id and status2 & 2 = 2 ) 
        and (ltrim(@prxytx) is null or @sysstat2 & 1024 = 1024) 
        select @have_con = '1' 
    else 
         select @have_con = '0' 
 
 
    if charindex('T',@indextg) > 0 begin 
        declare @col_int int 
        select @col_int = count(*) from syscolumns 
            where id = @obj_id 
     
        declare cur_col cursor for 
            select b.name, b.usertype, c.name , b.length, b.prec, b.scale, b.cdefault, 
                    convert(bit,b.status&8) as Nulls, 
                    convert(bit,b.status&128) as Ident 
                from sysobjects a, syscolumns b, systypes c 
                 where a.name = @tblname and a.type = 'U' 
                    and  a.id = b.id 
                    and b.usertype = c.usertype 
                order by b.colid 
     
        open cur_col 
        fetch cur_col into @colname, @usertype, @typename, @length, @prec, @scale, @def_id, @nulls, @ident 
        while @@sqlstatus = 0 
        begin 
            --系统定义的数据类型 
            if  @usertype < 100 
            begin 
     
                if rtrim(@typename) in ('char','varchar','nchar','nvarchar') 
                    select @typename = @typename + '('+ convert(varchar,@length) +')' 
                else if @typename in ('numeric','decimal') 
                    select @typename = @typename + '(' + convert(varchar,@prec) +  ',' + convert(varchar,@scale) + ')' 
                else if @typename in ('float','double') 
                    select @typename = @typename + '(' + convert(varchar,@prec) + ')' 
                else if @typename in ('binary','varbinary') 
                     select @typename =  @typename + '(' + convert(varchar,@length) + ')' 
            end 
     
            select @ide_text = case @ident when 1 then 'identity' else null end 
            select @nul_text = case @nulls when 1 then '    null'  else 'not null' end 
     
            if @def_id > 0 
            begin 
                select @def_text = ltrim(rtrim(b.text)) 
                    from sysobjects a, syscomments b 
                        where a.id = @def_id and a.id = b.id 
                 if @@rowcount <> 1 
                begin 
                    print '取default失败%1!', @def_id 
                    goto err 
                end 
                while charindex(@TAB,@def_text) > 0 
                    select @def_text = stuff(@def_text,charindex(@TAB,@def_text),char_length(@TAB),' ') 
                while charindex('  ',@def_text) > 0 
                    select @def_text = stuff(@def_text,charindex('  ',@def_text),char_length('  '),' ') 
                select @def_text = rtrim(ltrim(@def_text)) 
     
            end 
            else 
                select @def_text = null 
     
            declare @thiscol varchar(500) 
            select @thiscol = 
                    case when char_length(@colname) <= 10 then left(@colname+space(10),10) else @colname end  
                    + ' ' + case when char_length(@typename) <= 15 then left(@typename+space(15),15) else @typename end 
                    + ' ' + @def_text 
                    + ' ' + @ide_text 
                    + ' ' + @nul_text 
     
            if @i = @col_int and (@have_con = '0' or charindex('P',@indextg) <= 0) 
                select @thiscol  = @thiscol +  '  ' 
            else 
                select @thiscol  = @thiscol + ' ,' 
     
            --如果在sybsystemprocs数据库下提交,以下注释掉 
            declare @colmna varchar(255) 
            select @colmna = null 
            --select @colmna = colmna from knp_colm where tablcd = @tblname and colmcd = @colname 
     
            if ltrim(@colmna) is not null 
                select @thiscol = @thiscol + '    --'+@colmna 
     
            if @prechar <> '$' 
                print '%1!%2!',@prechar, @thiscol 
     
            select @table_dll = @table_dll + @thiscol + @CRNW 
     
            select @i = @i + 1 
            fetch cur_col into @colname, @usertype, @typename, @length, @prec, @scale, @def_id, @nulls, @ident 
        end 
    end 
 
    if @have_con = '1' and charindex('P',@indextg) > 0 
    begin 
 
        select @cns_name = name, @status = status, @indid = indid 
            from sysindexes where id = @obj_id and status2 & 2 = 2 
 
        --print 'exist constraint... status = %1!', @status 
 
        if @indid = 1  
            select @non_clu = 'clustered' 
        else if @indid > 1 
        begin 
            if  @status & 16 = 16 
                select @non_clu = 'clustered' 
            else 
                select @non_clu = 'nonclustered' 
        end 
 
        if @status & 2048 = 2048 
            select @uni_pri = 'primary key' 
        else 
            select @uni_pri = 'unique' 
 
        select @cns_text = 'constraint ' + @cns_name + ' ' + @uni_pri + ' ' + @non_clu 
 
        select   @i = 1, @keys = '' 
        select @thiskey = index_col(@tblname, @indid, @i) 
        while @thiskey <> null 
        begin 
            if @i > 1 
            begin 
                select @keys = @keys + ", " 
            end 
 
            if ltrim(@keys) is null 
                select @keys = @thiskey 
            else 
                select @keys = @keys + @thiskey 
 
            select @sorder = index_colorder(@tblname, @indid, @i) 
            if (@sorder = "DESC") 
                 select @keys = @keys + " " + @sorder 
 
            select @i = @i + 1 
            select @thiskey = index_col(@tblname, @indid, @i) 
        end 
 
        select @cns_text = @cns_text + ' (' + @keys + ')' 
 
        if ltrim(@table_seg) is null begin 
            select @table_seg = s.name 
                from sysobjects o, syssegments s, sysindexes i 
                    where o.id = object_id(@tblname) 
                        and i.id = o.id 
                        and i.indid < 2  
                        and i.segment = s.segment 
            if @@rowcount = 0 begin 
                print '表%1!所在的段不存在',@tblname 
                goto err 
            end 
        end 
 
        if charindex('T',@indextg) <= 0 
             select @cns_text = 'alter table '+@dbname+@username + '.'+@table_name+' add '+@cns_text+ " on '" + @table_seg + "'" 
        if @prechar <> '$' 
            print '%1!%2!',@prechar,@cns_text 
 
        select @table_dll = @table_dll + @cns_text 
 
    end 
 
    if charindex('T',@indextg) > 0 begin 
        if @prechar <> '$' 
            print '%1!%2!',@prechar, ') ' 
     
        select @table_dll = left(@table_dll,char_length(@table_dll)-1) +  @CRNW + ')' 
     
        --表锁计划 
        if @sysstat2 & 8192 = 8192 
            select @lock_scheme = 'lock allpages' 
        else if @sysstat2 & 16384 =  16384 
            select @lock_scheme = 'lock datapages' 
        else if @sysstat2 & 32768 = 32768 
            select @lock_scheme = 'lock datarows' 
        select @table_dll = @table_dll + @CRNW + @lock_scheme 
     
        if @prechar <> '$' 
            print '%1!%2!',@prechar, @lock_scheme 
     
        select @table_seg = "on '"+ @table_seg+"'" 
        select @table_dll = @table_dll + @CRNW + @table_seg + @CRNW+'go'+@CRNW 
     
        if @prechar <> '$' begin 
            print '%1!%2!',@prechar, @table_seg 
            print '%1!go',@prechar 
        end 
    end 
 
    if ltrim(@prxytx)  is not null or @sysstat2 & 1024 = 1024 
        goto ok 
 
    if charindex('T',@indextg) > 0 begin 
        declare @part_num int,@partition varchar(255) 
        select @part_num = count(*) 
            from syspartitions 
            where id = object_id(@tblname) 
        if @part_num <> 0 begin 
            select @partition = 'alter table '+ @username + '.' + @table_name + ' partition '+convert(varchar,@part_num) 
            select @table_dll = @table_dll + @CRNW + @partition 
            if @prechar <> '$' 
                print '%1!%2!',@prechar, @partition 
        end 
    end 
 
    --select @table_dll as table_dll 
    ------------------------------------------------------------------------------------- 
    --检查其他索引 
    declare @idx_seg  varchar(32) 
    if charindex('I',@indextg) > 0 or charindex('J',@indextg) > 0 begin 
        if exists  (select 1 from sysindexes where id = @obj_id and indid <> 0 and  
            (status2 & 2 <> 2 or charindex('P',@indextg) <= 0 and charindex('J',@indextg) <= 0)) 
 
        begin 
            declare cur_idx cursor for 
                select name, indid, status from sysindexes 
                    where id = @obj_id and indid <> 0 and  
            (status2 & 2 <> 2 or charindex('P',@indextg) <= 0 and charindex('J',@indextg) <= 0) 
--                  (status2 & 2 <> 2 or charindex('P',@indextg) <= 0) 
            open cur_idx 
            fetch cur_idx into @idx_name, @indid, @status 
            while @@sqlstatus = 0  
            begin 
     
                if @indid = 1 
                    select @non_clu = 'clustered' 
                else if @indid > 1 
                begin 
                    if  @status & 16 = 16 
                        select @non_clu = 'clustered' 
                    else 
                        select @non_clu = 'nonclustered' 
                end 
     
                if @status & 2 = 2 
                    select @non_uni = 'unique ' 
                else 
                     select @non_uni = null 
     
                select @i = 1,@keys = '' 
                select @thiskey = index_col(@tblname, @indid, @i) 
                while @thiskey <> null 
                begin 
                    if @i > 1 
                      begin 
                        select @keys = @keys + ", " 
                    end 
     
                    if ltrim(@keys) is null 
                        select @keys = @thiskey 
                    else 
                         select @keys = @keys + @thiskey 
     
                    select @sorder = index_colorder(@tblname, @indid, @i) 
                    if @sorder = "DESC" 
                        select @keys = @keys + " " + @sorder 
     
                    select @i = @i + 1 
                    select @thiskey = index_col(@tblname, @indid, @i) 
                end 
     
                if ltrim(@index_seg) is null begin  
                    select @idx_seg = s.name 
                        from syssegments s, sysindexes i 
                            where s.segment = i.segment 
                                and i.id = object_id(@tblname) 
                                and i.indid = @indid 
                    if @@rowcount = 0 begin 
                         print '索引%1!所在的段不存在',@idx_name  
                        goto err 
                    end 
                end 
                else 
                    select @idx_seg = @index_seg 
     
                if ltrim(@keys) is not null begin 
                    declare @thisidx varchar(500) 
                    select @thisidx = 'create ' + @non_uni 
                        + @non_clu + ' index ' + @idx_name + ' on ' + @dbname + @username 
                        + '.' + @table_name + "(" + @keys + ") on '" +@idx_seg+"'" 
     
                    select @index_dll = @index_dll + @thisidx + @CRNW 
                    if @prechar <> '$' 
                        print '%1!%2!',@prechar, @thisidx 
                end  
     
                fetch cur_idx into @idx_name, @indid, @status 
            end 
     
            if ltrim(@index_dll) is not null begin 
                if @droptg <> '0' begin 
                    select @index_dll = @index_dll + 'go' + @CRNW 
                    if @prechar <> '$' 
                        print '%1!go',@prechar 
                end 
            end 
     
            select @table_dll = @table_dll + @CRNW + @index_dll 
        end 
    end 
ok: 
    set nocount off 
    return 0 
err: 
    set nocount off 
    return -1 
end 
go
 

  • 本文链接地址:http://www.sybrepair.com/get-table-definition-syntax-sp_gettabledll.htm
  • 本文为dbainfo个人原创,请在尊重作者劳动成果的前提下进行转载;
  • 转载务必注明原始出处 : Sybase数据库技术,数据库恢复专家
  • 对《Sybase自动生成数据库内所有表的DDL语句的存储过程》有何疑问或见解,请在本文下方发表;
  • 对网站还有其他问题或建议,请提交在留言板,谢谢!
    1. Eisen
      2011-12-23 10:57:50

      发现了andkylee的老家了,漂亮……

    2. Eisen
      2011-12-23 10:59:57

      这个过程写得非常漂亮,佩服……

    3. Eisen
      2011-12-23 14:44:59

      提点意见:Line 55那里判断table是否存在时,可以写成
      where (name = @tblname or user_name(uid)+’.’+name=@tblname) and type = ‘U’

      这样防止一个库内含有不同user的同名表……

    4. heloonghan
      2012-08-06 18:11:15

      1> create table t4
      2> (id int,
      3> name varchar(10)
      4> )
      5> lock datarows
      6> with exp_row_size=1
      7> go

      1> insert into t4 values(1,’test’)
      2> go
      (1 row affected)

      1> sp_gettabledll t4
      2> go

      if exists(select 1 from sysobjects where name = ‘t4’ and type = ‘U’)
      drop
      table dbo.t4
      go

      create table dbo.t4 (
      id int not null ,
      name varchar(10) not null
      )
      lock datarows
      on ‘default’
      go
      (return status = 0)

      如上测试过程,在建立表t4时指定with exp_row_size=1
      选项,然后调用存储过程sp_gettabledll,生成的t4的ddl
      语句没有with exp_row_size=1 这个部分,使用sybase
      central 查看建表ddl是有with exp_row_size=1 这个部分
      的,存储过程sp_gettabledll应该完善下

      • dbainfo
        2012-08-06 18:45:02

        恩。 的确如您所说。存储过程sp_gettabledll没有提取表的一些存储属性。以后我会完善一下。

    :wink: :twisted: :roll: :oops: :mrgreen: :lol: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-D :-? :) :( :!: 8-O 8)