2010-05-14 31 views
1

场景:如何以编程方式验证,创建和更新SQL表结构?

我有一个应用程序(C#)期望一个SQL数据库和登录,这是由用户设置。一旦连接,它将检查是否存在多个表格,如果没有找到,则创建它们。

我想通过让程序能够向这些表添加列来扩展这一点,如果我发布依赖新列的程序的新版本。

问:

什么是编程检查现有的SQL表的结构和创建或更新,以符合预期结构的最佳方式?

我打算遍历所需列的列表,并在它不包含新列时更改现有表。我不禁想知道是否有一种不同或更好的方法。

标准:

这里有一些我的期望和自我强加的规则:该程序可能不再使用某些列的

  • 较新的版本,但他们将被保留数据记录目的。换句话说,没有列将被删除。
  • 表中的现有数据必须保留,所以不能简单地删除和重新创建表。
  • 在所有情况下,新添加的列将允许空数据,因此通过具有默认空值来处理旧记录的数量。

例子:

下面是一个示例表(因为视觉的例子帮助!):

 
id datetime   sensor_name sensor_status x1 x2 x3 x4 
1 20100513T151907 na019  OK    0.01 0.21 1.41 1.22 
2 20100513T152907 na019  OK    0.02 0.23 1.45 1.52 

然后,在新版本中,我可能要添加列x5。 “x -columns”都是接受null的数据存储列。

编辑:

我更新上述试样台。它更多的是日志而不是父表。因此传感器将在记录表中反复显示记录的值。一个单独的父表包含地理和其他物流信息传感器,使得我希望修改表的子表。

回答

2

这是一个非常麻烦的功能,您正在考虑实施。我会建议反对它,而不是考虑使用第三方工具,如红门的Sql脚本更改比较:http://www.red-gate.com/products/SQL_Compare/index.htm

如果您有疑问,请考虑下载试用版本的软件,并执行两个结构diff脚本数据库有一些不小的差异。从结果中可以看出,这些操作的考虑并不简单。

围绕此类问题的另一种方法是使用EAV模型来重新设计你的数据库:(支点动态地添加行因而从未改变结构它有自己的问题,但它是非常灵活的。)http://en.wikipedia.org/wiki/Entity-attribute-value_model

(要使用差异工具,你必须拥有所有数据库版本的副本,并创建diff脚本,这些脚本将会在新版本和升级版本中执行完毕,这是它自己维护的一大麻烦。对于一个这样的事情来说,它错误地得到了很多不像传统数据库结构一样的性能,但我已经使用过很多次了,事实上,我有一个符合HIPAA标准的EAV数据库(Sql Server 2000),已经有六年多的生产经验包含数十或数百万行的EAV表格,并且它仍然强大,没有大的减速。当然,我们不会针对该数据库进行大量报告。对于报告,我们有一个将数据变为关系结构的导出。)

+0

麻烦是对的!我希望能够向我们的客户发布新版本,以便他们不必修改他们的数据库。我还不确定我将如何利用Sql Compare(因为我实际上无法将* old *表与新的表进行比较(新的表不会在他们的服务器上存在)。在EAV上。 – JYelton 2010-05-14 21:29:26

+0

将此项目转换为EAV可能是最佳解决方案。这将会更长远一些,但它似乎正好处理这种类型的应用。 – JYelton 2010-05-18 15:17:15

+0

@JYelton - 我不同意EAV是你最好的选择。请注意Paul Sasik的帖子末尾的关键部分:“我们不做大量报道”。这是难题的关键之一。与仅仅提取数据相比,搜集信息与EAV中的数据完整性和其他一系列问题相比,难度要大得多。如果你所做的只是存储一大堆你永远不会报告的数据,并且永远不会查询某个特定的属性,而是总是将整个数据集合起来,那么EAV就没有问题。否则,你可能会要求维修头痛。 – Thomas 2010-07-15 04:20:10

0

如果您不得不依靠应用程序进行表更改来构建某些内容,那么您的设计是有缺陷的。您应该有一个传感器值(x1,x2等)的相关表格,然后您可以添加另一条记录,而不必创建一个新列。

建议的子表结构

READINGS ID INT Reading_type VARCHAR(10) Reading_Value INT

然后,在表中的数据将为:

ID Reading_type Reading_value 1 X1 2 1 x2 3 1 x3 1 2 x1 7

+0

示例表格表示具有4个值的传感器,但它不是单个条目。定期查询同一个传感器并记录其值。实际上有数百个传感器和大约60个值。我会更新我的示例以显示这一点,但我不确定有什么方法可以从中创建一对多关系。如果管理层想要追踪他们想要追踪的新属性,我想简单地添加一个新列来保存新值。 – JYelton 2010-05-14 21:19:03

2

我看到的常见解决方案是将某个版本信息存储在数据库中。也许有一个非常小的表:

CREATE TABLE DB_PROPERTIES (key varchar(100), value varchar(100)); 

,那么你可以添加行:

key | value 
version | 12 

然后,你可以只创建一个SQL更新脚本(或者脚本集)从12版本更新数据库到版本13

declare v varchar(100) 
select v=value from DB_PROPERTIES where key='version' 
if v ='12' 
    #do upgrade from 12 to 13 
elsif v='11' 
    #do upgrade from 11 to 13 

...and so on 

取决于您想要支持的升级路径,可以添加更多的案例。你当然也可以把这个升级逻辑转移到C#中,或者任何适合你的设计。但是,将数据库版本信息存储在数据库中将使得更容易找出已存在的内容,而不是单独查询所有数据库结构。

+0

这似乎很难(或者更多),因为我打算按照我已经保存在程序本身的列表来检查每列。尽管如此,你让我想到了存储添加哪些列的版本,所以可能有一种方法可以避免迭代步骤。 – JYelton 2010-05-14 21:35:45

0

尝试Microsoft.SqlServer.Management.Smo
这些是一组C#类,它们为SQL Server数据库对象提供了一个API。
Microsoft.SqlServer.Management.Smo.Table具有一个Columns集合,可让您查询和处理这些列。
玩得开心。