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
	 
发现了andkylee的老家了,漂亮……
呵呵,谢谢!
这个过程写得非常漂亮,佩服……
提点意见:Line 55那里判断table是否存在时,可以写成
where (name = @tblname or user_name(uid)+’.’+name=@tblname) and type = ‘U’
这样防止一个库内含有不同user的同名表……
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应该完善下
恩。 的确如您所说。存储过程sp_gettabledll没有提取表的一些存储属性。以后我会完善一下。