在账户表中,每个条目都有一个称为accountID的数字,在其他几个表(注释、设备等)中引用它。问题在于这些数字(由于某种随机原因)范围从-100000到+2000000,而只有大约7000个条目。
有没有好的方法可以重新编号,并同时更改其他表中相应的数字?我还可以使用ColdFusion,因此任何与SQL和/或我接受的内容一起工作的内容都可以。
对于代理键,它们的意义在于无意义,因此除非您实际上存在数据库完整性问题(例如没有正确定义外键约束)或者您的标识接近其数据类型的最大值,否则我会将它们保持不变,并寻找其他更有影响力的低垂果实。
如果您可以将其离线,您可能可以禁用外键关系,然后使用脚本更新主键。我以前曾使用过此更新脚本来更改值,您可以很容易地将此代码包装在游标中,逐个查看相关的关键值,并将任意值更新为一个您正在跟踪的递增值。
在这里检查脚本:http://vyaskn.tripod.com/sql_server_search_and_replace.htm
如果您只有使用主键的表清单,您可以设置一系列UPDATE语句,这些语句在您的游标内运行,那么您就不需要使用这个脚本(它可能有点慢)。
值得问一下的是,为什么这些值看起来不匹配。这个数据库是否经常添加和删除值?主键值真的是任意的吗,还是它们只是表面上看起来如此,但实际上它们确实有意义?尽管我支持合并,但您必须确保这些值没有目的。
使用ColdFusion,应该不会是一个艰巨的任务,但会有些混乱,需要小心处理。一种可能的方法是编写脚本以操作数据库并生成全新、空白的表结构。在新数据库中将accountID设置为identity字段。
然后,使用ColdFusion编写一个查询,逐一将所有旧账户数据插入到新数据库中。对于每一行数据,让新数据库分配一个新ID。在每次插入之后,使用@@IDENTITY或MAX(accountID)提取新ID,并将新ID和旧ID一起存储在临时表中,以便知道哪些旧ID属于哪些新ID。
接下来,对每个子表重复此过程。对于每个旧ID,提取其子项并使用新ID重新插入到新数据库中。如果子表的主键没有问题,可以按原样插入,或者如果不重要,可以让服务器分配新主键。
通过暂时禁用关系来直接在原位分配新ID也可能有效,但如果其中一个条目被分配了已经被旧数据使用的ID,则可能会发生冲突。
ALTER TABLE accounts
ADD new_accountID int IDENTITY
ALTER TABLE notes
ADD new_accountID int
ALTER TABLE equipment
ADD new_accountID int
然后,您可以将每个引用表上的new_accountID列映射到accounts表。
UPDATE notes
SET new_accountID = accounts.new_accountID
FROM accounts
INNER JOIN notes ON (notes.accountID = accounts.accountID)
UPDATE equipment
SET new_accountID = accounts.new_accountID
FROM accounts
INNER JOIN equipment ON (equipment.accountID = accounts.accountID)
此时,每个表都有旧密钥的accountID和新密钥的new_accountID。从这里开始应该很简单。