我花了很多时间来解决这个问题的解决方案,所以本帖子的精神,我在这里发布,因为我觉得它可能对其他人有用.
如果有人有更好的脚本或任何要添加的内容,请发布.
编辑:是的,我知道如何在Management Studio中执行此操作 - 但我需要能够在另一个应用程序中执行此操作.
我已修改上面的版本以运行所有表并支持新的SQL 2005数据类型.它还保留主键名称.仅适用于SQL 2005(使用交叉应用).
select 'create table [' + so.name + '] (' + o.list + ')' + CASE WHEN tc.Constraint_Name IS NULL THEN '' ELSE 'ALTER TABLE ' + so.Name + ' ADD CONSTRAINT ' + tc.Constraint_Name + ' PRIMARY KEY ' + ' (' + LEFT(j.List, Len(j.List)-1) + ')' END from sysobjects so cross apply (SELECT ' ['+column_name+'] ' + data_type + case data_type when 'sql_variant' then '' when 'text' then '' when 'ntext' then '' when 'xml' then '' when 'decimal' then '(' + cast(numeric_precision as varchar) + ', ' + cast(numeric_scale as varchar) + ')' else coalesce('('+case when character_maximum_length = -1 then 'MAX' else cast(character_maximum_length as varchar) end +')','') end + ' ' + case when exists ( select id from syscolumns where object_name(id)=so.name and name=column_name and columnproperty(id,name,'IsIdentity') = 1 ) then 'IDENTITY(' + cast(ident_seed(so.name) as varchar) + ',' + cast(ident_incr(so.name) as varchar) + ')' else '' end + ' ' + (case when IS_NULLABLE = 'No' then 'NOT ' else '' end ) + 'NULL ' + case when information_schema.columns.COLUMN_DEFAULT IS NOT NULL THEN 'DEFAULT '+ information_schema.columns.COLUMN_DEFAULT ELSE '' END + ', ' from information_schema.columns where table_name = so.name order by ordinal_position FOR XML PATH('')) o (list) left join information_schema.table_constraints tc on tc.Table_name = so.Name AND tc.Constraint_Type = 'PRIMARY KEY' cross apply (select '[' + Column_Name + '], ' FROM information_schema.key_column_usage kcu WHERE kcu.Constraint_Name = tc.Constraint_Name ORDER BY ORDINAL_POSITION FOR XML PATH('')) j (list) where xtype = 'U' AND name NOT IN ('dtproperties')
更新:添加了XML数据类型的处理
更新2:修复了以下情况: 1)有多个具有相同名称但具有不同模式的表,2)有多个表具有相同名称的PK约束
这是我提出的脚本.它处理标识列,默认值和主键.它不处理外键,索引,触发器或任何其他聪明的东西.它适用于SQLServer 2000,2005和2008.
declare @schema varchar(100), @table varchar(100) set @schema = 'dbo' -- set schema name here set @table = 'MyTable' -- set table name here declare @sql table(s varchar(1000), id int identity) -- create statement insert into @sql(s) values ('create table [' + @table + '] (') -- column list insert into @sql(s) select ' ['+column_name+'] ' + data_type + coalesce('('+cast(character_maximum_length as varchar)+')','') + ' ' + case when exists ( select id from syscolumns where object_name(id)=@table and name=column_name and columnproperty(id,name,'IsIdentity') = 1 ) then 'IDENTITY(' + cast(ident_seed(@table) as varchar) + ',' + cast(ident_incr(@table) as varchar) + ')' else '' end + ' ' + ( case when IS_NULLABLE = 'No' then 'NOT ' else '' end ) + 'NULL ' + coalesce('DEFAULT '+COLUMN_DEFAULT,'') + ',' from INFORMATION_SCHEMA.COLUMNS where table_name = @table AND table_schema = @schema order by ordinal_position -- primary key declare @pkname varchar(100) select @pkname = constraint_name from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where table_name = @table and constraint_type='PRIMARY KEY' if ( @pkname is not null ) begin insert into @sql(s) values(' PRIMARY KEY (') insert into @sql(s) select ' ['+COLUMN_NAME+'],' from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where constraint_name = @pkname order by ordinal_position -- remove trailing comma update @sql set s=left(s,len(s)-1) where id=@@identity insert into @sql(s) values (' )') end else begin -- remove trailing comma update @sql set s=left(s,len(s)-1) where id=@@identity end -- closing bracket insert into @sql(s) values( ')' ) -- result! select s from @sql order by id
在msdb论坛中有一个Powershell脚本,它将编写所有表和相关对象的脚本:
# Script all tables in a database [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null $s = new-object ('Microsoft.SqlServer.Management.Smo.Server') '' $db = $s.Databases[' '] $scrp = new-object ('Microsoft.SqlServer.Management.Smo.Scripter') ($s) $scrp.Options.AppendToFile = $True $scrp.Options.ClusteredIndexes = $True $scrp.Options.DriAll = $True $scrp.Options.ScriptDrops = $False $scrp.Options.IncludeHeaders = $False $scrp.Options.ToFileOnly = $True $scrp.Options.Indexes = $True $scrp.Options.WithDependencies = $True $scrp.Options.FileName = 'C:\Temp\ .SQL' foreach($item in $db.Tables) { $tablearray+=@($item) } $scrp.Script($tablearray) Write-Host "Scripting complete"
支持架构:
这是一个更新版本,修正了David等人给出的最佳答案.添加了对命名模式的支持.应该注意的是,如果在各种模式中存在同名的表,则可能会中断.另一个改进是使用官方QuoteName()函数.
SELECT t.TABLE_CATALOG, t.TABLE_SCHEMA, t.TABLE_NAME, 'create table '+QuoteName(t.TABLE_SCHEMA)+'.' + QuoteName(so.name) + ' (' + LEFT(o.List, Len(o.List)-1) + '); ' + CASE WHEN tc.Constraint_Name IS NULL THEN '' ELSE 'ALTER TABLE ' + QuoteName(t.TABLE_SCHEMA)+'.' + QuoteName(so.name) + ' ADD CONSTRAINT ' + tc.Constraint_Name + ' PRIMARY KEY ' + ' (' + LEFT(j.List, Len(j.List)-1) + '); ' END as 'SQL_CREATE_TABLE' FROM sysobjects so CROSS APPLY ( SELECT ' ['+column_name+'] ' + data_type + case data_type when 'sql_variant' then '' when 'text' then '' when 'ntext' then '' when 'decimal' then '(' + cast(numeric_precision as varchar) + ', ' + cast(numeric_scale as varchar) + ')' else coalesce( '('+ case when character_maximum_length = -1 then 'MAX' else cast(character_maximum_length as varchar) end + ')','') end + ' ' + case when exists ( SELECT id FROM syscolumns WHERE object_name(id) = so.name and name = column_name and columnproperty(id,name,'IsIdentity') = 1 ) then 'IDENTITY(' + cast(ident_seed(so.name) as varchar) + ',' + cast(ident_incr(so.name) as varchar) + ')' else '' end + ' ' + (case when IS_NULLABLE = 'No' then 'NOT ' else '' end) + 'NULL ' + case when information_schema.columns.COLUMN_DEFAULT IS NOT NULL THEN 'DEFAULT '+ information_schema.columns.COLUMN_DEFAULT ELSE '' END + ',' -- can't have a field name or we'll end up with XML FROM information_schema.columns WHERE table_name = so.name ORDER BY ordinal_position FOR XML PATH('') ) o (list) LEFT JOIN information_schema.table_constraints tc on tc.Table_name = so.Name AND tc.Constraint_Type = 'PRIMARY KEY' LEFT JOIN information_schema.tables t on t.Table_name = so.Name CROSS APPLY ( SELECT QuoteName(Column_Name) + ', ' FROM information_schema.key_column_usage kcu WHERE kcu.Constraint_Name = tc.Constraint_Name ORDER BY ORDINAL_POSITION FOR XML PATH('') ) j (list) WHERE xtype = 'U' AND name NOT IN ('dtproperties') -- AND so.name = 'ASPStateTempSessions' ;
..
在Management Studio中使用:
上面的sql代码的一个detractor是如果你使用SSMS测试它,长语句不容易阅读.因此,根据这个有用的帖子,这是另一个版本,在点击网格中单元格的链接后,稍微修改一下,以便更容易看到眼睛.对于db中的每个表,结果更容易识别为格式良好的CREATE TABLE语句.
-- settings DECLARE @CRLF NCHAR(2) SET @CRLF = Nchar(13) + NChar(10) DECLARE @PLACEHOLDER NCHAR(3) SET @PLACEHOLDER = '{:}' -- the main query SELECT t.TABLE_CATALOG, t.TABLE_SCHEMA, t.TABLE_NAME, CAST( REPLACE( 'create table ' + QuoteName(t.TABLE_SCHEMA) + '.' + QuoteName(so.name) + ' (' + @CRLF + LEFT(o.List, Len(o.List) - (LEN(@PLACEHOLDER)+2)) + @CRLF + ');' + @CRLF + CASE WHEN tc.Constraint_Name IS NULL THEN '' ELSE 'ALTER TABLE ' + QuoteName(t.TABLE_SCHEMA) + '.' + QuoteName(so.Name) + ' ADD CONSTRAINT ' + tc.Constraint_Name + ' PRIMARY KEY (' + LEFT(j.List, Len(j.List) - 1) + ');' + @CRLF END, @PLACEHOLDER, @CRLF ) AS XML) as 'SQL_CREATE_TABLE' FROM sysobjects so CROSS APPLY ( SELECT ' ' + '['+column_name+'] ' + data_type + case data_type when 'sql_variant' then '' when 'text' then '' when 'ntext' then '' when 'decimal' then '(' + cast(numeric_precision as varchar) + ', ' + cast(numeric_scale as varchar) + ')' else coalesce( '('+ case when character_maximum_length = -1 then 'MAX' else cast(character_maximum_length as varchar) end + ')','') end + ' ' + case when exists ( SELECT id FROM syscolumns WHERE object_name(id) = so.name and name = column_name and columnproperty(id,name,'IsIdentity') = 1 ) then 'IDENTITY(' + cast(ident_seed(so.name) as varchar) + ',' + cast(ident_incr(so.name) as varchar) + ')' else '' end + ' ' + (case when IS_NULLABLE = 'No' then 'NOT ' else '' end) + 'NULL ' + case when information_schema.columns.COLUMN_DEFAULT IS NOT NULL THEN 'DEFAULT '+ information_schema.columns.COLUMN_DEFAULT ELSE '' END + ', ' + @PLACEHOLDER -- note, can't have a field name or we'll end up with XML FROM information_schema.columns where table_name = so.name ORDER BY ordinal_position FOR XML PATH('') ) o (list) LEFT JOIN information_schema.table_constraints tc on tc.Table_name = so.Name AND tc.Constraint_Type = 'PRIMARY KEY' LEFT JOIN information_schema.tables t on t.Table_name = so.Name CROSS APPLY ( SELECT QUOTENAME(Column_Name) + ', ' FROM information_schema.key_column_usage kcu WHERE kcu.Constraint_Name = tc.Constraint_Name ORDER BY ORDINAL_POSITION FOR XML PATH('') ) j (list) WHERE xtype = 'U' AND name NOT IN ('dtproperties') -- AND so.name = 'ASPStateTempSessions' ;
不要强调这一点,但这里是用于比较的功能相同的示例输出:
-- 1 (scripting version) create table [dbo].[ASPStateTempApplications] ( [AppId] int NOT NULL , [AppName] char(280) NOT NULL ); ALTER TABLE [dbo].[ASPStateTempApplications] ADD CONSTRAINT PK__ASPState__8E2CF7F908EA5793 PRIMARY KEY ([AppId]); -- 2 (SSMS version) create table [dbo].[ASPStateTempSessions] ( [SessionId] nvarchar(88) NOT NULL , [Created] datetime NOT NULL DEFAULT (getutcdate()), [Expires] datetime NOT NULL , [LockDate] datetime NOT NULL , [LockDateLocal] datetime NOT NULL , [LockCookie] int NOT NULL , [Timeout] int NOT NULL , [Locked] bit NOT NULL , [SessionItemShort] varbinary(7000) NULL , [SessionItemLong] image(2147483647) NULL , [Flags] int NOT NULL DEFAULT ((0)) ); ALTER TABLE [dbo].[ASPStateTempSessions] ADD CONSTRAINT PK__ASPState__C9F4929003317E3D PRIMARY KEY ([SessionId]);
..
扣除因素:
应该指出的是,由于缺乏对主键之外的其他许可的支持,我对此仍然相对不满意.它仍然适合用作简单数据导出或复制的机制.
如果要生成脚本的应用程序是.NET应用程序,则可能需要查看使用SMO(Sql管理对象).引用此SQL Team链接,了解如何使用SMO编写脚本对象.
另外一个带有外键支持的变体,在一个声明中:
SELECT obj.name ,'CREATE TABLE [' + obj.name + '] (' + LEFT(cols.list, LEN(cols.list) - 1 ) + ')' + ISNULL(' ' + refs.list, '') FROM sysobjects obj CROSS APPLY ( SELECT CHAR(10) + ' [' + column_name + '] ' + data_type + CASE data_type WHEN 'sql_variant' THEN '' WHEN 'text' THEN '' WHEN 'ntext' THEN '' WHEN 'xml' THEN '' WHEN 'decimal' THEN '(' + CAST(numeric_precision as VARCHAR) + ', ' + CAST(numeric_scale as VARCHAR) + ')' ELSE COALESCE('(' + CASE WHEN character_maximum_length = -1 THEN 'MAX' ELSE CAST(character_maximum_length as VARCHAR) END + ')', '') END + ' ' + case when exists ( -- Identity skip select id from syscolumns where object_name(id) = obj.name and name = column_name and columnproperty(id,name,'IsIdentity') = 1 ) then 'IDENTITY(' + cast(ident_seed(obj.name) as varchar) + ',' + cast(ident_incr(obj.name) as varchar) + ')' else '' end + ' ' + CASE WHEN IS_NULLABLE = 'No' THEN 'NOT ' ELSE '' END + 'NULL' + CASE WHEN information_schema.columns.column_default IS NOT NULL THEN ' DEFAULT ' + information_schema.columns.column_default ELSE '' END + ',' FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = obj.name ORDER BY ordinal_position FOR XML PATH('') ) cols (list) CROSS APPLY( SELECT CHAR(10) + 'ALTER TABLE ' + obj.name + '_noident_temp ADD ' + LEFT(alt, LEN(alt)-1) FROM( SELECT CHAR(10) + ' CONSTRAINT ' + tc.constraint_name + ' ' + tc.constraint_type + ' (' + LEFT(c.list, LEN(c.list)-1) + ')' + COALESCE(CHAR(10) + r.list, ', ') FROM information_schema.table_constraints tc CROSS APPLY( SELECT '[' + kcu.column_name + '], ' FROM information_schema.key_column_usage kcu WHERE kcu.constraint_name = tc.constraint_name ORDER BY kcu.ordinal_position FOR XML PATH('') ) c (list) OUTER APPLY( -- // http://stackoverflow.com/questions/3907879/sql-server-howto-get-foreign-key-reference-from-information-schema SELECT ' REFERENCES [' + kcu1.constraint_schema + '].' + '[' + kcu2.table_name + ']' + '(' + kcu2.column_name + '), ' FROM information_schema.referential_constraints as rc JOIN information_schema.key_column_usage as kcu1 ON (kcu1.constraint_catalog = rc.constraint_catalog AND kcu1.constraint_schema = rc.constraint_schema AND kcu1.constraint_name = rc.constraint_name) JOIN information_schema.key_column_usage as kcu2 ON (kcu2.constraint_catalog = rc.unique_constraint_catalog AND kcu2.constraint_schema = rc.unique_constraint_schema AND kcu2.constraint_name = rc.unique_constraint_name AND kcu2.ordinal_position = KCU1.ordinal_position) WHERE kcu1.constraint_catalog = tc.constraint_catalog AND kcu1.constraint_schema = tc.constraint_schema AND kcu1.constraint_name = tc.constraint_name ) r (list) WHERE tc.table_name = obj.name FOR XML PATH('') ) a (alt) ) refs (list) WHERE xtype = 'U' AND name NOT IN ('dtproperties') AND obj.name = 'your_table_name'
您可以尝试使用sqlfiddle:http://sqlfiddle.com/#!6/e3b66/3/0
我修改了接受的答案,现在它可以在某个模式中获得包括主键和外键的命令.
declare @table varchar(100) declare @schema varchar(100) set @table = 'Persons' -- set table name here set @schema = 'OT' -- set SCHEMA name here declare @sql table(s varchar(1000), id int identity) -- create statement insert into @sql(s) values ('create table ' + @table + ' (') -- column list insert into @sql(s) select ' '+column_name+' ' + data_type + coalesce('('+cast(character_maximum_length as varchar)+')','') + ' ' + case when exists ( select id from syscolumns where object_name(id)=@table and name=column_name and columnproperty(id,name,'IsIdentity') = 1 ) then 'IDENTITY(' + cast(ident_seed(@table) as varchar) + ',' + cast(ident_incr(@table) as varchar) + ')' else '' end + ' ' + ( case when IS_NULLABLE = 'No' then 'NOT ' else '' end ) + 'NULL ' + coalesce('DEFAULT '+COLUMN_DEFAULT,'') + ',' from information_schema.columns where table_name = @table and table_schema = @schema order by ordinal_position -- primary key declare @pkname varchar(100) select @pkname = constraint_name from information_schema.table_constraints where table_name = @table and constraint_type='PRIMARY KEY' if ( @pkname is not null ) begin insert into @sql(s) values(' PRIMARY KEY (') insert into @sql(s) select ' '+COLUMN_NAME+',' from information_schema.key_column_usage where constraint_name = @pkname order by ordinal_position -- remove trailing comma update @sql set s=left(s,len(s)-1) where id=@@identity insert into @sql(s) values (' )') end else begin -- remove trailing comma update @sql set s=left(s,len(s)-1) where id=@@identity end -- foreign key declare @fkname varchar(100) select @fkname = constraint_name from information_schema.table_constraints where table_name = @table and constraint_type='FOREIGN KEY' if ( @fkname is not null ) begin insert into @sql(s) values(',') insert into @sql(s) values(' FOREIGN KEY (') insert into @sql(s) select ' '+COLUMN_NAME+',' from information_schema.key_column_usage where constraint_name = @fkname order by ordinal_position -- remove trailing comma update @sql set s=left(s,len(s)-1) where id=@@identity insert into @sql(s) values (' ) REFERENCES ') insert into @sql(s) SELECT OBJECT_NAME(fk.referenced_object_id) FROM sys.foreign_keys fk INNER JOIN sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id INNER JOIN sys.columns c1 ON fkc.parent_column_id = c1.column_id AND fkc.parent_object_id = c1.object_id INNER JOIN sys.columns c2 ON fkc.referenced_column_id = c2.column_id AND fkc.referenced_object_id = c2.object_id where fk.name = @fkname insert into @sql(s) SELECT '('+c2.name+')' FROM sys.foreign_keys fk INNER JOIN sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id INNER JOIN sys.columns c1 ON fkc.parent_column_id = c1.column_id AND fkc.parent_object_id = c1.object_id INNER JOIN sys.columns c2 ON fkc.referenced_column_id = c2.column_id AND fkc.referenced_object_id = c2.object_id where fk.name = @fkname end -- closing bracket insert into @sql(s) values( ')' ) -- result! select s from @sql order by id
我将通过支持分区表来改进答案:
使用下面的scritps查找分区方案和分区键:
declare @partition_scheme varchar(100) = ( select distinct ps.Name AS PartitionScheme from sys.indexes i join sys.partitions p ON i.object_id=p.object_id AND i.index_id=p.index_id join sys.partition_schemes ps on ps.data_space_id = i.data_space_id where i.object_id = object_id('your table name') ) print @partition_scheme declare @partition_column varchar(100) = ( select c.name from sys.tables t join sys.indexes i on(i.object_id = t.object_id and i.index_id < 2) join sys.index_columns ic on(ic.partition_ordinal > 0 and ic.index_id = i.index_id and ic.object_id = t.object_id) join sys.columns c on(c.object_id = ic.object_id and c.column_id = ic.column_id) where t.object_id = object_id('your table name') ) print @partition_column
然后通过在正确的位置添加以下行来更改生成查询:
+ IIF(@partition_scheme is null, '', 'ON [' + @partition_scheme + ']([' + @partition_column + '])')