我正在尝试构建一个脚本来生成ALTER TABLE查询,以便在整个架构中,对列进行调整以与MySQL严格模式兼容。
我希望它尽可能简单,对NOT / NOT NULL和Default值进行最基本的更改,以确保严格模式兼容,但同时最大程度地减少破坏任何现有查询或相关查询的机会取决于模式定义的工作原理的PHP代码。
任何提示/我错过的事情/我可能做错的事情..?顺便说一句,我认为我不需要涵盖MySQL中可用的每个列类型,因为我只是不使用其中的一些。但是还有一些额外的“ case:”语句不会出错.. ;;)
<?
include "common.inc.php";
include "header.inc.php";
$r_resultTables = dbQuery("SHOW TABLES");
echo '<textarea style="width: 95%; height: 80vh;">';
while ($a_rowTable = dbFetchRow($r_resultTables)) {
$table = dbEscape($a_rowTable[0]);
$tableNameAdded = false;
$r_result = dbQuery("SHOW FULL FIELDS FROM `$table`");
while ($a_row = dbFetchAssoc($r_result)) {
$comment = null;
$default = (($a_row['Default'] != NULL) ? "DEFAULT '" . $a_row['Default'] . "'" : '');
$extra = null;
$type = strtok($a_row['Type'],'(');
$field = dbEscape($a_row['Field']);
// Is the field allowed to be null?
if ($a_row['Null'] == 'YES') {
$nullable = 'NULL';
} else {
$nullable = 'NOT NULL';
}
// skip nullable fields with no set default (they will default to NULL)
if (($a_row['Default'] === NULL) AND ($a_row['Null'] == 'YES')) {
continue;
}
// skip PK fields
if ($a_row['Key'] == 'PRI') { continue; }
// fields that need a set default if they don't have one
if ($a_row['Default'] === NULL) {
switch ($type) {
case 'int':
case 'smallint':
case 'tinyint':
case 'mediumint':
case 'bigint':
case 'decimal':
case 'numeric':
case 'float':
case 'double':
$comment = "Numeric field should have '0' as default (if missing)";
$default = "DEFAULT '0'";
break;
case 'char':
case 'varchar':
$comment = "(VAR)CHAR fields should have empty string as default (if missing)";
$default = "DEFAULT ''";
break;
}
}
// fields that need changing anyway if they're not already nullable, or can be skipped
switch ($type) {
case 'datetime':
case 'date':
case 'timestamp':
case 'year':
case 'time':
if (substr($a_row['Default'],0,2) == '00') {
$comment = "Date/Time types cannot default to zeroes, should be NULLable (if missing)";
$extra = "UPDATE `$table` SET `$field` = NULL WHERE `$field` = '" . $a_row['Default'] . "';";
$default = "DEFAULT NULL";
} elseif ($a_row['Default'] == 'CURRENT_TIMESTAMP') {
continue 2;
} else {
$comment = "Date/Time types should be NULLable if missing";
}
$nullable = 'NULL';
break;
case 'enum':
case 'set':
continue 2; // ENUM and SET types don't need any change
break;
case 'tinytext':
case 'text':
case 'mediumtext':
case 'longtext':
continue 2; // TEXT types cannot have a default value
break;
default:
if ($a_row['Default'] !== NULL) { continue 2; } // skip any other types that already have defaults
break;
}
if (!$tableNameAdded) {
echo "\r\n# `$table`\r\n\r\n";
$tableNameAdded = true;
}
// Alter table query
if ($comment) { echo '# `' . $field . '` - ' . $comment . "\r\n"; } else { echo "# UNKNOWN\r\n" . '# '; }
echo "ALTER TABLE `$table` CHANGE `$field` `$field` $a_row[Type] $nullable $default;\r\n";
if ($extra) { echo $extra . "\r\n"; }
echo "\r\n";
}
}
echo '</textarea>';
include "footer.inc.php";
从此处使用默认值信息:https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html
严格模式信息从这里: https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html