问题
I'm trying to build a script to generate ALTER TABLE queries so that across whole schemas, columns are adjusted to be compatible with MySQL strict-mode..
I want it to be a simple as possible, making the most basic changes possible for NOT/NOT NULL and Default values to ensure strict-mode compatibility, but at the same time minimising the chances of breaking any existing queries, or associated PHP code that depends on the schema definition's workings.
Any tips / things I've missed out / things I maybe doing wrong..? BTW, I don't think I need to cover absolutely every column type available in MySQL, as I simply don't use some of them. But a few extra 'case:' statements wouldn't go amiss .. ;)
<?
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";
Using the default values info from here: https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html
And strict mode info from here: https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html
来源:https://stackoverflow.com/questions/55673938/php-script-to-fix-mysql-columns-to-work-with-strict-mode