在我的一次迁移中,我向所有表添加了一个“dateCreated”列。这适用于大多数表,但在其中一些表上引发了一个奇怪的错误:
'SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect date value: '0000-00-00' for column 'start_date' at row 1
The SQL being executed was: ALTER TABLE
付款ADD
{dateCreated会{1}}
列'start_date'已经存在,但我无法理解为什么这与新创建的列有关。 这打破了我的迁移。直接在PhpMyAdmin中的表上应用时,相同的SQL工作正常。 Yii是否为查询添加了额外的检查,或者我错过了其他内容?
这是完整的迁移:
DATETIME NULL DEFAULT NULL'
答案 0 :(得分:1)
迁移过程中存在一些错误。
1)迁移应该与数据库结构和与添加时间相关的数据进行交互,而非当前时间。
当你这样写:
Yii::$app->db->schema->tableNames;
您指的是迁移时的所有现有表。
因此,想象一下,如果稍后添加一些新表,并且某些表不需要该列。如果您的新队友将运行迁移或将在新服务器上运行,则dateCreated
将添加到所有表中。如果是其他操作,例如删除,则可能导致严重问题,例如意外数据丢失。
请记住 - 始终使用与创建迁移时刻相关的数据库结构和数据。
我建议创建私有静态数组,并在up()
和down()
方法中使用它。
private static $_tableNames = [
'tableName1',
'tableName2',
];
2)当有很多查询时,将它更安全地包装在事务中。请改用safeUp()
和safeDown()
方法。在这种情况下,如果某些查询的迁移失败,则将应用回滚,您不必对数据库进行任何其他手动操作。
3)在迁移过程中无需为此类常见任务编写原始SQL。使用yii\db\Migration
方法。
4) yii\db\Command
query()
用于选择,删除使用execute()
。但不需要使用它,因为在执行原始SQL的迁移中存在快捷方式:$this->execute('YOUR SQL GOES HERE')
。
5)我建议在列名中使用非核心(_
)作为分隔符,但这并不重要。
所以最后你的迁移看起来像这样:
use yii\db\Expression;
use yii\db\Migration;
class m111111_111111_add_date_created_column_to_all_existing_tables extends Migration
{
/**
* @var array List of table names
*/
private static $_tableNames = [
'tableName1',
'tableName2',
],
public function safeUp()
{
foreach (self::$_tableNames as $table) {
$this->addColumn($table, 'date_created', $this->dateTime()->defaultValue(new yii\db\Expression('NULL')));
}
}
public function safeDown()
{
foreach (self::$_tableNames as $table) {
$this->dropColumn($table, 'date_created');
}
}
}
这更像是代码审核,但回到主要问题:在提供的代码中根本没有添加dateCreated
列(实际上根本没有更改)以及与{{{{}相关的错误1}}来自不同的部分。
此类查询的逻辑:
start_date
是正确的,因此ALTER TABLE payments ADD dateCreated DATETIME NULL DEFAULT NULL
列将添加到所有列出的表名中。
现有行将填充dateCreated
个数据(NULL
列),因此不会出现像dateCreated
这样的值(也就是日期时间,而不是日期)。 0000-00-00
是一个不同的列,在其他代码处检查与之相关的逻辑。