有没有一种方法可以创建一个基于其他 2 个表自动创建具有所有结构(列、约束、PK、FK、索引等)的表的过程?
例如:
桌子a
id
a1
a2
桌子b
id
b1
b2
b3
该过程将接收 3 个表名(a
和b
- 输入,c
- 输出)并将创建c
包含列的表id,a1,a2,b1,b2,b3
,包括所有数据 - 约束、PK、FK、索引等。
我有超过 80 对表要创建,所以手动创建它会像永远一样......
有没有一种方法可以创建一个基于其他 2 个表自动创建具有所有结构(列、约束、PK、FK、索引等)的表的过程?
例如:
桌子a
id
a1
a2
桌子b
id
b1
b2
b3
该过程将接收 3 个表名(a
和b
- 输入,c
- 输出)并将创建c
包含列的表id,a1,a2,b1,b2,b3
,包括所有数据 - 约束、PK、FK、索引等。
我有超过 80 对表要创建,所以手动创建它会像永远一样......
更新:
此脚本从多个表中重新创建 DDL(列、FK、PK、非聚集索引)。可能对你有帮助-
DECLARE
@table1_name SYSNAME
, @table2_name SYSNAME
, @name_for_new_table SYSNAME
, @schema_for_new_table SYSNAME
SELECT
@table1_name = 'dbo.WorkOut'
, @table2_name = 'dbo.WorkPlace'
, @schema_for_new_table = 'dbo'
, @name_for_new_table = 'TableMerge'
DECLARE @SQL NVARCHAR(MAX) = ''
;WITH tbl AS
(
SELECT o.[object_id]
FROM sys.objects o WITH (NOWAIT)
WHERE SCHEMA_NAME(o.[schema_id]) + '.' + o.name IN (@table1_name, @table2_name)
AND o.[type] = 'U'
AND o.is_ms_shipped = 0
),
index_column AS
(
SELECT
ic.[object_id]
, ic.index_id
, ic.is_descending_key
, ic.is_included_column
, c.name
FROM sys.index_columns ic WITH (NOWAIT)
JOIN sys.columns c WITH (NOWAIT) ON ic.[object_id] = c.[object_id] AND ic.column_id = c.column_id
WHERE ic.[object_id] IN (SELECT t.[object_id] FROM tbl t)
),
fk_columns AS
(
SELECT
k.constraint_object_id
, cname = c.name
, rcname = rc.name
FROM sys.foreign_key_columns k WITH (NOWAIT)
JOIN sys.columns rc WITH (NOWAIT) ON rc.[object_id] = k.referenced_object_id AND rc.column_id = k.referenced_column_id
JOIN sys.columns c WITH (NOWAIT) ON c.[object_id] = k.parent_object_id AND c.column_id = k.parent_column_id
)
SELECT @SQL = 'CREATE TABLE [' + @schema_for_new_table + '].[' + @name_for_new_table + ']' + CHAR(13) + '(' + CHAR(13) + STUFF((
SELECT DISTINCT CHAR(9) + ', [' + c.name + '] ' + UPPER(t.name) +
CASE WHEN t.name IN ('varchar', 'char', 'varbinary', 'binary', 'text')
THEN '(' + CASE WHEN c.max_length = -1 THEN N'MAX' ELSE CAST(c.max_length AS NVARCHAR(5)) END + ')'
WHEN t.name IN ('nvarchar', 'nchar', 'ntext')
THEN '(' + CASE WHEN c.max_length = -1 THEN N'MAX' ELSE CAST(c.max_length / 2 AS NVARCHAR(5)) END + ')'
WHEN t.name IN ('datetime2', 'time2', 'datetimeoffset')
THEN '(' + CAST(c.scale AS NVARCHAR(5)) + ')'
WHEN t.name = 'decimal'
THEN '(' + CAST(c.[precision] AS NVARCHAR(5)) + ',' + CAST(c.scale AS NVARCHAR(5)) + ')'
ELSE ''
END +
CASE WHEN c.collation_name IS NOT NULL THEN ' COLLATE ' + c.collation_name ELSE '' END +
CASE WHEN c.is_nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END +
CASE WHEN c.[definition] IS NOT NULL THEN ' DEFAULT' + c.[definition] ELSE '' END +
CASE WHEN c.is_identity = 1 THEN ' IDENTITY(' + CAST(ISNULL(c.seed_value, '0') AS CHAR(1)) + ',' + CAST(ISNULL(c.increment_value, '1') AS CHAR(1)) + ')' ELSE '' END + CHAR(13)
FROM (
SELECT
c.name
, c.user_type_id
, c.max_length
, c.[precision]
, c.scale
, dc.[definition]
, ic.seed_value
, ic.increment_value
, c.collation_name
, is_nullable = MIN(CAST(c.is_nullable AS TINYINT))
, is_identity = MIN(CAST(c.is_identity AS TINYINT))
FROM sys.columns c WITH (NOWAIT)
LEFT JOIN sys.default_constraints dc WITH (NOWAIT) ON c.default_object_id != 0 AND c.[object_id] = dc.parent_object_id AND c.column_id = dc.parent_column_id
LEFT JOIN sys.identity_columns ic WITH (NOWAIT) ON c.is_identity = 1 AND c.[object_id] = ic.[object_id] AND c.column_id = ic.column_id
WHERE c.[object_id] IN (SELECT o.[object_id] FROM tbl o)
GROUP BY
c.name
, c.user_type_id
, c.max_length
, c.[precision]
, c.scale
, dc.[definition]
, ic.seed_value
, ic.increment_value
, c.collation_name
) c
JOIN sys.types t WITH (NOWAIT) ON c.user_type_id = t.user_type_id
FOR XML PATH(N''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)'), 1, 2, CHAR(9) + ' ')
+ ISNULL((SELECT CHAR(9) + ', CONSTRAINT [PK_' + @schema_for_new_table + '_' + @name_for_new_table + '] PRIMARY KEY (' +
(SELECT STUFF((
SELECT DISTINCT ', [' + c.name + ']' + CASE WHEN ic.is_descending_key = 1 THEN ' DESC' ELSE ' ASC' END
FROM sys.key_constraints k WITH (NOWAIT)
JOIN sys.index_columns ic WITH (NOWAIT) ON ic.[object_id] = k.parent_object_id AND ic.index_id = k.unique_index_id
JOIN sys.columns c WITH (NOWAIT) ON c.[object_id] = k.parent_object_id AND c.column_id = ic.column_id
WHERE k.[type] = 'PK'
AND ic.is_included_column = 0
AND k.parent_object_id IN (SELECT t.[object_id] FROM tbl t)
FOR XML PATH(N''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)'), 1, 2, '')) + ')' + CHAR(13)), '')
+ ')' + CHAR(13)
+ ISNULL((SELECT (
SELECT CHAR(13) +
'ALTER TABLE [' + @schema_for_new_table + '].[' + @name_for_new_table + '] WITH'
+ CASE WHEN fk.is_not_trusted = 1
THEN ' NOCHECK'
ELSE ' CHECK'
END +
' ADD CONSTRAINT [FK_' + @schema_for_new_table + '_' + @name_for_new_table + '_' + fk.name + '] FOREIGN KEY('
+ STUFF((
SELECT ', [' + k.cname + ']'
FROM fk_columns k
WHERE k.constraint_object_id = fk.[object_id]
FOR XML PATH(N''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)'), 1, 2, '')
+ ')' +
' REFERENCES [' + SCHEMA_NAME(ro.[schema_id]) + '].[' + ro.name + '] ('
+ STUFF((
SELECT ', [' + k.rcname + ']'
FROM fk_columns k
WHERE k.constraint_object_id = fk.[object_id]
FOR XML PATH(N''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)'), 1, 2, '')
+ ')'
+ CASE
WHEN fk.delete_referential_action = 1 THEN ' ON DELETE CASCADE'
WHEN fk.delete_referential_action = 2 THEN ' ON DELETE SET NULL'
WHEN fk.delete_referential_action = 3 THEN ' ON DELETE SET DEFAULT'
ELSE ''
END
+ CASE
WHEN fk.update_referential_action = 1 THEN ' ON UPDATE CASCADE'
WHEN fk.update_referential_action = 2 THEN ' ON UPDATE SET NULL'
WHEN fk.update_referential_action = 3 THEN ' ON UPDATE SET DEFAULT'
ELSE ''
END
+ CHAR(13) + 'ALTER TABLE [' + @schema_for_new_table + '].[' + @name_for_new_table + '] CHECK CONSTRAINT [FK_' + @schema_for_new_table + '_' + @name_for_new_table + '_' + fk.name + ']' + CHAR(13)
FROM sys.foreign_keys fk WITH (NOWAIT)
JOIN sys.objects ro WITH (NOWAIT) ON ro.[object_id] = fk.referenced_object_id
WHERE fk.parent_object_id IN (SELECT t.[object_id] FROM tbl t)
FOR XML PATH(N''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)')), '')
+ ISNULL(((SELECT
CHAR(13) + 'CREATE' + CASE WHEN i.is_unique = 1 THEN ' UNIQUE' ELSE '' END + ' NONCLUSTERED INDEX [IX_' + @schema_for_new_table + '_' + @name_for_new_table + '_' + i.name + '] ON [' + @schema_for_new_table + '].[' + @name_for_new_table + '] (' +
STUFF((
SELECT ', [' + c.name + ']' + CASE WHEN c.is_descending_key = 1 THEN ' DESC' ELSE ' ASC' END
FROM index_column c
WHERE c.is_included_column = 0
AND c.index_id = i.index_id
FOR XML PATH(N''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)'), 1, 2, '') + ')'
+ ISNULL(CHAR(13) + 'INCLUDE (' +
STUFF((
SELECT ', [' + c.name + ']'
FROM index_column c
WHERE c.is_included_column = 1
AND c.index_id = i.index_id
FOR XML PATH(N''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)'), 1, 2, '') + ')', '') + CHAR(13)
FROM sys.indexes i WITH (NOWAIT)
WHERE i.[object_id] IN (SELECT t.[object_id] FROM tbl t)
AND i.is_primary_key = 0
AND i.[type] = 2
FOR XML PATH(N''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)')
), '')
PRINT @SQL
--EXEC sys.sp_executesql @SQL
例如,此查询生成此 DDL:
CREATE TABLE dbo.TableMerge
(
AbsenceCode VARCHAR(25) COLLATE Cyrillic_General_CI_AS NULL
, CategoryID INT NULL
, DateOut DATETIME NOT NULL
, DepartmentUID UNIQUEIDENTIFIER NOT NULL
, EmployeeID INT NOT NULL
, IsMainWorkPlace BIT NOT NULL DEFAULT((1))
, PaymentType CHAR(2) COLLATE Cyrillic_General_CI_AS NOT NULL
, PositionID INT NOT NULL
, TariffScaleID INT NULL
, TeamUID UNIQUEIDENTIFIER NULL
, TimeSheetDate DATETIME NOT NULL
, WorkHours REAL NULL
, WorkOutID BIGINT NOT NULL IDENTITY(1,1)
, WorkPlaceUID UNIQUEIDENTIFIER NOT NULL
, WorkShiftCD NVARCHAR(20) COLLATE Cyrillic_General_CI_AS NULL
, CONSTRAINT [PK_dbo.TableMerge] PRIMARY KEY (WorkOutID ASC, WorkPlaceUID ASC)
)
如果将此表指定为源:
CREATE TABLE dbo.[WorkOut](
[WorkOutID] [bigint] IDENTITY(1,1) NOT NULL,
[TimeSheetDate] [datetime] NOT NULL,
[DateOut] [datetime] NOT NULL,
[EmployeeID] [int] NOT NULL,
[IsMainWorkPlace] [bit] NOT NULL,
[DepartmentUID] [uniqueidentifier] NOT NULL,
[WorkPlaceUID] [uniqueidentifier] NULL,
[TeamUID] [uniqueidentifier] NULL,
[WorkShiftCD] [nvarchar](10) NULL,
[WorkHours] [real] NULL,
[AbsenceCode] [varchar](25) NULL,
[PaymentType] [char](2) NULL,
[CategoryID] [int] NULL,
CONSTRAINT [PK_WorkOut] PRIMARY KEY CLUSTERED
(
[WorkOutID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE dbo.[WorkPlace](
[WorkPlaceUID] [uniqueidentifier] NOT NULL,
[PositionID] [int] NOT NULL,
[DepartmentUID] [uniqueidentifier] NOT NULL,
[PaymentType] [char](2) NOT NULL,
[TariffScaleID] [int] NULL,
[CategoryID] [int] NULL,
CONSTRAINT [PK_WorkPlace] PRIMARY KEY CLUSTERED
(
[WorkPlaceUID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]