1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CakePHP4 で Insert into Select を行う方法

Last updated at Posted at 2020-04-14

大量データを INSERT すると、どうしても処理が遅くなります。
INSERT into SELECT でも対応できる場合、INSERT into SELECT にすることで速度を改善できます。

この記事でわかること

  • CakePHP4 での INSERT into SELECT のやり方

バージョン情報

バージョン
CakePHP4 4.0.5

参考サイト

試し用テーブル

INSERT into SELECT を試すために以下の2つのテーブルを用意します。

tasks テーブルの内容を copy_tasks テーブルへコピー(INSERT into SELECT)するテーブルです。
PrimaryKey は uuid で採番します。
copy_tasks テーブルには、copied したことをマークするフラグを持たせいて、これはコピー時に常に 1 をセットします。

config/Migrations/yyyymmddhhmiss_CreateTasks.php
<?php
declare(strict_types=1);

use Migrations\AbstractMigration;

class CreateTasks extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * http://docs.phinx.org/en/latest/migrations.html#the-change-method
     * @return void
     */
    public function change(): void
    {
        $this->table('tasks', ['id' => false, 'primary_key' => ['id']])
            ->addColumn('id', 'uuid', ['default' => null, 'null' => false])
            ->addColumn('description', 'text', ['default' => null, 'limit' => null, 'null' => false])
            ->addColumn('created', 'datetime', ['default' => 'CURRENT_TIMESTAMP', 'limit' => null, 'null' => false])
            ->addColumn('modified', 'datetime', ['default' => 'CURRENT_TIMESTAMP', 'update' => 'CURRENT_TIMESTAMP', 'limit' => null, 'null' => false])
            ->create();
    }
}
config/Migrations/yyyymmddhhmiss_CreateCopyTasks.php
<?php
declare(strict_types=1);

use Migrations\AbstractMigration;

class CreateCopyTasks extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * http://docs.phinx.org/en/latest/migrations.html#the-change-method
     * @return void
     */
    public function change(): void
    {
        $this->table('copy_tasks', ['id' => false, 'primary_key' => ['id']])
            ->addColumn('id', 'uuid', ['default' => null, 'null' => false])
            ->addColumn('description', 'text', ['default' => null, 'limit' => null, 'null' => false])
            ->addColumn('copied', 'boolean', ['default' => null, 'limit' => null, 'null' => false])
            ->addColumn('created', 'datetime', ['default' => 'CURRENT_TIMESTAMP', 'limit' => null, 'null' => false])
            ->addColumn('modified', 'datetime', ['default' => 'CURRENT_TIMESTAMP', 'update' => 'CURRENT_TIMESTAMP', 'limit' => null, 'null' => false])
            ->create();
    }
}

INSERT into SELECT

INSERT するために SELECT するカラムを select() します。

id は MySQL で uuid を採番します。CakePHPの func() メソッドには ( https://book.cakephp.org/4/en/orm/query-builder.html#using-sql-functions )、 uuid() は定義されていませんが、定義されていない場合、直接DBの関数を呼び出すようになっているので、問題なく動きます。

description は tasksテーブルのレコード内容を使います。

copied は 常に 1 をセットします。

        $Tasks = $this->getTableLocator()->get('Tasks');
        $CopyTasks = $this->getTableLocator()->get('CopyTasks');

        $select = $Tasks->find();
        $select = $select->select([$select->func()->uuid(), 'description', 1])
            ->limit(5);

        $CopyTasks->query()
            ->insert(['id', 'description', 'copied'])
            ->values($select)
            ->execute();

実際に発行される SQL は以下です。

INSERT INTO copy_tasks (id, description, copied) SELECT (uuid()), Tasks.description AS Tasks__description, 1 FROM tasks Tasks LIMIT 5
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?