使用Laravel将数据从一个表移动到另一个表并删除数据来源列?

4
我将尝试在 Laravel 迁移中执行以下过程:
创建名为 client_log_partitions 的新表。(已完成)
$table->create();

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

$table->timestamps();
  • 我已经有一个名为client_logs的表格,其中数据存储在名为log_databigText()列中。
  • client_logs表中每行需要被分成每250 KB(或250,000个字符,因为它应为单字节编码),然后作为分区插入到新的client_log_partitions表中,并与其所属的client_logs条目建立关系。

我知道可以使用$table->postExecute()来完成此操作,但不知道可以使用什么工具来实现。

一旦数据移动到新表中,我需要从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);

2个回答

4
将你的新表迁移的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命令(用于撤消更改)!

我需要在将数据插入新表之前将来自client_logs表的数据每250个字符拆分一次。然而,由于旧表中存储的数据太大而无法一次性加载到PHP中(因此首先需要进行分区),所以我无法使用该模型执行此操作。 - Nathan F.
为了使 migrate:rollback 起作用,您首先需要添加一个 down() 方法并在那里反转该过程... 无论如何,对于大量数据而言,在 PHP 中获取 MyOldModel::all() 本身,然后循环遍历并单个创建调用是非常耗费资源的 - 您可能会耗尽内存 :) 我建议您不要使用类似 ::all() 的获取器来处理大小未定义/未知的数据。 - jave.web
有关Laravel中数据迁移的相关答案:https://dev59.com/gWAg5IYBdhLWcg3whrMV#23506744 - Ryan

2
你需要做的就是在删除列之前运行你的代码来移动信息并重新关联 IDs。这是因为 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
    }
}

1
现在我正在尝试使用SQL、查询构建器或Eloquent,每次将数据移动250个字符到新表中。 - Nathan F.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接