Миграция - готовим быстро

Миграция затрагивающая данные:

class Version20150722151547 extends AbstractMigration
{
    const TABLE_WORK    = 'participant';
    const TABLE_BACKUP = 'participant_20150722151547';

    public function up(Schema $schema)
    {

        // создаем бэкап-таблицу и копируем в неее данные без индексов и FK
        $this->addSql('CREATE TABLE ' . self::TABLE_BACKUP . ' AS SELECT * FROM ' . self::TABLE_WORK);
        // изменяем данные
        $this->addSql('UPDATE ' . self::TABLE_WORK . ' SET doc_type = 1 WHERE participant_type = 1');

    }

    public function down(Schema $schema)
    {
        $this->addSql('SET FOREIGN_KEY_CHECKS = 0');
        $this->addSql('SET UNIQUE_CHECKS = 0');
        $this->addSql('TRUNCATE ' . self::TABLE_WORK);
        $this->addSql('INSERT INTO ' . self::TABLE_WORK . ' SELECT * FROM ' . self::TABLE_BACKUP);
        $this->addSql('DROP TABLE ' . self::TABLE_BACKUP);
        $this->addSql('SET UNIQUE_CHECKS = 1');
        $this->addSql('SET FOREIGN_KEY_CHECKS = 1');
    }
}

Стоит заметить, что команада SET FOREIGN_KEY_CHECKS = 0 работает для текущей сессии (настройка текущей сессии), то есть на другом параллельном подключении будет уже стоять SET FOREIGN_KEY_CHECKS=1 (если в настройках не было указано иного).

Миграция с логикой:

class Version20140728123205 extends AbstractMigration
{
    public function up(Schema $schema)
    {
        $resultCount = $this->connection->executeQuery("
            SELECT
                COUNT(*) as count
            FROM
                booking
        ")->fetchAll();

        if (!array_key_exists('count', $resultCount)) {
            throw new Exception('no bookings found to proceed');
        }

        $this->connection->commit();// закрываем транзакцию, которую начала Doctrine

        $this->connection->beginTransaction();// стартуем транзакцию

        try {
                $this->connection->executeQuery("INSERT IGNORE INTO table SET room_id = :id", ['id' => 123]);
                // $this->addSql('UPDATE table_2 SET hotel_id = :id', ['id' => 45]);
$this->connection->commit();// выполняем транзакцию } catch (\Exception $e) {
$this->connection->rollback();// откатываем транзакцию
throw $e;
}
}

* обратите внимание, мы можем как сразу выполнить запрос, так и добавить запрос, и тогда он будет выполнен в транзакции открытой Doctrine.

Добавление поля (с предварительной проверкой на сущестование этого поля)

$this->addSql("
    SET @s = (SELECT IF(
        (SELECT COUNT(*)
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE table_name = 'my_table'
            AND table_schema = DATABASE()
            AND column_name = 'my_field'
        ) > 0,
        '',
        'ALTER TABLE my_table ADD my_field VARCHAR(20)'
    ));

    PREPARE stmt FROM @s;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
");

На самом деле вариантов решения данной проблемы мног, так что просто гуглите: mysql IF NOT EXISTS field.

Doctrine

Если Вы пользуетесь Doctrine, то при изменении описания схемы данных, удобно создать миграцию автоматом - запустив в следующей последовательности команды:

app/console doctrine:generate:entities NameOfYouBundle - обновит Ваши Entity-классы согласно Yml-схемам

app/console doctrine:migrations:diff - непосредественно создаст файл миграции

Удачки.

Оцени публикацию:
  • 1,5
Оценили человек: 1

Похожие статьи:

Справочники и учебники:


Предложения и пожелания:
Ваше имя:
Ваш E-mail:
Введите изображенные цифры:
Captcha
Главная
X

youtube.com/watch?v=7hFivbgIEqk

При полном или частичном использовании материалов данного сайта, ссылка на сайт "yapro.ru" обязательна как на источник информации.
Автоматический импорт материалов и информации с сайта запрещен.
Copyrights © 2007 - 2017 YaPro.Ru

Главная » Веб-мастеру » MySQL »