65

I'm trying to execute a raw SQL thru a Laravel (PHP) migration execution. I was trying with whatever syntax and can't think how can I write this correctly:

Schema::table('users', function(Blueprint $table){
    $sql = <<<SQL
        ALTER TABLE 'users' MODIFY 'age' DATETIME
    SQL;
    DB::connection()->getPdo()->exec($sql);
});

also tried with

DB::statement('ALTER TABLE \'users\' MODIFY COLUMN DATETIME);

and double quotation marks and so on. I always get the following when I run the migration:

Syntax error or access violation: 1064 You have an error in your SQL syntax; check
the manual that corresponds to your MariaDB server version for the right syntax to use near ''users' MODIFY 'age' DATETIME' at line 1

Yes, I have checked, MariaDB uses MySQL's syntax (at least for this case).

Milkncookiez
  • 6,817
  • 10
  • 57
  • 96

4 Answers4

68

The issue (as @postashin said) was the backticks.

As of Laravel 5 (not sure about Laravel 4), you could have done this:

DB::statement('ALTER TABLE `users` MODIFY `age` DATETIME');

In fact you didn't even need the back ticks as they don't need escaping. So you could have just written:

DB::statement('ALTER TABLE users MODIFY age DATETIME');

You do not need this in the closure either if you are just executing a database statement.

However a better approach to what you are doing is as follows:

Schema::table('users', function(Blueprint $table) {
    $table->dateTime('age')->change();
});

Note the last solution can sometimes raise an error due to a bug in Doctrine, which usually occurs if you have an enum in the table (not just the column you are changing).

For more information, see Laravel Database Migration - Modifying Column

ansidev
  • 361
  • 1
  • 3
  • 17
Yahya Uddin
  • 26,997
  • 35
  • 140
  • 231
49

Use back-ticks instead of single quotes to escape identifiers in MySQL:

alter table `users` modify `age` datetime

In this particular case you can omit escaping at all:

alter table users modify age datetime
potashin
  • 44,205
  • 11
  • 83
  • 107
  • 7
    Is there a reason for the query to be inside a Schema closure if not using the Blueprint object? – Lalo Sánchez Jan 13 '17 at 18:36
  • You don't need to Schema closure, it's just separate depending queries. Also you can run query in DB::statement('QUERY'). – KorbenDallas Dec 03 '17 at 14:34
  • @KorbenDallas: In the case of this question it was mostly about why his approach doesn't work in MySQL, not about how to make it better in Laravel (which I am not familiar working with at all) – potashin Dec 03 '17 at 14:47
0

You can use as below

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTestTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
      DB::statement('ALTER TABLE `users` MODIFY `age` DATETIME');         
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users'); \or whatever you want on rollback
    }
}

Also i have create a package to manage raw sql query migration (Queries created using phpMyAdmin or tool but manage the migration across the developer)

Check here : https://readerstacks.com/how-to-run-raw-sql-query-in-migration-laravel/

Aman Jain
  • 384
  • 1
  • 3
  • 15
-1

If your have your schema as public in your connection config and still getting this error, check that the owner in your database for the table migrations is the user which is configured in your connection :)

If not, execute:

ALTER TABLE public."migrations" OWNER TO [username]; 
ALTER SEQUENCE public."migrations_id_seq" OWNER TO [username];   

in that order, that's important.

Suggestion: use just one owner for all your tables and sequences

Kublai Gomez
  • 79
  • 1
  • 1