2

私は現在Railsアプリを構築しており、データベース設計(MySQL)で大きな間違いを犯さないように努めています。

現在、さまざまなテーブルに、単純な定数データを参照するフィールドがたくさんあります。たとえば、私のテーブルの1つが呼び出されrates、そのフィールドは、、、 idamountありunit、単位は時間/日/週/月です。

これらの値は変更されません。参照テーブルを使用する代わりにCHAR、値を表すために1つを使用しただけなので、時間は'h'、日は'd'、週はなどになり'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モードでは、無効な値を挿入しようとするとエラーとして報告されることも保証されます。

(ただし、SMALLINTカラムを使用し、時間を時間単位で測定するというeggyalの提案も検討する価値があります。)

追伸 私はRailsにあまり詳しくありませんが、少なくとも「mysqlrailsenum」をグーグルで検索したときに得られた最初の結果は次のようになっています。

「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;

名前の値を変更した場合でも(理解できるコンテキスト内で、2番目はsになります)、値との関係を格納するテーブルは変更されません。

このソリューションを使用すると、ルックアップテーブルに必要な数の行を追加できますが、列挙型を追加するためだけにalterステートメントを実行する必要があります。これは、大きなテーブルを処理する場合に問題になる可能性があります。

このソリューションの唯一の欠点は、アプリケーションコードが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 に答える