Laravel 将数据从一个 table 移动到另一个 table 并删除数据来自的列?

Laravel move data from one table to another and drop the column that the data came from?

我正在尝试在 Laravel 迁移中执行以下过程:

创建一个名为 client_log_partitions 的新 table。 (完成)

$table->create();

$table->bigIncrements('id')->unique();
$table->bigInteger('client_log_id');
$table->mediumText('partition_data');

$table->timestamps();

我知道我可以使用 $table->postExecute() 来实现这一点,我只是不知道我可以使用什么来做到这一点。

一旦数据移动到新的 table,我就需要从 client_logs.

中删除 log_data

通常,我会使用 PHP 脚本或类似的东西来执行此操作。但不幸的是,我在无法做到的情况下工作。


我的问题是,使用 Laravel 迁移是否可行,如果可行,如何实现?

编辑:

虽然我不确定,因为我只是匆匆忙忙地做了这个,还没有测试过,这就是我想象的 SQL 实现这个的样子:

DROP PROCEDURE IF EXISTS PROCESS_LOG_DATA;
DROP PROCEDURE IF EXISTS PROCESS_LOG_ENTRIES;
DELIMITER ;;

## Procedure for processing a specific log entry
## and moving its data to the new table.
CREATE PROCEDURE PROCESS_LOG_DATA(log_id bigint, partition_size int)
BEGIN
    DECLARE n INT DEFAULT 0;
    DECLARE i INT DEFAULT 0;
    SELECT LENGTH(log_data)/partition_size FROM client_logs where id=log_id INTO n;
    SET i=0;
    WHILE i<n DO

      # Move the characters to the new table.
      INSERT INTO client_log_partitions 
          (client_log_id, partition_data)
      SELECT (id, LEFT(log_data, partition_size))
      FROM client_logs 
      WHERE id=log_id

      # Shift the characters off of the log_data
      UPDATE client_logs
      SET log_data = SUBSTR(
          log_data,
          partition_size,
          LENGTH(log_data) - partition_size
      ) where id=log_id;

      # Update the number of data partitions we've processed for this log entry
      SET i = i + 1;
    END WHILE;
End;
;;


## Procedure for processing all log entries
## and passing each one to the PROCESS_LOG_DATA procedure.
CREATE PROCEDURE PROCESS_LOG_ENTRIES(partition_size int)
BEGIN
    DECLARE n INT DEFAULT 0;
    DECLARE i INT DEFAULT 0;
    SELECT COUNT(*) FROM client_logs INTO n;
    SET i=0;
    WHILE i<n DO
        PROCESS_LOG_DATA(i, partition_size)
    END WHILE;
End;
;;

DELIMIETER ;

## Process the log entries.
CALL PROCESS_LOG_ENTRIES(250000);

您需要做的就是运行您的代码来移动信息和re-associate删除列调用之前的ID。这是因为 up 函数中的所有内容都是 运行 顺序的,从上到下,而不是异步的。 https://laravel.com/docs/5.8/migrations

您可以使用 Eloquent 和 PHP 来移动和更改信息。这样做可能比编写查询更容易。这就是我工作过的公司如何移动数据然后更改表格的方式。有时,由于愚蠢的 SoX 合规性,我们不得不使用 SQL 脚本移动数据,但您不必担心这听起来像。

class DropClientLogsLogDataColumn extends Migration
{

    public function up()
    {
        // move data
        $this->moveData()

        Schema::table('client_logs', function (Blueprint $table) {
          // drop the log_data column
          $table->dropColumn('log_data');
        });
    }

    private function moveData()
    {
      // do whatever you need to do here 
      // more than likely you'll use eloquent or query builder
      // this is where you'd associate the id's
    }
}

将新的 table 迁移 up 方法更改为:

public function up()
{
    //Create the table
    Schema::create('your_table_name', function (Blueprint $table) {
        $table->bigIncrements('id')->unique();
        $table->bigInteger('client_log_id');
        $table->mediumText('partition_data');

        $table->timestamps();
    });

    //Copy column from last table to new table
    foreach(MyOldModel::all() as $item)
    {
        //now you can save old data into new table old data : $item -> log_data
        //other operation you want
        MyNewModel::create(array('partition_data' => $item -> log_data));//you can save other columns with adding array values
    }

    //Drop old table column
    Schema::table('client_logs', function (Blueprint $table) {
        $table->dropColumn('log_data');
    });
}

我认为这样 migrate:rollback 命令也应该有效(用于撤消您的更改)!