2

我目前正在构建一个 Rails 应用程序,并且我正在努力确保我现在不会在数据库设计 (MySQL) 中犯任何大错误,这将困扰我。

目前,我在各种表中有一堆字段,这些字段引用了简单的常量数据。例如,我的一张表被调用rates,它的字段是 id,amountunit,单位是每小时/天/周/月。

这些值不会改变,而不是使用参考表,我只是使用一个CHAR来表示这些值,所以 hour 是'h', day 是'd', week 是'w'等等。我认为这将使数据库更加人性化,并限制 ID 以某种方式更改以及所有数据因此而损坏的可能性。

这似乎是一种合理的方法,还是我错过了一些潜在的陷阱?

4

2 回答 2

1

如果你真的想这样做,我建议使用一个ENUM专栏:

CREATE TABLE rates (
  id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
  amount INTEGER NOT NULL,
  unit ENUM( 'hour', 'day', 'week', 'month' ) NOT NULL
);

这比使用单字符缩写更具可读性,同时效率也不低。在严格的 SQL 模式下,它还确保插入无效值的尝试将被报告为错误。

(然而,eggyal 建议使用SMALLINT列并以小时为单位测量持续时间也值得考虑。)

附言。我对 Rails 不是很熟悉,但至少我在谷歌搜索“mysql rails enum”时得到的第一个结果是

“Rails 方面最好的部分是,您无需更改代码中的任何内容即可将 varchar 换成 ENUM。”

于 2012-12-29T02:46:57.243 回答
1

如果由我决定,我会使用包含键/值对的查找表,其中值是您想要的任何值。像这样的东西:

CREATE TABLE `lookup_rate_type` 
(
 `id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, 
 `name` VARCHAR(20) NOT NULL, 
 PRIMARY KEY (`id`), UNIQUE KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

然后,在您需要参考汇率的任何表格中,只需使用与您感兴趣的汇率相关的 id,让我们添加几行:

INSERT INTO `lookup_rate_type` SET name = 'second'; # id = 1
INSERT INTO `lookup_rate_type` SET name = 'minute'; # id = 2
INSERT INTO `lookup_rate_type` SET name = 'hour'; # id = 3

现在,如果您有一张需要参考费率的表格,您可以这样做:

INSERT INTO `some_table` SET rate = 27, rate_type_id = 3; # 27 / hour
INSERT INTO `some_table` SET rate = 3600, rate_type_id = 2; # 3600 / minute

这种方法的好处是,如果您决定只使用第一个字母来识别 rate_type,您只需更新lookup_rate_type表:

UPDATE `lookup_rate_type` SET name = 's' WHERE ID = 1 LIMIT 1;

即使您更改了名称值(在您理解的上下文中,第二个变为 s),存储与该值的关系的任何表都将保持不变。

使用此解决方案,您可以根据需要向查找表添加任意数量的行,而不必运行更改语句来添加枚举,如果处理大型表,这可能会很痛苦。

此解决方案的唯一缺点是您可能需要使用类常量来允许您的应用程序代码访问 int 值,以便您可以根据您的业务逻辑执行 CRUD 操作,例如:

class LookupRateType
{
    const SECOND = 1;
    const MINUTE = 2;
}

// Calling code example
$sql = sprintf('INSERT INTO some_table SET rate = %d, rate_type_id = %d', 27, LookupRateType::MINUTE);

此外,如果您愿意,在处理一小部分常量时,您可以完全放弃查找表而只处理类常量。这里的缺点是您在查找特定数据时必须知道 id,而不是使用查询:

# If you use class constants only, you can do this
SELECT * FROM some_table WHERE rate_type_id = (SELECT id FROM lookup_rate_type WHERE name = 'hour');

# But if you can lookup the context with the code you can simply input the id
SELECT * FROM some_table WHERE rate_type_id = 3;

这些是我在处理大量不同应用程序时遇到的场景,并且发现查找表和/或类常量是最佳解决方案。

于 2012-12-29T03:16:10.500 回答