Skip to content

Instantly share code, notes, and snippets.

@spacemudd
Last active December 23, 2017 02:16
Show Gist options
  • Save spacemudd/abfa7ef66d096f3f20796bf373df365b to your computer and use it in GitHub Desktop.
Save spacemudd/abfa7ef66d096f3f20796bf373df365b to your computer and use it in GitHub Desktop.
Laravel and SQL Server 2012 DATETIME issue: PDOException: SQLSTATE[22007]
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateManufacturersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('manufacturers', function (Blueprint $table) {
$table->increments('id');
// Here, we specify the microseconds' precision digits to be 4 to make a DATETIME2.
// If we don't, Laravel will create a DATETIME column type.
// And our unit test will fail.
$table->datetime('created_at', 4);
$table->datetime('updated_at', 4);
// We can also use the precision param on timestamps() and timestmap().
// $table->timestamps(4);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('manufacturers');
}
}
<?php
namespace Tests\Unit;
use App\Models\Manufacturer;
use Carbon\Carbon;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class DateTimeMicrosecondsTest extends TestCase
{
public function testDateTimeMicrosecondsTest()
{
/**
* Saving this record in SQL Server 2012 will result in the following error.
*
* PDOException: SQLSTATE[22007]: [Microsoft][ODBC Driver 13 for SQL Server]
* [SQL Server]Conversion failed when converting date and/or time from
* character string.
*
* Because Laravel defaults to creating a DATETIME column when using migration
* method datetime(); on SQL Servers. SQL Servers limits to the nanoseconds
* parts to 3 DIGITS ONLY.
*
* In order to save and retrieve DATETIME values with 4+ digits on the
* microseconds part, specify the precision on the migration method
* $table->datetime(4); and this precision works too for:
*
* $table->timestamp(4), $table->timestamps(4) and $table->datetimeTz(4)
*
*/
$newManufacturer = new Manufacturer();
$newManufacturer->code = '123';
// This test also fails (using DATETIME columns) if you comment
// these two lines out and allow Eloquent to set
// created_at and updated_at datetimes.
$newManufacturer->created_at = '2017-12-22 13:46:36.1335';
$newManufacturer->updated_at = '2017-12-22 13:46:36.1335';
$newManufacturer->save();
// SQL Server's engine rounds the microseconds up.
$this->assertDatabaseHas('manufacturers', ['created_at' => '2017-12-22 13:46:36.1340']);
}
public function tearDown()
{
Manufacturer::where('code', '123')->delete();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment