Laravel使用Seeder填充数据时遇nvarchar转datetime类型错误
使用Laravel Seeder向SQL Server数据库填充数据时,反复遇到类型转换错误,报错信息为SQLSTATE[22007]:varchar数据类型转换为datetime数据类型时导致值超出范围。尝试将timestamps()替换为datetime()->nullable()后问题仍未解决,数据库管理工具使用SQL Server Management Studio。
相关迁移代码
public function up(): void { Schema::create('books', function (Blueprint $table) { $table->id(); $table->string('book_name'); $table->string('author'); $table->integer('page_count'); $table->foreignId('category_id')->constrained()->onDelete('cascade'); $table->string('isbn'); $table->string('publisher'); $table->string('publish_year'); $table->string('status'); $table->timestamps(); }); }
错误详情
SQLSTATE[22007]: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]The conversion of a varchar data type to a datetime data type resulted in an out-of-range value. (Connection: sqlsrv, SQL: insert into [books] ([book_name], [author], [page_count], [category_id], [isbn], [publisher], [publish_year], [status], [updated_at], [created_at]) values (1984, George Orwell, 328, 4, 9780451524935, Penguin Books, 1949, available, 2025-03-17 14:01:33.722, 2025-03-17 14:01:33.722))
1. 修正SQL Server连接配置
SQL Server默认日期格式可能与Laravel生成的YYYY-MM-DD HH:MM:SS.fff格式不兼容,修改config/database.php中的sqlsrv连接配置,明确日期处理规则:
'sqlsrv' => [ 'driver' => 'sqlsrv', 'host' => env('DB_HOST', 'localhost'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'prefix' => '', 'prefix_indexes' => true, 'options' => [ PDO::SQLSRV_ATTR_FORMAT_DECIMALS => true, PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE => true, 'ReturnDatesAsStrings' => false, ], ],
2. 调整publish_year字段类型
当前publish_year为string类型,纯年份值(如1949)可能被SQL Server误识别为日期进行转换,建议改为integer类型:
// 替换原代码中的$table->string('publish_year'); $table->integer('publish_year');
同时更新Seeder中对应字段的值,确保传入整数类型而非字符串。
3. 统一Laravel时间戳格式
在AppServiceProvider的boot方法中,设置Carbon的序列化格式,确保与SQL Server兼容:
use Illuminate\Support\Carbon; public function boot() { Carbon::serializeUsing(function ($carbon) { return $carbon->format('Y-m-d H:i:s.u'); }); }
4. 校验Seeder中的日期范围
确认Seeder生成的created_at/updated_at值在SQL Serverdatetime类型的合法范围内(1753-01-01 至 9999-12-31),使用now()或Carbon生成时间时,确保时区配置正确。
内容的提问来源于stack exchange,提问作者Ahmet Faruk Yaşar

