Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Altere o tipo de dados da coluna no MySQL sem perder outros metadados (DEFAULT, NOTNULL...)


Conforme declarado na página de manual , ALTER TABLE requer que todos os novos atributos de tipo sejam definidos.

No entanto, existe uma maneira de superar isso. Você pode usar INFORMATION_SCHEMA metadados para reconstruir o ALTER desejado consulta. por exemplo, se tivermos uma tabela simples:
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)

então podemos reproduzir nossa declaração alter com:
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'

o resultado seria:
+--------------------------------------+
| s                                    |
+--------------------------------------+
| id @new_type NOT NULL auto_increment |
| value @new_type NOT NULL             |
+--------------------------------------+

Aqui deixei @new_type para indicar que podemos usar variável para isso (ou até mesmo substituir nosso novo tipo diretamente na consulta). Com variável que seria:

  • Defina nossas variáveis.
    mysql> SET @new_type := 'VARCHAR(10)', @column_name := 'value';
    Query OK, 0 rows affected (0.00 sec)
    

  • Preparar variável para instrução preparada (é uma consulta longa, mas deixei explicações acima):
    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);
    

  • Preparar declaração:
    mysql> prepare stmt from @sql;
    Query OK, 0 rows affected (0.00 sec)
    Statement prepared
    

  • Por fim, execute-o:
    mysql> execute stmt;
    Query OK, 0 rows affected (0.22 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    

Então vamos alterar nosso tipo de dados para VARCHAR(10) salvando todos os especificadores restantes:
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)