SQL Server 2012 已经发布,维护如此多版本的SQL Server需要合适的工具和技巧
2012年第二季度,SQL Server 2012就已经发布。作为普通的开发者,并没有太多的热情去追随这些潮流的技术,经过短暂的尝鲜,果断决定放在一边,不予以理会。从SQL Server 2000起,就一直把SQL Server作为首选的项目数据库平台。随着SQL Server 2005, 2008, 2008 R2, 2012等系列版本的陆续发布,面临的问题也越来越多。遇到最多的一个问题是,SQL Server不同版本间的数据库转化问题。
举例说明,在几百个客户中,至今仍然有使用SQL Server 2000的,以我的经验,这个版本的SQL Server还有相当多的客户在用。2006年之后的客户,从开始上项目就推荐用SQL Server 2005,所以沿袭过来,他们一直是这个版本的。到了2009年,新的客户又被推荐使用SQL Server 2008或是SQL Server 2008 R2,从理解上来说,SQL Server 2008 R2相当于SQL Server 2010。再加上这几个版本之间有补丁包,SQL Server的版本又增加了好几个,理论上推荐客户升级到最新的补丁包,也有客户因稳定性的原因,拒绝升级。于是乎,就为一个SQL Server,就有好多个版本。作为开发者,一般只有装最新的SQL Server,以便于防止在查找客户问题时,发生数据库版本不兼容,无法还原数据库的错误。然而,最新的SQL Server 2012,不再支持SQL Server 2000的备份文件,这不是个好消息。
对于下面的这个错误,在客户比较多的情况下,经常会遇到。比如要拿客户的数据库回来查找问题,这个问题经常出现。如果耐心不好,就干脆装个最新的SQL Server,如果不想这样,下面提供的几种方法,也许对你有所帮助。
SQL Server Import/Export
SQL Server自带的导入导出向导,大部分情况下有效。我推荐的步骤是先创建目标数据库的脚本,让SQL Server只传输数据,而不是既创建表,又传输数据,以减少一些很奇怪的错误。
这个工具用的不多,有各种奇怪的问题,没有积累多的经验。
SQL Object Level Recovery Native
RedGate公司SQL Toolbet系列组件的一个,可以从SQL Server的备份文件中生成带数据的SQL语句,在目标数据库中直接执行即可。这种方法的成功率很高,简单的带数据的SQL INSERT语句,在任何版本的SQL Server中,都可以很正确的插入数据。
点击View Recovery Script,可以查看它生成的SQL 脚本,直接把备份数据文件转化为SQL语句,相当方便。
目前支持SQL Server 2008 R2的备份集,可以满足绝大部分客户的应用。
SQL Query Generator
公司的工具库里面的一个工具,一般是给客户维护(support)人员用,用于快速导入导出数据。
以Northwind数据库为例子,可以马上生成这个表的INSERT语句,保存到剪贴板中,例子语句如下所示
INSERT INTO [Employees] ([EmployeeID],[LastName],[FirstName],[Title],[TitleOfCourtesy],[BirthDate],[HireDate],[Address],[City],[Region],[PostalCode],[Country],[HomePhone],[Extension],[Photo],[Notes],[ReportsTo],[PhotoPath]) VALUES(9, N'Dodsworth', N'Anne', N'Sales Representative', N'Ms.', '1966-1-27 0:0:0.0', '1994-11-15 0:0:0.0', N'7 Houndstooth Rd.', N'London', N'', N'WG2 7LT', N'UK', N'(71) 555-4444', N'452', N'System.Byte[]', N'Anne has a BA degree in English from St. Lawrence College. She is fluent in French and German.', 5, N'http://accweb/emmployees/davolio.bmp') INSERT INTO [Employees] ([EmployeeID],[LastName],[FirstName],[Title],[TitleOfCourtesy],[BirthDate],[HireDate],[Address],[City],[Region],[PostalCode],[Country],[HomePhone],[Extension],[Photo],[Notes],[ReportsTo],[PhotoPath]) VALUES(8, N'Callahan', N'Laura', N'Inside Sales Coordinator', N'Ms.', '1958-1-9 0:0:0.0', '1994-3-5 0:0:0.0', N'4726 - 11th Ave. N.E.', N'Seattle', N'WA', N'98105', N'USA', N'(206) 555-1189', N'2344', N'System.Byte[]', N'Laura received a BA in psychology from the University of Washington. She has also completed a course in business French. She reads and writes French.', 2, N'http://accweb/emmployees/davolio.bmp')
这样,很方便的搬动数据库到另一个位置,简单灵活。对于图片数据,要单独处理。对于有种子字段的列,要在导入前,开启,语句如下所示
SET IDENTITY_INSERT dbo.ICMOVh OFF SET IDENTITY_INSERT dbo.ICMOVD ON
对于主从表数据,先导入主表,再导入从表。删除主从表数据,则是先删从表,再删主表。
LLBL Gen
作为ORM的基本特征,跨数据库平台。你可以运用此特点,从一个数据库中读取,然后改变连接字符串,在另一个数据库中保存,完成数据库的转移工作。以销售单为例子,读取销售单的代码,看起来是这样的
public SalesOrderEntity GetSalesOrder(System.String RefNo, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList fieldList) { SalesOrderEntity _SalesOrder = new SalesOrderEntity(RefNo); using (DataAccessAdapterBase adapter = GetCompanyDataAccessAdapter()) { bool found = adapter.FetchEntity(_SalesOrder, prefetchPath, null, fieldList); if (!found) throw new Foundation.Common.RecordNotFoundException("Invalid SalesOrder"); } return _SalesOrder; }
同时,保存销售单的代码,看起来是这样的
public SalesOrderEntity SaveSalesOrder(SalesOrderEntity SalesOrder, EntityCollection entitiesToDelete, string seriesCode) { using (DataAccessAdapterBase adapter = GetCompanyDataAccessAdapter()) { try { adapter.StartTransaction(IsolationLevel.ReadCommitted, "SaveSalesOrder"); adapter.SaveEntity(SalesOrder, true, false); adapter.Commit(); } catch { adapter.Rollback(); throw; } } return SalesOrder; }
这些代码均是由代码生成器直接生成的。完成数据转移的ORM代码,看起来是这样子的
string source = "Data Source=192.168.0.96;Initial Catalog=TS;User Id =sa ; Password =holiday;"; string destination = "Data Source=192.168.0.200;Initial Catalog=TS;User Id = sa ; Password = holiday;"; ClientProxyFactory.ConnectionString = source; ISalesOrderManager manager = ClientProxyFactory.CreateProxyInstance<ISalesOrderManager>(); SalesOrderEntity salesOrder = manager.GetSalesOrder(customerNo, null); ClientProxyFactory.ConnectionString = destination; manager.SaveSalesOrder(salesOrder);
就这样几句代码,把销售单数据从192.168.0.96的机器搬动到192.168..0.200的机器上。
更进一步的,这几句代码可以写成一个泛型的方法,传入参数,即可达到批量搬动数据。
以我的理解和摸索,当前仍然是让项目使用主流的SQL Server 2005,搭配Express版本的SQL Server 2008, 2008 R2,这样可以读取高于SQL Server 2005的客户数据库,兼容于更新的数据库。为了在不同的版本的SQL Server之间互导数据,供您参考。