在 SQL Server 中,如何为给定表生成 CREATE TABLE 语句?
Posted
技术标签:
【中文标题】在 SQL Server 中,如何为给定表生成 CREATE TABLE 语句?【英文标题】:In SQL Server, how do I generate a CREATE TABLE statement for a given table? 【发布时间】:2010-09-06 11:58:18 【问题描述】:我花了很多时间想出解决这个问题的方法,所以本着this post 的精神,我把它贴在这里,因为我认为它可能对其他人有用。
如果有人有更好的脚本,或者有什么要补充的,请发布。
编辑:是的,伙计们,我知道如何在 Management Studio 中执行此操作 - 但我需要能够从另一个应用程序中执行此操作。
【问题讨论】:
【参考方案1】:基于 Hubbitus 答案的查询。
包括架构名称 修复具有多个字段的外键 包括级联更新和删除 包括一个有条件的 DROP TABLESELECT
Schema_Name = SCHEMA_NAME(obj.uid)
, Table_Name = name
, Drop_Table = 'IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ''' + SCHEMA_NAME(obj.uid) + ''' AND TABLE_NAME = ''' + obj.name + '''))
DROP TABLE [' + SCHEMA_NAME(obj.uid) + '].[' + obj.name + '] '
, Create_Table ='
CREATE TABLE [' + SCHEMA_NAME(obj.uid) + '].[' + 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 id = obj.id
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 IC.column_default IS NOT NULL THEN ' DEFAULT ' + IC.column_default ELSE '' END
+ ','
FROM INFORMATION_SCHEMA.COLUMNS IC
WHERE IC.table_name = obj.name
AND IC.TABLE_SCHEMA = SCHEMA_NAME(obj.uid)
ORDER BY ordinal_position
FOR XML PATH('')
) cols (list)
CROSS APPLY(
SELECT
CHAR(10) + 'ALTER TABLE [' + SCHEMA_NAME(obj.uid) + '].[' + obj.name + '] 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://***.com/questions/3907879/sql-server-howto-get-foreign-key-reference-from-information-schema
SELECT LEFT(f.list, LEN(f.list)-1) + ')' + IIF(rc.DELETE_RULE = 'NO ACTION', '', ' ON DELETE ' + rc.DELETE_RULE) + IIF(rc.UPDATE_RULE = 'NO ACTION', '', ' ON UPDATE ' + rc.UPDATE_RULE) + ', '
FROM information_schema.referential_constraints rc
CROSS APPLY(
SELECT IIF(kcu.ordinal_position = 1, ' REFERENCES [' + kcu.table_schema + '].[' + kcu.table_name + '] (', '')
+ '[' + kcu.column_name + '], '
FROM information_schema.key_column_usage kcu
WHERE kcu.constraint_catalog = rc.unique_constraint_catalog AND kcu.constraint_schema = rc.unique_constraint_schema AND kcu.constraint_name = rc.unique_constraint_name
ORDER BY kcu.ordinal_position
FOR XML PATH('')
) f (list)
WHERE rc.constraint_catalog = tc.constraint_catalog
AND rc.constraint_schema = tc.constraint_schema
AND rc.constraint_name = tc.constraint_name
) r (list)
WHERE tc.table_name = obj.name
FOR XML PATH('')
) a (alt)
) refs (list)
WHERE xtype = 'U'
将 drop table(如果存在)与 create 结合使用,如下所示:
SELECT Drop_Table + CHAR(10) + Create_Table FROM SysCreateTables
【讨论】:
【参考方案2】:我已修改上述版本以运行所有表并支持新的 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 UPPER(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 约束的表
【讨论】:
这太棒了!我一直在寻找这样的东西很长一段时间! (尝试将表结构编写到我们的版本控制中) 感谢您发布此消息!我认为您应该使用 numeric_precision 列,而不是 numeric_precision_radix,并且除了小数数据类型之外,它对于 numeric 数据类型的工作方式应该相同。 我认为你有一个错误 -- numeric_precision_radix 应该是 numeric_precision 我注意到在运行它时,在列出列时输出的末尾有一个额外的逗号。我可以通过用STUFF(o.list,1,2,'')
将第1 行中的o.list 括起来并将逗号从第23 行的交叉应用的末尾移到第5 行的开头', ['+column_name+'] ' +
来删除多余的逗号
通过@Imingle 更改,我还将LEFT(j.List, Len(j.List)-1)
更改为STUFF(j.List, 1,2,'')
,并将第33 行的逗号移到前面select ', [' + Column_Name + '] '
【参考方案3】:
这是我想出的脚本。它处理标识列、默认值和主键。它不处理外键、索引、触发器或任何其他聪明的东西。它适用于 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
【讨论】:
由于动态 sql 的原因,许多系统将无法运行它。在您的本地盒子上可能不是问题,但只是想指出这一点。 什么动态sql?此脚本生成 sql - 它不执行它。 希望将其分解为多个步骤,以便可以通过一系列可以用 C++ 编写的查询来执行 如果架构不是“dbo”,您将失去对架构的支持。此外,如果数据库具有相同的表名但架构不同,则会出现问题。我得到了我需要的东西,谢谢。 @TT。你确定吗?select cast(123456 as varchar)
为我返回 123456
。【参考方案4】:
我意识到这已经很长时间了,但我还是想补充一下。如果您只想要表格,而不是您可以使用的 create table 语句
select into x from db.schema.y where 1=0
将表复制到新数据库
【讨论】:
关于此方法的一个注意事项是,它不会复制约束或默认值等扩展信息,但它仍然是直接表复制的简单解决方案。【参考方案5】:我包含计算列的定义
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, name
from sysobjects so
cross apply
(SELECT
case when comps.definition is not null then ' ['+column_name+'] AS ' + comps.definition
else
' ['+column_name+'] ' + data_type +
case
when data_type like '%text' or data_type in ('image', 'sql_variant' ,'xml')
then ''
when data_type in ('float')
then '(' + cast(coalesce(numeric_precision, 18) as varchar(11)) + ')'
when data_type in ('datetime2', 'datetimeoffset', 'time')
then '(' + cast(coalesce(datetime_precision, 7) as varchar(11)) + ')'
when data_type in ('decimal', 'numeric')
then '(' + cast(coalesce(numeric_precision, 18) as varchar(11)) + ',' + cast(coalesce(numeric_scale, 0) as varchar(11)) + ')'
when (data_type like '%binary' or data_type like '%char') and character_maximum_length = -1
then '(max)'
when character_maximum_length is not null
then '(' + cast(character_maximum_length as varchar(11)) + ')'
else ''
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 information_schema.columns.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
end + ', '
from information_schema.columns
left join sys.computed_columns comps
on OBJECT_ID(information_schema.columns.TABLE_NAME)=comps.object_id and information_schema.columns.COLUMN_NAME=comps.name
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')
【讨论】:
【参考方案6】:-- 或者你可以创建一个存储过程...首先创建 Id
USE [db]
GO
/****** Object: StoredProcedure [dbo].[procUtils_InsertGeneratorWithId] Script Date: 06/13/2009 22:18:11 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create PROC [dbo].[procUtils_InsertGeneratorWithId]
(
@domain_user varchar(50),
@tableName varchar(100)
)
as
--Declare a cursor to retrieve column specific information for the specified table
DECLARE cursCol CURSOR FAST_FORWARD FOR
SELECT column_name,data_type FROM information_schema.columns WHERE table_name = @tableName
OPEN cursCol
DECLARE @string nvarchar(3000) --for storing the first half of INSERT statement
DECLARE @stringData nvarchar(3000) --for storing the data (VALUES) related statement
DECLARE @dataType nvarchar(1000) --data types returned for respective columns
DECLARE @IDENTITY_STRING nvarchar ( 100 )
SET @IDENTITY_STRING = ' '
select @IDENTITY_STRING
SET @string='INSERT '+@tableName+'('
SET @stringData=''
DECLARE @colName nvarchar(50)
FETCH NEXT FROM cursCol INTO @colName,@dataType
IF @@fetch_status<>0
begin
print 'Table '+@tableName+' not found, processing skipped.'
close curscol
deallocate curscol
return
END
WHILE @@FETCH_STATUS=0
BEGIN
IF @dataType in ('varchar','char','nchar','nvarchar')
BEGIN
--SET @stringData=@stringData+'''''''''+isnull('+@colName+','''')+'''''',''+'
SET @stringData=@stringData+''''+'''+isnull('''''+'''''+'+@colName+'+'''''+''''',''NULL'')+'',''+'
END
ELSE
if @dataType in ('text','ntext') --if the datatype is text or something else
BEGIN
SET @stringData=@stringData+'''''''''+isnull(cast('+@colName+' as varchar(2000)),'''')+'''''',''+'
END
ELSE
IF @dataType = 'money' --because money doesn't get converted from varchar implicitly
BEGIN
SET @stringData=@stringData+'''convert(money,''''''+isnull(cast('+@colName+' as varchar(200)),''0.0000'')+''''''),''+'
END
ELSE
IF @dataType='datetime'
BEGIN
--SET @stringData=@stringData+'''convert(datetime,''''''+isnull(cast('+@colName+' as varchar(200)),''0'')+''''''),''+'
--SELECT 'INSERT Authorizations(StatusDate) VALUES('+'convert(datetime,'+isnull(''''+convert(varchar(200),StatusDate,121)+'''','NULL')+',121),)' FROM Authorizations
--SET @stringData=@stringData+'''convert(money,''''''+isnull(cast('+@colName+' as varchar(200)),''0.0000'')+''''''),''+'
SET @stringData=@stringData+'''convert(datetime,'+'''+isnull('''''+'''''+convert(varchar(200),'+@colName+',121)+'''''+''''',''NULL'')+'',121),''+'
-- 'convert(datetime,'+isnull(''''+convert(varchar(200),StatusDate,121)+'''','NULL')+',121),)' FROM Authorizations
END
ELSE
IF @dataType='image'
BEGIN
SET @stringData=@stringData+'''''''''+isnull(cast(convert(varbinary,'+@colName+') as varchar(6)),''0'')+'''''',''+'
END
ELSE --presuming the data type is int,bit,numeric,decimal
BEGIN
--SET @stringData=@stringData+'''''''''+isnull(cast('+@colName+' as varchar(200)),''0'')+'''''',''+'
--SET @stringData=@stringData+'''convert(datetime,'+'''+isnull('''''+'''''+convert(varchar(200),'+@colName+',121)+'''''+''''',''NULL'')+'',121),''+'
SET @stringData=@stringData+''''+'''+isnull('''''+'''''+convert(varchar(200),'+@colName+')+'''''+''''',''NULL'')+'',''+'
END
SET @string=@string+@colName+','
FETCH NEXT FROM cursCol INTO @colName,@dataType
END
DECLARE @Query nvarchar(4000)
SET @query ='SELECT '''+substring(@string,0,len(@string)) + ') VALUES(''+ ' + substring(@stringData,0,len(@stringData)-2)+'''+'')'' FROM '+@tableName
exec sp_executesql @query
--select @query
CLOSE cursCol
DEALLOCATE cursCol
/*
USAGE
*/
GO
--第二个没有iD INSERTION
USE [db]
GO
/****** Object: StoredProcedure [dbo].[procUtils_InsertGenerator] Script Date: 06/13/2009 22:20:52 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROC [dbo].[procUtils_InsertGenerator]
(
@domain_user varchar(50),
@tableName varchar(100)
)
as
--Declare a cursor to retrieve column specific information for the specified table
DECLARE cursCol CURSOR FAST_FORWARD FOR
-- SELECT column_name,data_type FROM information_schema.columns WHERE table_name = @tableName
/* NEW
SELECT c.name , sc.data_type FROM sys.extended_properties AS ep
INNER JOIN sys.tables AS t ON ep.major_id = t.object_id
INNER JOIN sys.columns AS c ON ep.major_id = c.object_id AND ep.minor_id
= c.column_id
INNER JOIN INFORMATION_SCHEMA.COLUMNS sc ON t.name = sc.table_name and
c.name = sc.column_name
WHERE t.name = @tableName and c.is_identity=0
*/
select object_name(c.object_id) "TABLE_NAME", c.name "COLUMN_NAME", s.name "DATA_TYPE"
from sys.columns c
join sys.systypes s on (s.xtype = c.system_type_id)
where object_name(c.object_id) in (select name from sys.tables where name not like 'sysdiagrams')
AND object_name(c.object_id) in (select name from sys.tables where [name]=@tableName ) and c.is_identity=0 and s.name not like 'sysname'
OPEN cursCol
DECLARE @string nvarchar(3000) --for storing the first half of INSERT statement
DECLARE @stringData nvarchar(3000) --for storing the data (VALUES) related statement
DECLARE @dataType nvarchar(1000) --data types returned for respective columns
DECLARE @IDENTITY_STRING nvarchar ( 100 )
SET @IDENTITY_STRING = ' '
select @IDENTITY_STRING
SET @string='INSERT '+@tableName+'('
SET @stringData=''
DECLARE @colName nvarchar(50)
FETCH NEXT FROM cursCol INTO @tableName , @colName,@dataType
IF @@fetch_status<>0
begin
print 'Table '+@tableName+' not found, processing skipped.'
close curscol
deallocate curscol
return
END
WHILE @@FETCH_STATUS=0
BEGIN
IF @dataType in ('varchar','char','nchar','nvarchar')
BEGIN
--SET @stringData=@stringData+'''''''''+isnull('+@colName+','''')+'''''',''+'
SET @stringData=@stringData+''''+'''+isnull('''''+'''''+'+@colName+'+'''''+''''',''NULL'')+'',''+'
END
ELSE
if @dataType in ('text','ntext') --if the datatype is text or something else
BEGIN
SET @stringData=@stringData+'''''''''+isnull(cast('+@colName+' as varchar(2000)),'''')+'''''',''+'
END
ELSE
IF @dataType = 'money' --because money doesn't get converted from varchar implicitly
BEGIN
SET @stringData=@stringData+'''convert(money,''''''+isnull(cast('+@colName+' as varchar(200)),''0.0000'')+''''''),''+'
END
ELSE
IF @dataType='datetime'
BEGIN
--SET @stringData=@stringData+'''convert(datetime,''''''+isnull(cast('+@colName+' as varchar(200)),''0'')+''''''),''+'
--SELECT 'INSERT Authorizations(StatusDate) VALUES('+'convert(datetime,'+isnull(''''+convert(varchar(200),StatusDate,121)+'''','NULL')+',121),)' FROM Authorizations
--SET @stringData=@stringData+'''convert(money,''''''+isnull(cast('+@colName+' as varchar(200)),''0.0000'')+''''''),''+'
SET @stringData=@stringData+'''convert(datetime,'+'''+isnull('''''+'''''+convert(varchar(200),'+@colName+',121)+'''''+''''',''NULL'')+'',121),''+'
-- 'convert(datetime,'+isnull(''''+convert(varchar(200),StatusDate,121)+'''','NULL')+',121),)' FROM Authorizations
END
ELSE
IF @dataType='image'
BEGIN
SET @stringData=@stringData+'''''''''+isnull(cast(convert(varbinary,'+@colName+') as varchar(6)),''0'')+'''''',''+'
END
ELSE --presuming the data type is int,bit,numeric,decimal
BEGIN
--SET @stringData=@stringData+'''''''''+isnull(cast('+@colName+' as varchar(200)),''0'')+'''''',''+'
--SET @stringData=@stringData+'''convert(datetime,'+'''+isnull('''''+'''''+convert(varchar(200),'+@colName+',121)+'''''+''''',''NULL'')+'',121),''+'
SET @stringData=@stringData+''''+'''+isnull('''''+'''''+convert(varchar(200),'+@colName+')+'''''+''''',''NULL'')+'',''+'
END
SET @string=@string+@colName+','
FETCH NEXT FROM cursCol INTO @tableName , @colName,@dataType
END
DECLARE @Query nvarchar(4000)
SET @query ='SELECT '''+substring(@string,0,len(@string)) + ') VALUES(''+ ' + substring(@stringData,0,len(@stringData)-2)+'''+'')'' FROM '+@tableName
exec sp_executesql @query
--select @query
CLOSE cursCol
DEALLOCATE cursCol
/*
use poc
go
DECLARE @RC int
DECLARE @domain_user varchar(50)
DECLARE @tableName varchar(100)
-- TODO: Set parameter values here.
set @domain_user='yorgeorg'
set @tableName = 'tbGui_WizardTabButtonAreas'
EXECUTE @RC = [POC].[dbo].[procUtils_InsertGenerator]
@domain_user
,@tableName
*/
GO
【讨论】:
【参考方案7】:我将通过支持分区表来改进答案:
使用以下脚本查找分区方案和分区键:
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 + '])')
【讨论】:
【参考方案8】:在一个语句中支持外键的另一种变体:
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://***.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
【讨论】:
我喜欢这个单语句解决方案,它支持外键。@tableName
的前 2 个实例可以替换为 so.name
,这样可以更轻松地同时为多个表生成创建表脚本。
此外,当没有单一约束(如主键)时,查询将为 NULL
。要解决这个问题,' ' + j.list
应该是ISNULL(' ' + j.list, '')
。我冒昧地为我的两个 cmets 中描述的用例调整了代码
@ChristiaanWesterbeek 的建议看起来很合理。但我不明白最后一个案例。 j.list 什么时候为空?可以举个例子吗?
用你的小提琴中的表区试试。你会看到一个空值。最后一列还有一个不应存在的尾随逗号。不过还是喜欢你的回答:)
啊,你说的桌子没有钥匙!谢谢,也修好了。最后一个逗号不是问题,因为它更正了 SQL,但它(以及更易读的子查询名称)也为 estetic 修复。【参考方案9】:
我修改了接受的答案,现在它可以在某个模式中获取包含主键和外键的命令。
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
【讨论】:
将此(编辑)重新发布到已接受的答案中可能会很好。这似乎完全符合 SO 的精神。我的回答中的模式和换行符对于全面的一站式人性化解决方案也很好。【参考方案10】:支持模式:
这是一个更新版本,修改了 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 代码的一个批评是,如果您使用 SSMS 对其进行测试,那么长语句不容易阅读。因此,根据this helpful post,这是另一个版本,在单击网格中单元格的链接后,它经过了一些修改,使眼睛更容易看到。结果更容易识别为 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]);
..
不利因素:
应该注意的是,由于缺乏对除主键以外的索引的支持,我对此仍然相对不满意。它仍然适合用作简单数据导出或复制的机制。
【讨论】:
这实际上适用于 Stack Exchange Data Explorer,超级有用!【参考方案11】: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') '<Servername>'
$db = $s.Databases['<Database>']
$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\<Database>.SQL'
foreach($item in $db.Tables) $tablearray+=@($item)
$scrp.Script($tablearray)
Write-Host "Scripting complete"
【讨论】:
当您有权使用 SMO 时,它非常棒。我发现许多系统并非如此,因此纯 INFORMATION_SCHEMA 方法具有一些优势。【参考方案12】:Show create table in classic asp(处理约束、主键、复制表结构和/或数据...)
Sql server 显示创建表 来自 Microsoft sql server 的 mysql 风格的“显示创建表”和“显示创建数据库”命令。 该脚本是用 Microsoft asp 语言编写的,很容易移植到另一种语言。*
【讨论】:
【参考方案13】:如果您从中生成脚本的应用程序是 .NET 应用程序,您可能需要考虑使用 SMO(Sql 管理对象)。参考此SQL Team link 了解如何使用 SMO 编写对象脚本。
【讨论】:
【参考方案14】:如果您使用的是管理工作室并打开了查询分析器窗口,您可以将表名拖到查询分析器窗口,然后...宾果游戏!你得到表格脚本。 我没有在 SQL2008 中尝试过这个
【讨论】:
这是一个简洁的快捷方式,但同样:我需要以编程方式完成。【参考方案15】:我注意到了 - 在 INFORMATION_SCHEMA.COLUMNS 视图中,CHARACTER_MAXIMUM_LENGTH 为图像和文本等字段类型提供了 2147483647 (2^31-1) 的大小。 ntext 是 2^30-1 (是双字节 unicode 和所有)。
此大小包含在此查询的输出中,但对于 CREATE 语句中的这些数据类型无效(它们根本不应该具有最大大小值)。因此,除非手动更正由此产生的结果,否则 CREATE 脚本在这些数据类型下将无法工作。
我想可以修复脚本来解决这个问题,但这超出了我的 SQL 能力。
【讨论】:
【参考方案16】:感谢@Blorgbeard 分享他的脚本。我一定会收藏它以备不时之需。
是的,您可以“右键单击”表格并编写 CREATE TABLE
脚本,但是:
通过将此脚本转换为存储过程,并结合包装脚本,您将有一种很好的自动化方式将您的表格设计转储到源代码控制等中。
您的数据库代码的其余部分(SP、FK 索引、触发器等)无论如何都将处于源代码控制之下;)
【讨论】:
我认为 dbproject 可以直接从服务器导入架构,因此您不需要签入创建表语句,并且在 SSMS 中您可以使用“对象资源管理器详细信息”编写多个表的脚本或右键单击对象资源管理器中的数据库并选择 Tasks->Generate scripts以上是关于在 SQL Server 中,如何为给定表生成 CREATE TABLE 语句?的主要内容,如果未能解决你的问题,请参考以下文章
如何为多个参数值显示特定字段中的所有值? SQL Server 报表生成器
如何为每个表计算由 SQL Server 中未指定数量的表共享的列中的不同值?
从 python 使用 TSQL(SQL Server 上的 mssql)时,如何为 SQLAlchemy 自动生成 ORM 代码?