Technical Article

Script tables to emulate Copy in Enterprise Manage

,

This script will produce the same output as doing a Copy in enterprise manager and then pasting into Query Analyser.

It can handle Clustered and Nonclustered Primary Keys, Multiple Foreign Keys, Defaults, Constraints, Identity Fields.  If you are able to improve this script, or find any bugs, please let me know.

create proc usp_scripttables @script_table varchar(256) as

begin

	set nocount on
	
	
	declare @mincols int
	declare @maxcols int
	declare @count int
	declare @statement varchar(8000)
	declare @table_name varchar(256)
	declare @table_id int
	declare @ptr binary(16)
	declare @txtlen int
	declare @default varchar(8000)
	declare @default_name varchar(256)
	declare @default_id int
	declare @status int
	declare @clustered int
	declare @indid int
	declare @ftable_id int
	declare @ftable_name varchar(256)
	declare @iscomputed int
	declare @incr varchar(10)
	declare @seed varchar(10)



	select @table_name = @script_table
	
	
	select @table_id = id from sysobjects
	where name = @table_name
	and xtype = 'U'
	
	if @table_id <> 0 
	begin
		--min no of columns in the table
		select @mincols = min(colid) from syscolumns
		where id = @table_id
		
		--max no of columns in the table
		select @maxcols = max(colid) from syscolumns
		where id = @table_id
		
		
		create table #sql_statements (sql_id int identity (1,1), string text)
		
		select @statement = 'CREATE TABLE [' + @table_name + '] (' + char(13)
		
		
		insert into #sql_statements (string) values(@statement)
		
		
		select @ptr = TEXTPTR(string),
		@txtlen = DATALENGTH(string)
		from #sql_statements
		
		
		select @count = 1
		
		
		while @count < @maxcols + 1
		begin
			--Each column


			--This is failing when there is more than one foreign key on a column
			select @default_id = cdefault from syscolumns
			where id = @table_id and colid = @count

			select @default_name = name from sysobjects where id = @default_id
			select @default = text from syscomments where id = @default_id


			select @iscomputed = iscomputed from syscolumns where id = @table_id and colid = @count

			select @seed = IDENT_SEED(name) from sysobjects
			where IDENT_SEED(name) IS NOT NULL
			and id = @table_id

			select @incr = IDENT_INCR(name) from sysobjects
			where IDENT_INCR(name) IS NOT NULL
			and id = @table_id



	
			if @iscomputed = 0
			begin
				select @statement = space(13) + '[' + name + '] [' + type_name(xtype) + ']'
				+ case 
				when type_name(xtype) in ('decimal','numeric') then 
				' ('+ convert(varchar,prec) + ',' + convert(varchar,length) + ')' 
				+ case when autoval is null then '' else ' IDENTITY(' + @seed + ',' + @incr + ')' end 
				+ CASE when isnullable=0 THEN ' NOT NULL' ELSE ' NULL' END 
				WHEN type_name(xtype) IN ('float','real') THEN 
				' ('+ convert(varchar,prec) + ')' 
				+ case when autoval is null then '' else ' IDENTITY(' + @seed + ',' + @incr + ')' 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) + ')' 
				+ ' COLLATE ' + collation 
				+ case when autoval is null then '' else ' IDENTITY(' + @seed + ',' + @incr + ')' end 
				+ CASE when isnullable=0 THEN ' NOT NULL' ELSE ' NULL' END 
				--ie int
				ELSE
				+ case when autoval is null then '' else ' IDENTITY(' + @seed + ',' + @incr + ')' end 
				+ CASE when isnullable=0 THEN ' NOT NULL' ELSE ' NULL' END 
				end
				from syscolumns
				where colid = @count
				and id = @table_id
			end
			else
			begin


				select @statement = space(13) + '[' + name + '] AS ' 
				from syscolumns
				where colid = @count
				and id = @table_id

				select @default = text from syscomments where id = @table_id and number = @count
				select @statement = @statement + @default + ' ,' + char(13)

				UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
				select @ptr = TEXTPTR(string),
				@txtlen = DATALENGTH(string)
				from #sql_statements

			end
		
			if (len(@default) > 0)
			begin
				select @statement = @statement + ' CONSTRAINT [' + @default_name + '] DEFAULT ' + @default
				select @default = ''
			end
		
		
			if (@count < @maxcols)
			begin
			 select @statement = @statement + ' ,'
			end
		
			if @count = @maxcols
			begin
				select @default_id = constid from sysconstraints where id=@table_id and colid=0
		
				if @default_id <> 0
				begin
					 select @statement = @statement + ' ,'
				end
		
			end
		
			select @statement = @statement + char(13)
		
		
		
			UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
			select @ptr = TEXTPTR(string),
			@txtlen = DATALENGTH(string)
			from #sql_statements
		
		
			select @count = @count + 1
		end
		
		
		
		--Do the Primary Keys
		--Table constraints

	
		select @default_id = id from sysobjects where parent_obj=@table_id
		and xtype = 'PK'
		
		if @default_id <> 0
		begin
		
	
			select @default_name = name from sysobjects where id = @default_id
		
		
			select @statement = space(13) + 'CONSTRAINT [' + @default_name + '] PRIMARY KEY'
		
			
			select @clustered = indid from sysindexes
			where id = @table_id
			and name = @default_name
		
		
			if @clustered = 1 
			begin
				select @statement = @statement + ' CLUSTERED' + char(13) + space(13) + '(' + char(13)
			end
			else 
			if @clustered > 1 and @clustered <> 255
			begin
				select @statement = @statement + ' NONCLUSTERED' + char(13) + space(13) + '(' + char(13)
			end
		
		
			UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
			select @ptr = TEXTPTR(string),
			@txtlen = DATALENGTH(string)
			from #sql_statements
		
		
			select @indid = indid from sysindexes
			where id = @table_id
			and name = @default_name
		
		
		
			declare cols cursor for
			select colid from sysindexkeys
			where id = @table_id
			and indid = @indid
		
		
			open cols
		
			fetch next from cols into @count
		
		
			while @@FETCH_STATUS =0
			begin
				select @statement = space(24) + '[' + name + ']' from syscolumns
				where colid = @count
				and id = @table_id
		
				fetch next from cols into @count
		
				if @@FETCH_STATUS =0 
				begin	
					select @statement = @statement + ' ,' + char(13)
				end
		
		
				UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
				select @ptr = TEXTPTR(string),
				@txtlen = DATALENGTH(string)
				from #sql_statements
		
			end
		
		
			close cols
			
			deallocate cols
		
		
		
			select @statement = char(13) + space(13) + ') ON [PRIMARY]'
		
			select @default_id = 0

		
			select @default_id = id from sysobjects where parent_obj=@table_id
			and xtype = 'FK'



		
			if @default_id <> 0 
			begin
				select @statement = @statement + ' ,'
			end
			
			select @statement = @statement + char(13)
		
			UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
			select @ptr = TEXTPTR(string),
			@txtlen = DATALENGTH(string)
			from #sql_statements
		
		
		end
		
		
		
		
		
		
		--Do the Foreign Keys
		--Table constraints


		--This needs to be looped as you can have more than one foreign key on a table
		
		select @default_id = 0


		declare foreignkeys cursor for
		select id from sysobjects
		where parent_obj = @table_id
		and xtype = 'F'


--		select @table_id

		open foreignkeys

		fetch next from foreignkeys into @default_id
		
		
		--This loop needs fixing as the comma's are in the wrong place
		--and it doesn't loop correctly for multiple foreign keys


		WHILE @@FETCH_STATUS =0
		begin
		
			select @default_name = name from sysobjects where id = @default_id
		
		
			select @statement = space(13) + 'CONSTRAINT [' + @default_name + '] FOREIGN KEY' + char(13) + space(13) + '(' + char(13)
		
			
			select @clustered = indid from sysindexes
			where id = @table_id
			and name = @default_name
		
			UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
			select @ptr = TEXTPTR(string),
			@txtlen = DATALENGTH(string)
			from #sql_statements
		

			--Need to link it to the columns 
			declare cols cursor for
			select fkey from sysforeignkeys
			where fkeyid = @table_id
			and constid = @default_id
		
--			select @table_id
--			select @default_id
		
			open cols
		
			fetch next from cols into @count
		
			while @@FETCH_STATUS =0
			begin
				select @statement = space(24) + '[' + name + ']' from syscolumns
				where colid = @count
				and id = @table_id
		
				fetch next from cols into @count
		
				if @@FETCH_STATUS =0 
				begin	
					select @statement = @statement + ' ,' + char(13)
				end
		
		
				UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
				select @ptr = TEXTPTR(string),
				@txtlen = DATALENGTH(string)
				from #sql_statements
		
			end
		
		
			close cols
			
			deallocate cols
		
			--References
			declare cols cursor for
			select rkeyid,rkey from sysforeignkeys
			where fkeyid = @table_id
			and constid = @default_id

		
			open cols
		
			fetch next from cols into @ftable_id,@count
		
		
			select @ftable_name = name from sysobjects
			where id = @ftable_id
		
		
			select @statement = char(13) + space(13) + ') REFERENCES [' + @ftable_name + '] (' + char(13) 
		
			UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
			select @ptr = TEXTPTR(string),
			@txtlen = DATALENGTH(string)
			from #sql_statements
		
		
		
			WHILE @@FETCH_STATUS = 0
			begin
		
				select @statement = space(24) + '[' + name + ']' from syscolumns
				where colid = @count
				and id = @ftable_id
		
				fetch next from cols into @ftable_id,@count
		
				if @@FETCH_STATUS =0 
				begin	
					select @statement = @statement + ' ,' + char(13)
				end
				
			
		
				UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
				select @ptr = TEXTPTR(string),
				@txtlen = DATALENGTH(string)
				from #sql_statements
		
				fetch next from cols into @ftable_id,@count
				
			
			end
		
		
			close cols
			deallocate cols
		
		
			select @statement = char(13) + space(13) + ')'


			fetch next from foreignkeys into @default_id

			IF @@FETCH_STATUS = 0
			begin
				select @statement = @statement + ',' + char(13)
			end
			else
			begin
				select @statement=@statement + char(13)
			end
		
		
			UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
			select @ptr = TEXTPTR(string),
			@txtlen = DATALENGTH(string)
			from #sql_statements
		
		
		end
		

		close foreignkeys

		deallocate foreignkeys


		select @statement = char(13) +  ') ON [PRIMARY]' + char(13) + 'GO'
		
		UPDATETEXT #sql_statements.string @ptr @txtlen 0 @statement
		
		select @ptr = TEXTPTR(string),
		@txtlen = DATALENGTH(string)
		from #sql_statements
		
		select string from #sql_statements
		
		drop table #sql_statements
	
	
	end
	else
	begin
		RAISERROR('The specified table does not exist in the catalog',16,1)
	end

end

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating