如何在 SQL Server 中复制表(包括 PK 和 FK)
Posted
技术标签:
【中文标题】如何在 SQL Server 中复制表(包括 PK 和 FK)【英文标题】:How to duplicate table in SQL server (include PK & FK) 【发布时间】:2016-10-22 15:55:05 【问题描述】:如何在 SQL Server 中复制表(包括PK
& FK
),我试过这个:
SELECT TOP 0 * INTO new_table FROM old_table
但它不起作用,它只是复制 columns
而没有 Primary Key/Foreign Key
【问题讨论】:
看到这个话题:dba.stackexchange.com/questions/18059/… 【参考方案1】:我已经在我的工作环境中编写了一个脚本来执行此操作
这将基于现有表在新表上创建以下对象
-
默认约束
主键约束
唯一约束
外键约束
使用INTO
子句创建的表不会有上述对象在新表中创建
脚本:
IF Object_id('TEMPDB..#TABLE_LIST') IS NOT NULL
DROP TABLE #TABLE_LIST
CREATE TABLE #TABLE_LIST
(
ORG_TABLE_NAME SYSNAME,
TEMP_TABLE_NAME SYSNAME
)
INSERT INTO #TABLE_LIST
(ORG_TABLE_NAME,
TEMP_TABLE_NAME)
Values('old_table','new_table')
-------------------------------------------------DEFAULT SCRIPT START---------------------------------------------------
DECLARE @DEFAULT_SCRIPT VARCHAR(MAX) =''
SET @DEFAULT_SCRIPT = (SELECT 'ALTER TABLE ['+SCHEMA_NAME(SCHEMA_ID)+'].['+TL.TEMP_TABLE_NAME+']
ADD CONSTRAINT ['+replace(DC.NAME,tl.ORG_TABLE_NAME,tl.TEMP_TABLE_NAME)+'] DEFAULT '+DEFINITION+' FOR ['+C.NAME+']
'
FROM SYS.DEFAULT_CONSTRAINTS DC INNER JOIN SYS.COLUMNS C ON DC.PARENT_OBJECT_ID = C.OBJECT_ID
AND DC.PARENT_COLUMN_ID = C.COLUMN_ID
join #TABLE_LIST TL on OBJECT_ID(TL.ORG_TABLE_NAME) = PARENT_OBJECT_ID)
--print @DEFAULT_SCRIPT
EXEC (@DEFAULT_SCRIPT)
-------------------------------------------------DEFAULT SCRIPT END---------------------------------------------------
-------------------------------------------------PRIMARY SCRIPT START---------------------------------------------------
DECLARE @PRIMARY_SCRIPT VARCHAR(MAX) =''
SET @PRIMARY_SCRIPT = (SELECT 'ALTER TABLE ['+TL.TEMP_TABLE_NAME+']
ADD CONSTRAINT ['+replace(TAB.CONSTRAINT_NAME,tl.ORG_TABLE_NAME,tl.TEMP_TABLE_NAME) +'] PRIMARY KEY ('+LEFT(CS.COL_LIST, LEN(CS.COL_LIST) - 1)+')
'
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS TAB
JOIN #TABLE_LIST TL on TL.ORG_TABLE_NAME = TAB.TABLE_NAME
CROSS APPLY (SELECT QUOTENAME(COLUMN_NAME) + ','
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE COL
WHERE COL.CONSTRAINT_NAME = TAB.CONSTRAINT_NAME
AND COL.TABLE_NAME = TAB.TABLE_NAME
FOR XML PATH('')) CS (COL_LIST)
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
GROUP BY TAB.TABLE_NAME,
TAB.CONSTRAINT_NAME,
CONSTRAINT_SCHEMA,tl.ORG_TABLE_NAME,tl.TEMP_TABLE_NAME,
LEFT(CS.COL_LIST, LEN(CS.COL_LIST) - 1))
--print @PRIMARY_SCRIPT
EXEC (@PRIMARY_SCRIPT)
-------------------------------------------------PRIMARY SCRIPT END---------------------------------------------------
-------------------------------------------------UNIQUE CONSTARINT SCRIPT START---------------------------------------------------
DECLARE @UNIQUE_SCRIPT VARCHAR(MAX) =''
SET @UNIQUE_SCRIPT = (SELECT 'ALTER TABLE ['+TL.TEMP_TABLE_NAME+']
ADD CONSTRAINT ['+replace(TAB.CONSTRAINT_NAME,tl.ORG_TABLE_NAME,tl.TEMP_TABLE_NAME)+'] UNIQUE ('+LEFT(CS.COL_LIST, LEN(CS.COL_LIST) - 1)+')
'
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS TAB
JOIN #TABLE_LIST TL on TL.ORG_TABLE_NAME = TAB.TABLE_NAME
CROSS APPLY (SELECT QUOTENAME(COLUMN_NAME) + ','
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE COL
WHERE COL.CONSTRAINT_NAME = TAB.CONSTRAINT_NAME
AND COL.TABLE_NAME = TAB.TABLE_NAME
FOR XML PATH('')) CS (COL_LIST)
WHERE CONSTRAINT_TYPE = 'UNIQUE'
GROUP BY TAB.TABLE_NAME,
TAB.CONSTRAINT_NAME,
CONSTRAINT_SCHEMA,tl.ORG_TABLE_NAME,tl.TEMP_TABLE_NAME,
LEFT(CS.COL_LIST, LEN(CS.COL_LIST) - 1))
EXEC (@UNIQUE_SCRIPT)
-------------------------------------------------UNIQUE CONSTARINT SCRIPT END---------------------------------------------------
-------------------------------------------------FOREIGN KEY SCRIPT START---------------------------------------------------
DECLARE @FOREIGNKEY_SCRIPT VARCHAR(MAX) = ''
SET @FOREIGNKEY_SCRIPT = (SELECT 'ALTER TABLE ['+TL.TEMP_TABLE_NAME+']
ADD CONSTRAINT '+replace(F.NAME,tl.ORG_TABLE_NAME,tl.TEMP_TABLE_NAME)+' FOREIGN KEY('+QUOTENAME(COL_NAME(FC.PARENT_OBJECT_ID, FC.PARENT_COLUMN_ID))+') REFERENCES '+OBJECT_NAME (F.REFERENCED_OBJECT_ID)+'('+QUOTENAME(COL_NAME(FC.REFERENCED_OBJECT_ID, FC.REFERENCED_COLUMN_ID))+')
'
FROM SYS.FOREIGN_KEYS AS F
INNER JOIN SYS.FOREIGN_KEY_COLUMNS AS FC
ON F.OBJECT_ID = FC.CONSTRAINT_OBJECT_ID
INNER JOIN #TABLE_LIST TL on TL.ORG_TABLE_NAME = OBJECT_NAME(F.PARENT_OBJECT_ID))
EXEC (@FOREIGNKEY_SCRIPT)
注意:
-
我没有处理
schema
所以脚本认为只有 dbo 架构
如果不需要任何constraint
,您可以评论或从脚本中删除它。
【讨论】:
我没有投反对票,但脚本假定约束命名约定,缺少检查约束、索引、无文件组/分区方案等。在 T-SQL 中执行此任务需要使用 SQL Server 目录视图代替或补充 INFORMATION_SCHEMA。此外,聚合字符串连接也不可靠;请改用 XML。 @DanGuzman - 最好有与基表相同的命名约定。然后 OP 只要求PK
和 FK
但我也简单地添加了其他约束。将更新我对check constraint
和Index
的回答。但我对filegroup/partition scheme
不太了解,所以跳过这些
@DanGuzman - 使用 XML PATH
方法更改了字符串连接
表名使用的类型是SYSNAME
,而不是VARCHAR(200)。另外,使用QUOTENAME(...)
正确引用系统名称,不要给自己加上方括号。 (PS:我没有投反对票,也没有测试过这个脚本)。
@TT。 - 更新了数据类型。现在我不能删除那么多方括号;)以上是关于如何在 SQL Server 中复制表(包括 PK 和 FK)的主要内容,如果未能解决你的问题,请参考以下文章
TSQL / SQL-SERVER:如何在具有主键的快照复制中查找所有表
SQL server 数据库 如何把一张表复制到另一个数据库表中