DATE)。 * 用法:php tools/migrate_time_to_date.php [库名] * 说明: * - 自动遍历指定库(默认取 config/database.php 的 dbname)中所有 DATETIME/TIMESTAMP 字段, * 生成并执行 ALTER TABLE ... MODIFY ... DATE。 * - 对带默认值 CURRENT_TIMESTAMP 的字段,改为 DEFAULT (CURRENT_DATE)(需 MySQL 8.0.13+); * 若执行环境为 MySQL 5.7,请手动调整或保留 DATETIME。 * - 已存在 DATE 类型的字段不会重复处理;脚本幂等,可重复执行。 */ require __DIR__ . '/../config/database.php'; $dbname = $argv[1] ?? $cfg['dbname']; $dsn = sprintf('mysql:host=%s;port=%d;dbname=%s;charset=%s', $cfg['host'], $cfg['port'], $dbname, $cfg['charset']); try { $pdo = new PDO($dsn, $cfg['username'], $cfg['password'], [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]); } catch (Exception $e) { fwrite(STDERR, "[错误] 数据库连接失败:" . $e->getMessage() . "\n"); exit(1); } // 查出所有 DATETIME / TIMESTAMP 列 $stmt = $pdo->prepare( "SELECT TABLE_NAME, COLUMN_NAME, IS_NULLABLE, COLUMN_DEFAULT, EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND DATA_TYPE IN ('datetime', 'timestamp') ORDER BY TABLE_NAME, ORDINAL_POSITION" ); $stmt->execute([$dbname]); $cols = $stmt->fetchAll(); if (!$cols) { echo "未发现需要转换的 DATETIME/TIMESTAMP 字段。\n"; exit(0); } $converted = 0; foreach ($cols as $col) { $table = $col['TABLE_NAME']; $name = $col['COLUMN_NAME']; $nullable = $col['IS_NULLABLE'] === 'YES' ? 'NULL' : 'NOT NULL'; // 原默认值为 CURRENT_TIMESTAMP / on update CURRENT_TIMESTAMP 的,改为 (CURRENT_DATE) $def = 'NULL'; if (stripos((string)$col['COLUMN_DEFAULT'], 'CURRENT_TIMESTAMP') !== false) { $def = '(CURRENT_DATE)'; } $extra = ''; if (stripos((string)$col['EXTRA'], 'on update') !== false) { $extra = ' ON UPDATE (CURRENT_DATE)'; } $sql = "ALTER TABLE `$table` MODIFY COLUMN `$name` DATE $nullable DEFAULT $def$extra"; try { $pdo->exec($sql); echo "转换:$table.$name DATETIME -> DATE\n"; $converted++; } catch (Exception $e) { fwrite(STDERR, "[跳过] $table.$name:" . $e->getMessage() . "\n"); } } echo "完成:共转换 $converted / " . count($cols) . " 个时间字段。\n";