• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
皇图霸业谈笑间
更高、更快、更强
博客园    首页    新随笔    联系   管理    订阅  订阅
关于SQLSERVER2005导表结构

首先我要叫声:操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 、操阿 。。。

这几天碰到不开心的事情,但是这些不开心的事情暂时不能在这里论述,只能发泄一番 。。。

偶已经好几天没兑现我每天写博客技术文章的诺言了 。

今天要记录一下关于SQLSERVER2005中导表结构的方案,当然这里的结构是包含【键、索引、约束、触发器】等等一大堆东西的。

其实偶就是操了别人的存储过程罢了 , 代码贴出来供自己以后回顾:

 

USE MobileCommunity
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--功能目的:复制源DB中某个表的结构到目标DB的同名表中,只改表结构、约束、索引等,不改目标DB的数据
--注意:    默认约束名是自动生成的新名字,如果和以前的名字有冲突请手工修改后运行,
--          新的默认约束名统一为 'DF_表名_列名' ,如果要使用原默认约束名需要修改代码

CREATE PROCEDURE [dbo].[NovelTableLayout11]
  @sourceDB                 sysname,        
--源DB名
  @targetDB                 sysname,        
--目标DB名
  @schemaName               sysname,
--架构名,此参数保留,未使用
  @sourceTableName          sysname,        
--源表名
  @targetTableName          sysname,   
--目标表名,默认与源表名相同
  @enable                   bit 
= 0         --是否执行
WITH ENCRYPTION
AS
DECLARE @schema_id          
int             --架构ID
DECLARE @tmpTableName       varchar(
100)    --临时表名
DECLARE @columnName         varchar(
100)    --列名
DECLARE @d_name             varchar(
100)    --默认约束的约束名
DECLARE @definition         varchar(
100)    --默认值
DECLARE @i_name             varchar(
100)    --索引名
DECLARE @is_key             bit             
--是否主键
DECLARE @i_no               tinyInt         
--索引的序号
DECLARE @c_name             varchar(
200)    --索引所在的列名
DECLARE @i_type             varchar(
60)     --是否聚集
DECLARE @is_unique          varchar(
6)      --是否唯一
DECLARE @is_unique_key      bit             
--是否唯一键
DECLARE @cmd_all            varchar(max)    
--存放全部语句
DECLARE @cmd_temp           nvarchar(max)   
--存放临时执行的语句
DECLARE @cmd_create_table   varchar(
5000)   --存放创建 Table 的语句
DECLARE @cmd_drop_default   nvarchar(max)   
--删除默认约束
DECLARE @cmd_add_default    nvarchar(max)   
--添加默认约束
DECLARE @cmd_add_index      varchar(
2000)   --添加索引
DECLARE @cmd_add_check      varchar(
2000)   --添加 CHECK 约束
DECLARE @cmd_add_foreign    varchar(
600)    --添加外键约束
DECLARE @cmd_insert         varchar(max)    
--插入语句
DECLARE @c_name_A           varchar(
4000)   --INSERT语句用
DECLARE @c_name_B           varchar(
4000)   --INSERT语句用
DECLARE @identity_on        varchar(
60)     --关闭自增长
DECLARE @identity_off       varchar(
60)     --开启自增长
DECLARE @cmd_create_trigger nvarchar(max)   
--创建 TRIGGER 的语句
DECLARE @i                  smallInt        
--用于循环

SET NOCOUNT ON

IF (@targetTableName 
= '') SET @targetTableName = @sourceTableName
SET @schema_id 
= SCHEMA_ID(@schemaName)
SET @columnName 
= ''
SET @cmd_add_default 
= ''
SET @cmd_drop_default 
= ''
SET @cmd_add_index 
= ''

DECLARE @columns table(c_no 
int identity,c_name varchar(100))--存放表中所有的列名
DECLARE @indexName table(i_no tinyInt IDENTITY(
1,1),         --存放该表中的索引名
    i_name varchar(
100),type_desc varchar(60),is_unique bit,is_key bit,is_unique_key bit)
INSERT INTO @columns EXEC(
'SELECT name FROM ' + @sourceDB + '.sys.columns WHERE object_id = (SELECT object_id FROM ' + @sourceDB + '.sys.tables WHERE name = ''' + @sourceTableName + ''')')
INSERT INTO @indexName EXEC(
'SELECT name,type_desc,is_unique,is_primary_key,is_unique_constraint FROM ' + @sourceDB + '.sys.indexes WHERE object_id = (SELECT object_id FROM ' + @sourceDB + '.sys.tables WHERE name = ''' + @sourceTableName + ''')')

--生成中间过渡临时表的名字
SET @cmd_temp 
= 'DECLARE @i tinyInt
SET @i = 1
SET @tmpTableName 
= ''Tmp_' + @targetTableName + '''
WHILE (EXISTS (SELECT 
* FROM ' + @targetDB + '.sys.objects WHERE NAME = @tmpTableName AND TYPE = ''U''))
BEGIN
SET @tmpTableName 
= ''Tmp_' + @targetTableName + '_'' + RTRIM(@i)
SET @i 
= @i + 1
END
'
EXECUTE sp_executesql @cmd_temp,N'@tmpTableName varchar(100) OUTPUT',@tmpTableName OUTPUT

--生成创建表的代码
SET @cmd_temp 
= 'USE ' + @sourceDB + '
SET @cmd_create_table = ''CREATE TABLE ' + @tmpTableName + '(''  + char(13)
SELECT @cmd_create_table 
= @cmd_create_table + ''['' + name + ''] '' + 
CASE is_computed WHEN 
1 THEN
    (SELECT 
''AS '' + definition + CASE is_persisted WHEN ''1'' THEN '' PERSISTED'' ELSE '''' END
       FROM sys.computed_columns WHERE name 
= sys.columns.name)
ELSE (TYPE_NAME(system_type_id) 
+
  CASE WHEN system_type_id 
in (167,175) THEN ''('' + (CASE max_length WHEN -1 THEN ''MAX'' ELSE RTRIM(max_length) END) + '')''
    WHEN system_type_id 
in (231,239) THEN ''('' + (CASE max_length WHEN -1 THEN ''MAX'' ELSE RTRIM(max_length / 2) END) + '')''
    WHEN system_type_id 
in (106,108) THEN ''('' + RTRIM(precision) + '','' + RTRIM(scale) + '')''
    ELSE 
'''' END +
  CASE is_nullable WHEN 
0 THEN '' NOT NULL''
    ELSE 
'''' END +
  CASE is_identity WHEN 
1 THEN
    (SELECT TOP 
1 '' IDENTITY('' + CAST(seed_value as varchar(10)) + '','' + CAST(increment_value as varchar(10)) + '')''
       FROM sys.identity_columns WHERE name 
= sys.columns.name)
  ELSE 
'''' END)
END 
+ '','' + char(13) FROM sys.columns where object_id = OBJECT_ID(''' + @sourceTableName + ''')
SET @cmd_create_table 
= SUBSTRING(@cmd_create_table,1,LEN(@cmd_create_table) - 2) + '')
GO
'''
EXEC sp_executesql @cmd_temp,N'@cmd_create_table varchar(5000) OUTPUT',@cmd_create_table OUTPUT

--生成创建和删除默认约束的代码
SET @i 
= 1
WHILE (@i 
<= (SELECT COUNT(c_no) FROM @columns))
BEGIN
  SELECT @columnName 
= c_name FROM @columns WHERE c_no = @i
  SET @cmd_temp 
= 'use ' + @sourceDB + char(13) +
    
'SELECT @d_name = name,@definition = definition FROM sys.default_constraints
      WHERE object_id = (SELECT default_object_id FROM sys.columns WHERE object_id = OBJECT_ID(''' + @sourceTableName + ''') AND name = ''' + @columnName + ''')'
  SET @d_name = ''
  EXEC sp_executesql @cmd_temp,N
'@d_name varchar(60) output,@definition nvarchar(50) output',@d_name OUTPUT,@definition OUTPUT
  IF (@d_name 
!= '')    --此处使用了新默认约束名,原默认约束名保存在 @d_name 中没有使用
    SET @cmd_add_default 
= @cmd_add_default + 'ALTER TABLE [' + @tmpTableName + '] ADD CONSTRAINT [DF_' + @targetTableName + '_' + @columnName +'] DEFAULT ' + @definition + ' FOR [' + @columnName + ']
GO
'
  SET @cmd_temp = 'use ' + @targetDB + char(13) +
    
'SELECT @d_name = name FROM sys.default_constraints
      WHERE object_id = (SELECT default_object_id FROM sys.columns WHERE object_id = OBJECT_ID(''' + @targetTableName + ''') AND name = ''' + @columnName + ''')'
  SET @d_name = ''
  EXEC sp_executesql @cmd_temp,N
'@d_name varchar(60) output',@d_name OUTPUT
  IF (@d_name 
!= '')
    SET @cmd_drop_default 
= @cmd_drop_default + 'ALTER TABLE [' + @targetTableName + '] DROP CONSTRAINT [' + @d_name + ']
GO
'
  SET @i = @i + 1
END

--生成创建索引的代码,没有考虑填充因子等选项,使用的是默认值
SET @i 
= 1
WHILE (@i 
<= (SELECT COUNT(i_no) FROM @indexName))
BEGIN
  SELECT @i_name 
= i_name,@i_type = type_desc,@is_unique = is_unique,@is_key = is_key FROM @indexName WHERE i_no = @i
  IF (@i_name 
is null)    --如果没有索引或键直接退出
    BREAK;
  SET @cmd_temp 
= 'set @c_name = ''''
    SELECT @c_name = @c_name + '',['' + a.name + (CASE b.is_descending_key WHEN 1 THEN ''] DESC'' ELSE ''] ASC'' END)
    FROM 
' + @sourceDB + '.sys.columns a inner join ' + @sourceDB + '.sys.index_columns b 
    ON a.object_id 
= b.object_id AND a.column_id = b.column_id inner join ' + @sourceDB + '.sys.indexes c
    ON b.object_id 
= c.object_id AND b.index_id = c.index_id
    WHERE a.object_id 
= (SELECT object_id FROM ' + @sourceDB + '.sys.tables WHERE name = ''' + @sourceTableName + ''') AND c.name = ''' + @i_name + ''''

  EXEC sp_executesql @cmd_temp,N
'@c_name varchar(200) output',@c_name output

  IF (@is_key 
= 1)    --键和索引的创建方法不一样
    SET @cmd_add_index 
= @cmd_add_index + 'ALTER TABLE [' + @targetTableName + '] ADD CONSTRAINT [' + REPLACE(@i_name,@sourceTableName,@targetTableName) + '] PRIMARY KEY ' + @i_type + char(13) + '(' + SUBSTRING(@c_name,2,len(@c_name)) + ')' + '
GO
'
  ELSE IF (@is_unique_key = 1)  --唯一键
    SET @cmd_add_index 
= @cmd_add_index + 'ALTER TABLE [' + @targetTableName + '] ADD CONSTRAINT [' + REPLACE(@i_name,@sourceTableName,@targetTableName) + '] UNIQUE ' + @i_type + char(13) + '(' + SUBSTRING(@c_name,2,len(@c_name)) + ')' + '
GO
'
  ELSE  --普通索引
    SET @cmd_add_index 
= @cmd_add_index + 'CREATE ' + (CASE @is_unique WHEN 1 THEN 'UNIQUE' ELSE '' END) + ' ' + @i_type + ' INDEX [' + REPLACE(@i_name,@sourceTableName,@targetTableName) + '] ON [' + @targetTableName + ']' + char(13) + '(' + SUBSTRING(@c_name,2,len(@c_name)) + ')' + '
GO
'
SET @i = @i + 1 --循环下一个键或索引
END 
--end while

--生成创建 CHECK 约束的代码
SET @cmd_temp 
= 'SET @cmd_add_check = ''''
SELECT @cmd_add_check = @cmd_add_check + ''ALTER TABLE [' + @targetTableName + '] WITH NOCHECK ADD CONSTRAINT '' + name + '' CHECK '' + definition + ''
GO
'' FROM ' + @sourceDB + '.sys.check_constraints WHERE parent_object_id = (SELECT object_id FROM ' + @sourceDB + '.sys.tables WHERE name = ''' + @sourceTableName + ''')'
EXEC sp_executesql @cmd_temp,N'@cmd_add_check varchar(2000) OUTPUT',@cmd_add_check OUTPUT

--判断是否有自增长列
SET @cmd_temp 
= 'IF EXISTS
 (SELECT name FROM ' + @sourceDB + '.sys.columns WHERE object_id = (SELECT object_id FROM ' + @sourceDB + '.sys.tables WHERE name = '''+ @sourceTableName + ''') AND is_identity = 1)
BEGIN
  SET @identity_on 
= ''SET IDENTITY_INSERT [' + @tmpTableName + '] ON
GO
''
  SET @identity_off 
= ''SET IDENTITY_INSERT [' + @targetTableName + '] OFF
GO
''
END
ELSE
BEGIN
  SET @identity_on 
= ''''
  SET @identity_off 
= ''''
END
'
EXEC sp_executesql @cmd_temp,N'@identity_on varchar(60) OUTPUT,@identity_off varchar(60) OUTPUT',@identity_on OUTPUT,@identity_off OUTPUT

--生成创建外键约束的代码
SET @cmd_temp 
= 'SET @cmd_add_foreign = ''''
SELECT @cmd_add_foreign = @cmd_add_foreign + ''ALTER TABLE ' + @targetTableName + ' ADD CONSTRAINT '' + a.name +
    
'' FOREIGN KEY ('' + (SELECT name FROM ' + @sourceDB + '.sys.columns WHERE OBJECT_ID = b.parent_object_id AND column_id = b.parent_column_id) + '') REFERENCES '' + 
    (SELECT name FROM 
' + @sourceDB + '.sys.tables WHERE object_id = a.referenced_object_id) + ''('' + (SELECT name FROM ' + @sourceDB + '.sys.columns WHERE OBJECT_ID = b.referenced_object_id AND column_id = b.referenced_column_id) + '') ON UPDATE '' +
    CASE update_referential_action WHEN 
0 THEN ''SET NULL'' WHEN 1 THEN ''CASCADE'' WHEN 2 THEN ''NO ACTION'' ELSE ''SET DEFAULT'' END + '' ON DELETE '' +
    CASE delete_referential_action WHEN 
0 THEN ''SET NULL'' WHEN 1 THEN ''CASCADE'' WHEN 2 THEN ''NO ACTION'' ELSE ''SET DEFAULT'' END + ''
GO
''
  FROM 
' + @sourceDB + '.sys.foreign_keys a INNER JOIN ' + @sourceDB + '.sys.foreign_key_columns b ON a.object_id = b.constraint_object_id
 WHERE a.parent_object_id 
= (SELECT object_id FROM ' + @sourceDB + '.sys.tables WHERE name = ''' + @sourceTableName + ''')'
EXEC sp_executesql @cmd_temp,N'@cmd_add_foreign varchar(500) OUTPUT',@cmd_add_foreign OUTPUT

--生成 INSERT 语句
SET @cmd_temp 
= 'SELECT @c_A = '''', @c_B = ''''
SELECT @c_A = @c_A + ''['' + a.name + ''],'',@c_B = @c_B +
  CASE WHEN b.name IS NOT NULL THEN 
''['' + b.name  + '']''
  ELSE (CASE WHEN default_object_id 
!= 0 THEN definition
    WHEN is_nullable 
= 0 THEN
      (CASE WHEN system_type_id 
in(48,52,56,59,60,62,106,108,122,127)THEN ''0'' ELSE '''''''''''' END)
    ELSE 
''NULL'' END)END + '',''
 FROM
  (SELECT a.name,a.system_type_id,a.is_nullable,a.default_object_id,b.definition FROM 
' + @sourceDB + '.sys.columns a
     LEFT JOIN 
' + @sourceDB + '.sys.default_constraints b ON a.object_id = b.parent_object_id AND a.default_object_id = b.object_id
    WHERE a.object_id 
= (SELECT object_id from ' + @sourceDB + '.sys.objects WHERE type = ''U'' AND name = ''' + @sourceTableName + ''' AND is_computed = 0))a
 LEFT JOIN
  (SELECT name FROM 
' + @targetDB + '.sys.columns WHERE object_id = 
    (SELECT object_id from 
' + @targetDB + '.sys.objects WHERE type = ''U'' AND name = ''' + @targetTableName + ''' AND is_computed = 0))b
  ON a.name 
= b.name'
EXEC sp_executesql @cmd_temp,N'@c_A varchar(4000) OUTPUT,@c_B varchar(4000) OUTPUT',@c_name_A OUTPUT,@c_name_B OUTPUT
SET @cmd_insert 
= CAST('INSERT INTO [' as varchar(max)) + @tmpTableName + ']('+ SUBSTRING(@c_name_A,1,LEN(@c_name_A) - 1) +')
    SELECT ' + SUBSTRING(@c_name_B,1,LEN(@c_name_B) - 1) + ' FROM [' + @targetTableName + '] WITH (HOLDLOCK TABLOCKX)
GO
'

--生成创建 TRIGGER 的语句
SET @cmd_temp 
= 'SET @cmd_create_trigger = ''''
SELECT @cmd_create_trigger = @cmd_create_trigger + ''
exec(
'''''' + REPLACE(definition,'''''''','''''''''''') + ''
'''');'' FROM ' + @targetDB + '.sys.sql_modules WHERE object_id in
(SELECT object_id FROM 
' + @targetDB + '.sys.triggers WHERE parent_id = (SELECT object_id FROM ' + @targetDB + '.sys.tables WHERE name = ''' + @targetTableName + '''))'
EXEC sp_executesql @cmd_temp,N'@cmd_create_trigger nvarchar(max) OUTPUT',@cmd_create_trigger OUTPUT

--汇总所有的语句
SET @cmd_all 
= 'BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
USE [
' + @targetDB + ']
GO
BEGIN TRANSACTION
GO
' + @cmd_drop_default + @cmd_create_table + @cmd_add_default + @identity_on + @cmd_insert +
'
DROP TABLE [' + @targetTableName + ']
GO
EXECUTE sp_rename N
''' + @tmpTableName + ''',N''' + @targetTableName + ''',''OBJECT'' 
GO
' + @cmd_add_index + @identity_off + 'COMMIT'

--执行或打印生成的语句
IF (@enable 
= 1)
BEGIN
  
--批处理的时候去掉 @cmd_all 中的 'GO' 以后才能执行
  SET @cmd_all 
= REPLACE(@cmd_all,('GO' + char(13)),'')
  BEGIN TRANSACTION
  BEGIN TRY
    EXEC (@cmd_all)
    IF (@cmd_add_check 
+ @cmd_add_foreign != '')
    BEGIN   
--这里有点麻烦,必须把上面的建好才能建约束,不知道为什么
       SET @cmd_all 
= 'USE [' + @targetDB + '];
'
 + @cmd_add_check + @cmd_add_foreign
      SET @cmd_all = REPLACE(@cmd_all,('GO' + char(13)),'')
      EXEC (@cmd_all)
    END
    IF (@cmd_create_trigger 
!= '')  --如果表有触发器则继续添加触发器
    BEGIN
      SET @cmd_create_trigger 
= 'USE [' + @targetDB + '];
'
 + @cmd_create_trigger
      EXEC (@cmd_create_trigger)
    END
    COMMIT
  END TRY
  BEGIN CATCH
    print (ERROR_MESSAGE())
    ROLLBACK
  END CATCH
END  
--end if
ELSE IF (@enable 
= 0)
BEGIN
  SET @cmd_all 
= '/*为了防止任何可能出现的数据丢失问题,您应该先仔细检查此脚本,然后再在数据库设计器的上下文之外运行此脚本。*/
'
 + @cmd_all + char(13) + @cmd_create_trigger
  PRINT SUBSTRING(@cmd_all,1,8000)  -- PRINT 一次最多打印8000个字符
  SET @i 
= 0
  WHILE (((LEN(@cmd_all) 
- @i * 8000) / 8000) > 0)
  BEGIN 
--如果输出的字符串大于8000则循环打印出来
    SET @i 
= @i + 1
    PRINT SUBSTRING(@cmd_all,@i 
* 8000 + 1,8000)
  END  
--end while
END  
--end else if
ELSE    
--如果传入的是 null 则直接执行,抛出具体的错误信息,建议不要使用
BEGIN
  SET @cmd_all 
= REPLACE(@cmd_all,('GO' + char(13)),' ') + @cmd_create_trigger
  EXEC (@cmd_all)
END  
--end else
GO

SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO

 

创建一个要备份的目标数据表:

 

CREATE TABLE Old_Novel_BookInfo
(
    id 
int not null,
) 
--这里字段可以随意写,因为之后都会被新的结构覆盖

 

 

将数据导入备份目标表:

 

EXEC NovelTableLayout  '源数据库' , '目标数据库' , '新约束前缀' ,'Novel_BookInfo' ,'Old_Novel_BookInfo' , '1'

 

最后一步就是完成将历史数据导入备份数据表:

 

INSERT INTO Old_Novel_BookInfo SELECT * FROM Novel_BookInfo

 

 

 

 

 

posted on 2009-02-20 19:57  布颜书  阅读(1337)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3