简体   繁体   English

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

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

I'm trying to do the following process in a Laravel migration: 我正在尝试在Laravel迁移中执行以下过程:

Create a new table called client_log_partitions . 创建一个名为client_log_partitions的新表。 (DONE) (DONE)

$table->create();

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

$table->timestamps();

  • I already have a table called client_logs with data stored in a bigText() column called log_data . 我已经有一个名为client_logs的表,其数据存储在名为log_databigText()列中。
  • Each row that already exists in the client_logs table needs to be split every 250 KB (or 250,000 characters since it should be single byte encoded) and then inserted into the new client_log_partitions table as partitions, with a reference to the client_logs entry it belongs to. client_logs表中已存在的每一行需要每250 KB(或250,000个字符,因为它应该是单字节编码)进行拆分,然后作为分区插入到新的client_log_partitions表中,并引用它所属的client_logs条目。

I know I may be able to achieve this using $table->postExecute() , I just don't know what I might use to do so. 我知道我可以使用$table->postExecute()实现这一点,我只是不知道我可能会这样做。

Once the data is moved to the new table, I then need to drop the log_data column from client_logs . 将数据移动到新表后,我需要从client_logs删除log_data列。

Normally, I would do this with a PHP script or something similar. 通常,我会用PHP脚本或类似的东西来做这件事。 But unfortunately I'm operating under circumstances where I'm unable to. 但不幸的是,我在我无法做到的情况下运作。


My question is, Is this doable using Laravel Migrations, and if so, how? 我的问题是,这是否可以使用Laravel Migrations,如果是这样,怎么样?

EDIT : 编辑

Although I'm unsure since i only whipped this up on the fly and haven't tested it, this is what I imagine the SQL for achieving this would look something like: 虽然我不确定,因为我只是动态地掀起了它并且没有测试过,这就是我想象的实现这个的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);

All you should need to do is run your code to move the information and re-associate the ids before the drop column call. 您需要做的就是运行代码来移动信息并在drop column调用之前重新关联id。 This is because everything in the up function is ran sequentially, from top to bottom, and not asynchronously. 这是因为up函数中的所有内容都是从上到下顺序运行,而不是异步运行。 https://laravel.com/docs/5.8/migrations https://laravel.com/docs/5.8/migrations

You could use Eloquent and PHP to move the information and alter it. 您可以使用Eloquent和PHP来移动信息并对其进行更改。 Doing so would probably be easier than writing a query. 这样做可能比编写查询更容易。 This is how companies that I've worked at moved data and then altered tables. 这就是我工作过的公司移动数据然后改变表格的方式。 Sometimes, because of SoX compliance stupidity, we had to move data using SQL scripts but you shouldn't have to worry about that it sounds like. 有时,由于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
    }
}

Change your new table migration up method to : 改变你的新表迁移方法:

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');
    });
}

I think in this way also migrate:rollback command should be work ( for undo your changes ) ! 我想通过这种方式也可以迁移:rollback命令应该工作(撤消你的更改)!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM