2

2 つに分割する必要がある mysql テーブルがあります。現在、テーブルには、緩やかに関連する 2 つのエンティティに関する情報が含まれています。たとえば、エンティティは、会社の従業員と、彼がタグ付けされている会社のラップトップである可能性があります。次の表は、私の例を説明しています。employee次の列を持つテーブルがあります

employee_id,employee_name,employee_detail,join_date,laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make.

以下に示すように、このテーブルを 2 つに分割する必要があります。 employeeラップトップの列のないテーブル

employee_id,employee_name,employee_detail,join_date.

laptopキーとして employee_id を持つ新しいテーブル。

employee_id,laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make

以下のステートメントは、現在のデータベース設計に当てはまります

  • このemployeeテーブルは、バックエンド コードによって頻繁に使用されます。バックエンドのコードは Java と php で書かれています。
  • employeeテーブルの名前を変更することはできません.2 つの新しいテーブルを作成したくないことを意味します.employeeテーブルを保持したいが、そこからすべてのラップトップ情報を削除します.
  • 毎日、新しい行が追加され、既存の行が更新されます。

私の質問は

  1. 単一のテーブルの現在の設計から新しく提案された設計にスムーズに移行するために従うことができる設計アプローチはありますか?
  2. スムーズな移行を確実にするために従うべきベストプラクティスはありますか?
  3. このタスクを完了するための手順を提案/リダイレクトしていただけませんか。
4

3 に答える 3

2
  1. 既存のデータベースをバックアップします。

    mysqldump my_db > backup.sql
    
  2. 新しいのテーブルを作成しますlaptop(以下の例ではインデックスや外部キー制約を定義していませんが、データ構造に適した方法を実行する必要があります)。

    CREATE TABLE laptop
    SELECT employee_id,
           laptop_id,
           laptop_type,
           laptop_tagged_date,
           laptop_details,
           laptop_make
    FROM   employee
    WHERE  FALSE;
    
  3. 元のテーブルにトリガーを定義して、各タイプの書き込み操作(挿入/更新/削除)を新しいテーブルに転送します。

    CREATE TRIGGER employee_insert AFTER INSERT ON employee FOR EACH ROW
      INSERT INTO laptop VALUES (
        NEW.employee_id,
        NEW.laptop_id,
        NEW.laptop_type,
        NEW.laptop_tagged_date,
        NEW.laptop_details,
        NEW.laptop_make
      );
    
    CREATE TRIGGER employee_update AFTER UPDATE ON employee FOR EACH ROW
      UPDATE laptop SET
        employee_id         =  NEW.employee_id,
        laptop_id           =  NEW.laptop_id,
        laptop_type         =  NEW.laptop_type,
        laptop_tagged_date  =  NEW.laptop_tagged_date,
        laptop_details      =  NEW.laptop_details,
        laptop_make         =  NEW.laptop_make
      WHERE
        employee_id        <=> OLD.employee_id,
        laptop_id          <=> OLD.laptop_id,
        laptop_type        <=> OLD.laptop_type,
        laptop_tagged_date <=> OLD.laptop_tagged_date,
        laptop_details     <=> OLD.laptop_details,
        laptop_make        <=> OLD.laptop_make;
    
    CREATE TRIGGER employee_delete AFTER DELETE ON employee FOR EACH ROW
      DELETE FROM laptop WHERE
        employee_id        <=> OLD.employee_id,
        laptop_id          <=> OLD.laptop_id,
        laptop_type        <=> OLD.laptop_type,
        laptop_tagged_date <=> OLD.laptop_tagged_date,
        laptop_details     <=> OLD.laptop_details,
        laptop_make        <=> OLD.laptop_make;
    
  4. (トリガーが挿入されてから)新しいテーブルを空にしてから、同じトランザクション内でINSERT ... SELECT、元のテーブルからすべての既存のデータをそのテーブルにコピーするために使用します。

    START TRANSACTION;
    
    DELETE FROM laptop;
    INSERT INTO laptop
    SELECT employee_id,
           laptop_id,
           laptop_type,
           laptop_tagged_date,
           laptop_details,
           laptop_make
    FROM   employee;
    
    COMMIT;
    
  5. 元のテーブルのラップトップ列にアクセスするすべての操作について、コードベース(データベースに格納されたプログラムを含む)を徹底的に検索します。各操作が次のことを行うかどうかに注意してください。

    • それらの列からのみ読み取ります。

    • それらの列にのみ書き込みます。また

    • それらの列からの読み取りとそれらの列への書き込みの両方(例UPDATE employee SET laptop_tagged_date = laptop_tagged_date + INTERVAL 1 WEEK WHERE ...)。

  6. 新しいテーブルを使用するように読み取り操作を変更し、読み取りと書き込みの両方の操作を別々のステップに分割します(例UPDATE employee JOIN laptop ON ... SET employee.laptop_tagged_date = laptop.laptop_tagged_date + INTERVAL 1 WEEK WHERE ...)。

    元のテーブルと新しいテーブルはトリガーによって同期が維持されるため、この変更をアトミックに行う必要はありません。したがって、アプリケーションの一部は新しいテーブルから読み取ることができ、他の部分は元のテーブルを引き続き使用できます。

    このステップが完了したことを確認するまで、次のステップに進まないでください。次のステップでは、テーブルの同期が解除されます。このステップが完了したことを確認するまで、MySQLユーザー権限を使用して、(トリガーを除いて)新しいテーブルへの書き込みを防ぐこともできます。

  7. 新しいテーブルを使用するように書き込み操作を変更します。

    元のテーブルへの書き込みはトリガーによって新しいテーブルに転送されるため、この変更をアトミックに行う必要はありません。したがって、アプリケーションの一部は新しいテーブルに書き込むことができ、他の部分は元のテーブルに書き込みを続行できます。

  8. 元のテーブルから列を削除します。

    ALTER TABLE employee
      DROP COLUMN laptop_id,
      DROP COLUMN laptop_type,
      DROP COLUMN laptop_tagged_date,
      DROP COLUMN laptop_details,
      DROP COLUMN laptop_make;
    
于 2012-09-13T14:17:54.850 に答える
1

テーブルを作成するときに、次のクエリタイプを使用する方法を提案できますlaptop:-

create table laptop select employee_id,laptop_id,laptop_type,
laptop_tagged_date,laptop_details,laptop_make from
employee;

laptop上記のプロセスでテーブルを作成した後、テーブルから指定された列を削除しemployeeて、関連するフィールドを持つ新しい従業員テーブルを取得できます。

テーブルから列を削除しemployeeます。

alter table employee
drop column laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make;

新しいemployeeテーブルには次のフィールドがあります。

employee_id,employee_name,employee_detail,join_date

現在、laptopテーブルには次のフィールドがあります。

mployee_id,laptop_id,laptop_type,
    laptop_tagged_date,laptop_details,laptop_make

それがあなたを助けることを願っています。

于 2012-09-13T13:34:20.620 に答える
1

物理的に異なる 2 つのテーブルが必要な場合は、Sebastien M. の回答を次のように適応させることができます。

それらを外部化するための対応するデータを含むラップトップテーブルを作成します

CREATE TABLE laptop AS
SELECT DISTINCT employee_id,laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make
FROM employee
WHERE ...

employee_laptop ビューを提供して、employee の動作を模倣し、後方互換性を確保します

create view employee_laptop as 
select employee_id, e.employee_name,e.employee_detail,e.join_date,
       l.laptop_id,l.laptop_type,l.laptop_tagged_date,l.laptop_details,l.laptop_make
from employee e join laptop l using(employee_id);

次に、従業員テーブルから不要な列を削除する自由があります

于 2012-09-13T12:38:37.283 に答える