2014-04-07 140 views
10

如果我做的:更改列数据类型(默认,NOTNULL ...)

ALTER TABLE testtable MODIFY mycolumn NEWDATATYPE; 

我失去喜欢NOT NULL,评论,默认值等定义?有没有如何做到这一点?

In PostgreSQL I used

ALTER TABLE testtable ALTER COLUMN mycolumn NEWDATATYPE; 

以及它的作用应该是:更改列数据类型,不接触任何其他的定义,只给错误,如果数据类型是不兼容等(但您可以指定使用)。

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

+0

我得到了[修改要求(http://dev.mysql.com/doc/refman /5.1/en/alter-table.html)所有_column_definition_,我认为它可能有另一种语法来改变你想要的。 –

回答

4

正如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 [email protected]_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) 
+0

伟大的提示。记住这一点并不容易,但是当您有近100列的更新时就会简化。作为一个加号,如果你可以在你的子句中添加COMMENT和DEFAULT,那将是非常好的,因为所有的东西都应该被修饰,如:IF(COLUMN_DEFAULT不是NULL,CONCAT('DEFAULT',QUOTE(c.COLUMN_DEFAULT),'' ),''),IF(COLUMN_COMMENT IS NOT NULL AND COLUMN_COMMENT!='',CONCAT('COMMENT',QUOTE(c.COLUMN_COMMENT),''),''),'。这将完成答案。 –

+0

是的,它应该添加为常见的情况 - 所以我的观点是显示整个想法 –

0
ALTER TABLE tableName 
MODIFY COLUMN columnName datatype 
+0

这给了我这个问题的问题。 –

0

当您使用CHANGEMODIFYALTER table_namecolumn_definition必须包括数据类型和所有属性应适用于新列,除了指数属性,例如PRIMARY KEYUNIQUE。存在于原定义中但未为新定义指定的属性未结转

假设一列col1被定义为INT UNSIGNED DEFAULT 1COMMENT 'my column'和修改列如下:

ALTER TABLE t1 MODIFY col1 BIGINT; 

结果列将被定义为BIGINT,但不包括属性UNSIGNED DEFAULT 1COMMENT 'my column'。为了留住他们,语句应该是:

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

当您更改使用CHANGEMODIFYMySQL尝试对现有列值转换为新类型以及可能的数据类型。

请参阅documentation

+0

我看到了文档,我期望有一种方法可以只改变你想要的。丑陋的方式来改变一个精确的信息。我知道,我无法做到我所要求的。此外[这个问题](http://stackoverflow.com/questions/5759667/must-i-include-all-column-attributes-in-an-sql-statement-when-i-want-to-alter-on) 2年前有过这种回应。我想这可能是变化。 –