董晓涛(David Dong)

博客园 首页 新随笔 联系 订阅 管理
-- --
 --exec Up_ExportTables 'Customers'
-- When you want to export a table structure to T-SQL, everyone always points you to Enterprise Manager, or a script that calls BCP.
-- Sometimes, a developer either doesn't have access to those tools, or just doesn't want to use them (like me) out of spite.
-- I made this T-SQL because it was educational, and noone else seems to have done it yet.
-- ideally, with this script AND the sp_generate_inserts script from http://vyaskn.tripod.com/code.htm, you could use a loop to export both the definition of a table, And then it's contents.
-- please, if you take this script and make it better, please email me a copy at lowell@stormrage.com so I can learn from your improvements.
--
-- Best to view the results in Query Analyzer Results in Text (Control +T)
--
-- Known limitations at this time:
-- 1.Doesn't add the check constraint's yet, only the implied PK AND Unique Constraints.
-- 2.Doesn't add the indexes for the table yet.
-- 3. Completely ignores the optional COLLATE statement because I never use it when creating a varchar; ie  COLLATE SQL_Latin1_General_CP1_CI_AS
 
CREATE PROCEDURE Up_ExportTables
-- USAGE: sp_ExportTables gmproj
@table_name    varchar(32)
as
begin

Create Table #CreateStatements    (uid int identity(1,1),Info    text)

DECLARE @table_id int,
    @CurrColumn    int,
    @MaxColumn    int,
    @CreateStatement    varchar(8000),
    @ColumnTypeName        varchar(255),
    @uid    int,
    @i    int,
    @primary_key_field varchar(50)

    select @table_id=id from sysobjects where xtype='U' and [name] <> 'dtproperties' and [name] = @table_name
    /*Since a table can have only one Primary key, get the column name for this table(if any) that is the PK*/
    select @primary_key_field = convert(varchar(32),c.name)
        from
         sysindexes i, syscolumns c, sysobjects o, syscolumns c1
        where
         o.id = @table_id
         and o.id = c.id
         and o.id = i.id
         and (i.status & 0x800) = 0x800
         and c.name = index_col (@table_name, i.indid, c1.colid)
         and c1.colid <= i.keycnt
         and c1.id = @table_id
    Select @CreateStatement = CHAR(13) + 'CREATE TABLE [' + [name] + '] ( ' from SYSOBJECTS WHERE ID=@TABLE_ID
    --For Each Column
    Select @CurrColumn=Min(colid),@MaxColumn = Max(colid) from syscolumns where id= @table_id
    --Select * from syscolumns where id=1511676433

    while @currColumn <= @MaxColumn
        begin
       
        --print @currColumn
        Declare @UQIndex int, @DefaultValue nvarchar(4000)
        set @DefaultValue = null
        select @DefaultValue=text from syscomments where id=
            (select constid from sysconstraints where id=@table_id and colid=@currColumn)

            --Process different Column Types differently
            SELECT @CreateStatement = @CreateStatement + CHAR(13) + '[' + [name] + '] ' + type_name(xtype) +
                case   
                    --ie numeric(10,2)
                    WHEN  type_name(xtype) IN ('decimal','numeric') THEN   
                        ' ('+ convert(varchar,prec) + ',' + convert(varchar,length) + ')'
                        + case when autoval is null then '' else ' IDENTITY(1,1)' end   
                        + CASE when isnullable=0 THEN  ' NOT NULL' ELSE ' NULL' END
                    --ie float(53)     
                    WHEN  type_name(xtype) IN ('float','real') THEN   
                        ' ('+ convert(varchar,prec) + ')'
                        + case when autoval is null then '' else ' IDENTITY(1,1)' end   
                        + CASE when isnullable=0 THEN  ' NOT NULL' ELSE ' NULL' END
                    --ie varchar(40)
                    WHEN  type_name(xtype) IN ('char','varchar','nchar','nvarchar') THEN
                        ' ('+ convert(varchar,length) + ')' 
                        + case when autoval is null then '' else ' IDENTITY(1,1)' end
                        + CASE when isnullable=0 THEN  ' NOT NULL' ELSE ' NULL' END
                    --ie int
                    ELSE
                        + case when autoval is null then '' else ' IDENTITY(1,1)' end
                        + CASE when isnullable=0 THEN  ' NOT NULL' ELSE ' NULL' END
                end
            --code to determine if 'PRIMARY KEY'
            + CASE when syscolumns.name = @primary_key_field THEN ' PRIMARY KEY' else '' END
            + CASE when @DefaultValue is null then ''
            ELSE
                CASE
                WHEN  type_name(xtype) IN ('decimal','numeric','float','real','bigint','int','smallint','tinyint','money','smallmoney') THEN
                    ' DEFAULT ' + convert(varchar,@DefaultValue)
                ELSE
                    ' DEFAULT ' + convert(varchar,@DefaultValue)
                END
            END
             + ',' from syscolumns where id=@table_id and colid=@CurrColumn

        Select @CurrColumn = @CurrColumn + 1
        end
        insert into #CreateStatements(Info) values(@CreateStatement)
        SELECT @CreateStatement=''
        select @uid=@@IDENTITY

        --CODE TO ADD ALL THE FOREIGN KEYS TO THE BOTTOM OF THE STATEMENT
        declare @cursorID    int
        declare c1 cursor for SELECT fkeyid from sysforeignkeys where fkeyid=@table_id
            open c1
            fetch next from c1 into @cursorID
           
            SELECT @CreateStatement=@CreateStatement +
            (select + CHAR(13) +'FOREIGN KEY (' +   [syscolumns].[name] + ') REFERENCES ' from syscolumns where id=fkeyid and colid =fkey) +
            (select (SELECT distinct [sysobjects].[name] from sysobjects where id=rkeyid) + '(' + [syscolumns].[name] + '),' from syscolumns where id=rkeyid and colid =rkey)
             from sysforeignkeys where fkeyid=@table_id
               
            close c1
            deallocate c1
        --CODE TO ADD ALL THE UNIQUE CONSTRAINTS TO THE BOTTOM OF THE DEFINITION.
        declare c1 cursor for select id from sysobjects where xtype='UQ' and parent_obj=@table_id
        open c1
        fetch next from c1 into @cursorID
            --adapted shamelessly from sp_helpconstraints
            while @@fetch_status >= 0
            begin
                declare @indid smallint
                SELECT @indid = indid,@CreateStatement=@CreateStatement + CHAR(13) + 'CONSTRAINT ' + object_name(@cursorID) + ' UNIQUE '
                 + case when (status & 16)=16 then ' CLUSTERED' else ' NONCLUSTERED' end
                from    sysindexes
                where    name = object_name(@cursorID) and id = @table_ID
                    declare @thiskey nvarchar(131), -- 128+3
                        @keys     nvarchar(2126) -- a specific size for MS for whatever reason
       
                    select @keys = index_col(@table_name, @indid, 1), @i = 2
                    if (indexkey_property(@table_id, @indid, 1, 'isdescending') = 1)
                        select @keys = @keys  + '(-)'
       
                    select @thiskey = index_col(@table_name, @indid, @i)
                    if ((@thiskey is not null) and (indexkey_property(@table_ID, @indid, @i, 'isdescending') = 1))
                        select @thiskey = @thiskey + '(-)'
       
                    while (@thiskey is not null)
                    begin
                        select @keys = @keys + ', ' + @thiskey, @i = @i + 1
                        select @thiskey = index_col(@table_name, @indid, @i)
                        if ((@thiskey is not null) and (indexkey_property(@table_ID, @indid, @i, 'isdescending') = 1))
                            select @thiskey = @thiskey + '(-)'
                    end
                    Select @CreateStatement=@CreateStatement + '(' + @keys + '),'
            fetch next from c1 into @cursorID
            end
        close c1
        deallocate c1
            --CODE TO ADD CHECK CONSTRAINTS TO THE BOTTOM OF THE DEFINITION?

            --CODE TO ADD INDEXES TO THE BOTTOM OF THE DEFINITION?

        --at this point, there is a trailing comma, or it blank
        DECLARE @ptrval binary(16),@txtlen INT
        if len(@CreateStatement) > 0
        BEGIN
            SELECT @ptrval = TEXTPTR(info) ,
            @txtlen = DATALENGTH(info)
               FROM #CreateStatements
                  WHERE uid=@uid
            UPDATETEXT #CreateStatements.info @ptrval @txtlen 0 @CreateStatement
        END
       
        --note that this trims the trailing comma from the end of the statement
        SELECT @ptrval = TEXTPTR(info) ,
        @txtlen = DATALENGTH(info) - 1
           FROM #CreateStatements
              WHERE uid=@uid
       
        SELECT @CreateStatement= ')'+ CHAR(13)    
        UPDATETEXT #CreateStatements.info @ptrval @txtlen 1 @CreateStatement

Select info from #CreateStatements
drop table #CreateStatements
end

posted on 2005-06-29 12:21  董晓涛  阅读(631)  评论(0编辑  收藏  举报