我之所以问这个问题,是因为我们一直在使用遗留数据库,如果您试图将ORM放在没有主键的表上,可能会出现问题。在这个论坛上,这个问题的许多回复者都说(在我看来相当漠不关心),只需向表添加一个主键。没什么大不了的。
现在我要问,如果你突然在现有的数据库中添加主键,你能想象到可能的负面影响,特别是对客户端应用程序吗?如果问题太宽泛,那基本上已经回答了我的问题。
在开始之前,请确保没有其他机制来强制惟一性。例如,not null unique
声明在行为上等同于primary key
声明。可能会有触发因素;可能存在要求数据库更新通过存储过程的特权;可能还有其他机制是我今天早上没有想到的。
你似乎在谈论一些事情,比如添加一个自动递增的整数列,并将其声明为主键。
假设当前确实没有是主键,并且假设没有其他的与主键等效,那么主要问题涉及应用程序代码隐式地依赖于列的顺序或列的数量。
例如,这是一条有效的SQL语句。您可能会在应用程序代码中发现类似的内容。select *
from your_table
order by 1 desc;
该语句将按照第一列中的值降序对结果集进行排序。
如果向表中添加一列,并将该列定位为表定义中的第一列,则该SQL语句将开始以不同于其他客户端期望的顺序返回数据。
有些平台不允许alter table
语句改变列的顺序;新列只出现在表定义的末尾。但是即使在这些平台上,DBA也可以转储数据,先用新列重写create table
语句,然后重新加载数据。
这类问题——更改表中的列数——可能会破坏一些数据导入和导出。
没有列名的插入语句,如insert into foo values (...)
可能会失败。
语句也可能出现在触发器中,但这在数据库代码中比应用程序代码中更容易出现问题。
有可能出现性能问题。将新列用作聚集索引(某些平台上的选项)将改变行的物理顺序。这肯定会改变的表现,但我不能预测这是否一定是一件坏事。表将变得更宽——但不是太宽——这意味着磁盘上的页上可以容纳的行略少。
弹性解决方案
- 修改现有表的名称。(这很简单,但可能并不容易。)
- 创建一个与原始表具有相同结构和名称的可更新视图。
- 修改原表的结构
所有使用原始表名称的应用程序代码现在都将使用可更新视图的名称。由于视图的结构和行为与原始表相同,因此所有应用程序代码都应该继续工作。(如果应用程序代码需要知道它是在处理表还是视图,我会感到惊讶,但这是一个可能的问题。)
<<p> 预防措施/strong> 在任何情况下,您都不应该首先在生产中进行此更改。您应该首先在本地进行更改,然后在您的测试环境中进行更改,最后—当您耗尽了我们的集体想象力时—转移到生产环境中。并且每次转移到生产中一点。添加列,然后稍等。填充列,并等待一段时间。