更改MySQL中的列数据类型而不会丢失其他元数据(DEFAULT,NOTNULL ...)

时间:2014-04-07 13:50:27

标签: mysql sql

如果我这样做:

ALTER TABLE testtable MODIFY mycolumn NEWDATATYPE;

我放弃了其他定义,如NOT NULL,COMMENTS,DEFAULT值......有没有办法做到这一点?

In PostgreSQL I used

ALTER TABLE testtable ALTER COLUMN mycolumn NEWDATATYPE;

它可以完成以下任务:更改列数据类型,不触及任何其他定义,仅在数据类型不兼容时给出错误等等(但您可以指定USING)。

我会尝试一种解决方法,但我做了一个查询,以确定不同表中的几个列来更新数据类型,现在我已经确定这些数据已丢失,因此我将不得不重新考虑这些信息

3 个答案:

答案 0 :(得分:5)

正如manual page中所述,ALTER TABLE要求定义所有新类型属性。

然而,有一种方法可以解决这个问题。您可以使用INFORMATION_SCHEMA meta-data重新构建所需的ALTER查询。例如,如果我们有简单的表:

mysql> DESCRIBE t;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| value | varchar(255)     | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)

然后我们可以用:

重现我们的alter语句
SELECT 
  CONCAT(
    COLUMN_NAME, 
    ' @new_type', 
    IF(IS_NULLABLE='NO', ' NOT NULL ', ' '), 
    EXTRA
  ) AS s
FROM 
  INFORMATION_SCHEMA.COLUMNS 
WHERE 
  TABLE_SCHEMA='test' 
  AND 
  TABLE_NAME='t'

结果将是:

+--------------------------------------+
| s                                    |
+--------------------------------------+
| id @new_type NOT NULL auto_increment |
| value @new_type NOT NULL             |
+--------------------------------------+

我已经离开@new_type表示我们可以使用变量(或者甚至直接替换我们的新类型进行查询)。使用变量:

  • 设置我们的变量。

    mysql> SET @new_type := 'VARCHAR(10)', @column_name := 'value';
    Query OK, 0 rows affected (0.00 sec)
    
  • prepared statement准备变量(这是一个很长的查询,但我上面留下了解释):

    SET @sql = (SELECT CONCAT('ALTER TABLE t CHANGE `',COLUMN_NAME, '` `', COLUMN_NAME, '` ', @new_type, IF(IS_NULLABLE='NO', ' NOT NULL ', ' '), EXTRA) AS s FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t' AND COLUMN_NAME=@column_name);
    
  • 准备声明:

    mysql> prepare stmt from @sql;
    Query OK, 0 rows affected (0.00 sec)
    Statement prepared
    
  • 最后,执行它:

    mysql> execute stmt;
    Query OK, 0 rows affected (0.22 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    

然后我们将我们的数据类型更改为VARCHAR(10)并保存所有其余的说明符:

mysql> DESCRIBE t;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| value | varchar(10)      | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

答案 1 :(得分:0)

ALTER TABLE tableName
MODIFY COLUMN columnName datatype

答案 2 :(得分:0)

CHANGE中使用MODIFYALTER table_name时,column_definition必须包含数据类型和应适用于新列的所有属性,而不是PRIMARY KEYUNIQUE等索引属性。原始定义中出现的属性但未为新定义指定的属性不会结转

假设列col1定义为INT UNSIGNED DEFAULT 1 COMMENT 'my column',您可以按如下方式修改列:

ALTER TABLE t1 MODIFY col1 BIGINT;

结果列将定义为BIGINT,但不会包含属性UNSIGNED DEFAULT 1 COMMENT 'my column'。为了保留它们,声明应该是:

ALTER TABLE t1 MODIFY col1 BIGINT UNSIGNED DEFAULT 1 COMMENT 'my column';

使用CHANGEMODIFY更改数据类型时,MySQL会尝试尽可能将现有列值转换为新类型。

请参阅documentation