Sql Server 2005 自动生成修改表的代码(存储过程)
2007-06-25 23:45
633 查看
我们公司的数据库也真是多啊,大大小小的有30多个,大一点的分公司都有自己独立的数据库,然后有些库还需要有给客户和供应商以及自己内部新员工的 Test 库,还有要给开发部门的 develop 库,这些库的结构当然还要求是一样的,因为很多数据是需要上传到集团总部去的,特别是人事和财务方面的数据。而以前的设计跟现在的实际需求相差也有点大的,所以修改表结构的事情几乎每天都有发生,公司上层一个简单的决定真是难为死我这个做数据库维护的人了。
很多时候要增加的字段必须放在要求的位置上,不能放最后,有些字段一需要其他所有关联的字段也有修改,还是所有的数据库中有的都必须修改。当然这都不是很难,都是很简单的事情,可是一个个的改对我懒人高升来说真是莫大的痛苦,所以我又想出了一个偷懒的办法,写了一个修改表的存储过程,比原先写的那个各有各的好处,这个可是模仿 MS 在企业管理器中拖拖鼠标自动生成的代码写的。
原先那个存储过程:http://blog.csdn.net/hb_gx/archive/2007/06/18/1655990.aspx
测试的效果还是很不错的,高兴!虽然又浪费我一个双休,可是今天上班真是轻松啊,旁边那个高级一点的DBA自己点鼠标点的只响也不怕麻烦,想我高升这辈子偷懒也是偷出了点小名堂的。:)
本存储过程能把某个数据库的表结构复制到指定的数据库同名表中,但是不改目标数据库中的数据,原始数据还是保留的,跟数据库复制是有区别的,如果你有两个数据库是一样的,只是数据不同,那么当其中一个修改了结构后可以使用本存储过程帮你自动更新另一个结构。其实就是和在企业管理器中拖拖鼠标一样的,只是可以换到别的数据库生成。
USE msdb
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--建立人: 高升
--建立日期:2007/06/25
--修改日期:2007/08/01
--功能目的:复制源DB中某个表的结构到目标DB的同名表中,只改表结构、约束、索引等,不改目标DB的数据
--注意: 默认约束名是自动生成的新名字,如果和以前的名字有冲突请手工修改后运行,
-- 新的默认约束名统一为 'DF_表名_列名' ,如果要使用原默认约束名需要修改代码
ALTER PROCEDURE [dbo].[AlterTableLayout]
@sourceDB sysname, --源DB名
@targetDB sysname, --目标DB名
@schemaName sysname = 'dbo',--架构名,此参数保留,未使用
@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
最后想了一想,发现外键这个东西不好加的,我一直不喜欢用,我们公司里所有的表都没有建立外键关系的,所以没有怎么测试的,使用的时候注意一下。还有如果表有触发器,修改的时候注意触发器中某些特定字符,可能会导致执行失败。另外定义的那些字段的长度并不是太好指定,如果全部都用varchar(max)好像也没那个必要的,如果遇到某些错误,可能是字段定义的长度问题,这个还是要根据实际情况了决定,定义多了也是浪费。个人认为一个表内字段可能有很多,相应的默认约束也会很多,但INDEX和CHECK约束通就常不会有很多了。
建立一个测试环境,测试一下,看看存储过程的效果:
--创建第一个测试库和一个表,有很多的类型和计算列约束之类的东东
CREATE DATABASE Test1
GO
USE Test1
GO
CREATE TABLE dbo.T1
(
t2 int NULL,
t1 uniqueidentifier NOT NULL,
t3 char(4) NULL,
t4 varchar(8) NOT NULL,
t5 decimal(6, 2) NOT NULL,
t6 AS ([t2]+[t5]/(2)),
t7 AS ([t2]+[t5]/(4)) PERSISTED ,
t8 int NOT NULL IDENTITY (100, 10),
t9 bigint NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_T1 ADD CONSTRAINT
DF_T1_t2 DEFAULT ((0)) FOR t2
GO
ALTER TABLE dbo.Tmp_T1 ADD CONSTRAINT
DF_T1_t4 DEFAULT ('') FOR t4
GO
ALTER TABLE dbo.Tmp_T1 ADD CONSTRAINT
DF_T1_t5 DEFAULT ((10)) FOR t5
GO
ALTER TABLE dbo.Tmp_T1 ADD CONSTRAINT
DF_T1_t9 DEFAULT ((0)) FOR t9
GO
ALTER TABLE dbo.T1 ADD CONSTRAINT
PK_T1 PRIMARY KEY CLUSTERED
(
t1
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX IX_T1 ON dbo.T1
(
t3
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
--创建第二个测试库和一个表,就是一表,里面可以加点数据看看
CREATE DATABASE Test2
GO
USE Test2
CREATE TABLE dbo.T1
(
t1 uniqueidentifier NOT NULL,
t2 int NULL,
t4 varchar(8) NOT NULL,
t5 decimal(6, 2) NOT NULL,
t6 AS ([t2]+[t5]/(2)),
)
GO
--没加数据,可以随便加一点测试数据上去
执行看看,现在 Test2 里面的 T1 表变什么样子了,如果里面原来有数据的,看看现在的数据是不是一样啊?
--用刚建的存储过程测试看看,最后的1就直接执行了,如果想看生成的代码用0看看
EXEC msdb.dbo.AlterTableLayout 'Test1' , 'Test2' , 'dbo' ,'T1' ,'' , '1'
唉!我高升也真是有点 BT 的,工作日的时间到处玩,一到双休就冒出来免费加班,为什么每次到双休才能写出点东西啊?真不知道该怎么说我了,表现给谁看啊!
本篇地址:http://blog.csdn.net/hb_gx/archive/2007/06/25/1666347.aspx
6月份写出来的东西,现在已经8月份了,经过两个月的测试,现在已经肯定能正常运行。这期间修改了很多原先没有考虑的东西,感觉自己进步了很多,对系统试图的运用熟练不少!庆祝一下!
今天重新整理了一下,希望能够对同样有类似需求的人有帮助,也希望能够得到一些宝贵意见,谢谢!
注意:如果想将两个数据库里面所以的表都改成一样的,那就自己去写个循环来调用吧。
很多时候要增加的字段必须放在要求的位置上,不能放最后,有些字段一需要其他所有关联的字段也有修改,还是所有的数据库中有的都必须修改。当然这都不是很难,都是很简单的事情,可是一个个的改对我懒人高升来说真是莫大的痛苦,所以我又想出了一个偷懒的办法,写了一个修改表的存储过程,比原先写的那个各有各的好处,这个可是模仿 MS 在企业管理器中拖拖鼠标自动生成的代码写的。
原先那个存储过程:http://blog.csdn.net/hb_gx/archive/2007/06/18/1655990.aspx
测试的效果还是很不错的,高兴!虽然又浪费我一个双休,可是今天上班真是轻松啊,旁边那个高级一点的DBA自己点鼠标点的只响也不怕麻烦,想我高升这辈子偷懒也是偷出了点小名堂的。:)
本存储过程能把某个数据库的表结构复制到指定的数据库同名表中,但是不改目标数据库中的数据,原始数据还是保留的,跟数据库复制是有区别的,如果你有两个数据库是一样的,只是数据不同,那么当其中一个修改了结构后可以使用本存储过程帮你自动更新另一个结构。其实就是和在企业管理器中拖拖鼠标一样的,只是可以换到别的数据库生成。
USE msdb
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--建立人: 高升
--建立日期:2007/06/25
--修改日期:2007/08/01
--功能目的:复制源DB中某个表的结构到目标DB的同名表中,只改表结构、约束、索引等,不改目标DB的数据
--注意: 默认约束名是自动生成的新名字,如果和以前的名字有冲突请手工修改后运行,
-- 新的默认约束名统一为 'DF_表名_列名' ,如果要使用原默认约束名需要修改代码
ALTER PROCEDURE [dbo].[AlterTableLayout]
@sourceDB sysname, --源DB名
@targetDB sysname, --目标DB名
@schemaName sysname = 'dbo',--架构名,此参数保留,未使用
@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
最后想了一想,发现外键这个东西不好加的,我一直不喜欢用,我们公司里所有的表都没有建立外键关系的,所以没有怎么测试的,使用的时候注意一下。还有如果表有触发器,修改的时候注意触发器中某些特定字符,可能会导致执行失败。另外定义的那些字段的长度并不是太好指定,如果全部都用varchar(max)好像也没那个必要的,如果遇到某些错误,可能是字段定义的长度问题,这个还是要根据实际情况了决定,定义多了也是浪费。个人认为一个表内字段可能有很多,相应的默认约束也会很多,但INDEX和CHECK约束通就常不会有很多了。
建立一个测试环境,测试一下,看看存储过程的效果:
--创建第一个测试库和一个表,有很多的类型和计算列约束之类的东东
CREATE DATABASE Test1
GO
USE Test1
GO
CREATE TABLE dbo.T1
(
t2 int NULL,
t1 uniqueidentifier NOT NULL,
t3 char(4) NULL,
t4 varchar(8) NOT NULL,
t5 decimal(6, 2) NOT NULL,
t6 AS ([t2]+[t5]/(2)),
t7 AS ([t2]+[t5]/(4)) PERSISTED ,
t8 int NOT NULL IDENTITY (100, 10),
t9 bigint NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_T1 ADD CONSTRAINT
DF_T1_t2 DEFAULT ((0)) FOR t2
GO
ALTER TABLE dbo.Tmp_T1 ADD CONSTRAINT
DF_T1_t4 DEFAULT ('') FOR t4
GO
ALTER TABLE dbo.Tmp_T1 ADD CONSTRAINT
DF_T1_t5 DEFAULT ((10)) FOR t5
GO
ALTER TABLE dbo.Tmp_T1 ADD CONSTRAINT
DF_T1_t9 DEFAULT ((0)) FOR t9
GO
ALTER TABLE dbo.T1 ADD CONSTRAINT
PK_T1 PRIMARY KEY CLUSTERED
(
t1
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX IX_T1 ON dbo.T1
(
t3
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
--创建第二个测试库和一个表,就是一表,里面可以加点数据看看
CREATE DATABASE Test2
GO
USE Test2
CREATE TABLE dbo.T1
(
t1 uniqueidentifier NOT NULL,
t2 int NULL,
t4 varchar(8) NOT NULL,
t5 decimal(6, 2) NOT NULL,
t6 AS ([t2]+[t5]/(2)),
)
GO
--没加数据,可以随便加一点测试数据上去
执行看看,现在 Test2 里面的 T1 表变什么样子了,如果里面原来有数据的,看看现在的数据是不是一样啊?
--用刚建的存储过程测试看看,最后的1就直接执行了,如果想看生成的代码用0看看
EXEC msdb.dbo.AlterTableLayout 'Test1' , 'Test2' , 'dbo' ,'T1' ,'' , '1'
唉!我高升也真是有点 BT 的,工作日的时间到处玩,一到双休就冒出来免费加班,为什么每次到双休才能写出点东西啊?真不知道该怎么说我了,表现给谁看啊!
本篇地址:http://blog.csdn.net/hb_gx/archive/2007/06/25/1666347.aspx
6月份写出来的东西,现在已经8月份了,经过两个月的测试,现在已经肯定能正常运行。这期间修改了很多原先没有考虑的东西,感觉自己进步了很多,对系统试图的运用熟练不少!庆祝一下!
今天重新整理了一下,希望能够对同样有类似需求的人有帮助,也希望能够得到一些宝贵意见,谢谢!
注意:如果想将两个数据库里面所以的表都改成一样的,那就自己去写个循环来调用吧。
相关文章推荐
- 一个自动生成用ADO调用SQL SERVER的存储过程VB代码的ADDIN
- 刷新SQL Server所有视图、函数、存储过程 更多 sql 此脚本用于在删除或添加字段时刷新相关视图,并检查视图、函数、存储过程有效性。 [SQL]代码 --视图、存储过程、函数名称 DECLARE @NAME NVARCHAR(255); --局部游标 DECLARE @CUR CURSOR --自动修改未上状态为旷课 SET @CUR=CURSOR SCROLL DYNAMIC FO
- Sql Server 2005 使用代码修改列的属性(存储过程)
- MyBaties自动生成sql server代码number类型变为BigDecimal
- Unity修改自动生成的代码模板
- powerdesigner自动生成代码的修改
- ibatis代码自动生成工具ibator修改备忘
- 如何手动修改或增加word2007自动生成的目录的链接(修改域代码方式):
- Xcode 代码自动生成的版权相关修改
- ADT14或者15,修改代码后bin目录下不自动生成apk的解决方案
- ADT14或者15,修改代码后bin目录下不自动生成apk的解决方案
- SQL Server 2005 中为查询结果自动生成记录编号
- 修改XCODE自动生成代码模板
- maven+mybatis+mybatis-generator+sql server 2005自动生成代码,加上自定义分页插件和批量插入更新插件
- sqlserver存储过程:SQL Server 2005修改存储过程
- 根据表或者视图自动生成分页语句的存储过程,适用于Sql Server 2005及以上版本
- 升级到ADT v14/15,修改代码后bin目录下不自动生成apk的解决方案
- ADT14或者15,修改代码后bin目录下不自动生成apk的解决方案
- SQL Server主键自动生成_表and存储过程
- 使用存储过程修改sql server 2005 用户密码