3

我继承了一个(Microsoft?)SQL 数据库,它在原始状态下并不是很原始。我正在尝试修复其中的一些非常奇怪的东西——其中之一是不一致的 ID 条目。

在accounts 表中,每个条目都有一个称为accountID 的编号,在其他几个表(注释、设备等)中都引用了该编号。问题是数字(出于某种随机原因) - 当只有大约 7000 个条目时,范围从大约 -100000 到 +2000000。

有没有什么好方法可以在更改其他表中的相应数字时重新编号它们?在我的支配下,我也有 ColdFusion,所以任何适用于 SQL 和/或我会接受的东西。

4

6 回答 6

4

对于代理键,它们是没有意义的,所以除非你真的有一个数据库完整性问题(比如没有正确定义外键约束)或者你的身份接近其数据类型的最大值,我会不理会它们并继续其他一些会产生更大影响的低级成果。

于 2009-01-15T04:50:29.593 回答
2

在这种情况下,听起来“为什么”比“如何”更好。OP 指出有一个奇怪的问题需要解决,但没有说明为什么会出现问题。它会引起问题吗?改变这些数字会产生什么积极影响?除非您最初对系统进行了编程并准确理解数字为何处于当前状态,否则您进行这样的更改是非常冒险的。

于 2009-01-15T19:36:39.540 回答
1

如果这是一个财务应用程序,我会先与会计师(或至少您的财务人员)交谈,然后再弄乱帐户表中的数字。账目表对于如何报告财务状况非常重要。这些 ID 可能具有您不理解的含义。除非有理由,否则没有人会输入否定的身份。在任何情况下我都不会改变这一点,除非我明白为什么它一开始是消极的。您可以通过进行不必要的更改来真正搞砸您的税务报告或其他事情。

于 2009-01-15T14:15:54.973 回答
0

您可能会禁用外键关系(如果您能够暂时使其脱机),然后使用脚本更新主键。我之前使用过这个更新脚本来改变值,你可以很容易地把这段代码包装在一个游标中,一个一个地遍历有问题的键值,并将任意值更新为你正在跟踪的递增值的。

在此处查看脚本:http: //vyaskn.tripod.com/sql_server_search_and_replace.htm

如果您只有一个使用主键的表列表,您可以设置一系列在游标内运行的 UPDATE 语句,然后您就不需要使用这个脚本(这可能有点慢)。

不过,值得一问的是,为什么这些值显得格格不入。该数据库是否有不断添加和删除的值?主键值真的是任意的,还是它们只是看起来是,但它们真的有意义?虽然我完全赞成巩固,但你必须确保这些价值观没有任何意义。

于 2009-01-15T04:46:26.200 回答
0

使用 ColdFusion,这不应该是一项艰巨的任务,但它会很混乱,您必须小心。您可以使用的一种方法是编写数据库脚本,然后生成一个全新的空白表模式。将 accountID 设置为新数据库中的标识字段。

然后,使用 ColdFusion,编写一个查询,该查询将提取所有旧帐户数据并将它们一一插入到新数据库中。对于每一行,让新数据库分配一个新 ID。每次插入后,提取新 ID(使用 @@IDENTITY 或 MAX(accountID))并将新 ID 和旧 ID 一起存储在临时表中,以便您知道哪些旧 ID 属于哪些新 ID。

接下来,对每个子表重复该过程。对于每个旧 ID,提取其子条目并使用新 ID 将它们重新插入到新数据库中。如果子表上的主键没问题,您可以按原样插入它们,或者如果它们无关紧要,让服务器分配新的主键。

通过暂时禁用关系来分配新的 ID 可能会起作用,但如果为其中一个条目分配的 ID 已被旧数据使用,那么您也可能会遇到冲突,这可能会导致冲突。

于 2009-01-15T04:50:09.033 回答
0

在帐户表中为您的新 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 列映射到帐户表。

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。从这里开始应该很简单。

  1. 打破 accountID 上的所有外键。
  2. 在每个表上,UPDATE [table] SET accountID = new_accountID。
  3. 重新添加 accountID 的外键。
  4. 从所有表中删除 new_accountID,因为它不再需要。
于 2009-01-15T13:37:37.937 回答