sql >> Database teknologi >  >> RDS >> Mysql

Skift kolonnedatatype i MySQL uden at miste andre metadata (DEFAULT, NOTNULL...)

Som det står på manualside , ALTER TABLE kræver, at alle nye typeattributter defineres.

Der er dog en måde at overvinde dette på. Du kan bruge INFORMATION_SCHEMA meta-data for at rekonstruere ønsket ALTER forespørgsel. for eksempel, hvis vi har en simpel tabel:

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)

så kan vi gengive vores alter-udsagn med:

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'

resultatet ville være:

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

Her har jeg efterladt @new_type for at indikere, at vi kan bruge variabel til det (eller endda erstatte vores nye type direkte for at forespørge). Med variabel ville det være:

  • Indstil vores variabler.

    mysql> SET @new_type := 'VARCHAR(10)', @column_name := 'value';
    Query OK, 0 rows affected (0.00 sec)
    
  • Forbered variabel til forberedt erklæring (det er en lang forespørgsel, men jeg har efterladt forklaringer ovenfor):

    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);
    
  • Forbered erklæring:

    mysql> prepare stmt from @sql;
    Query OK, 0 rows affected (0.00 sec)
    Statement prepared
    
  • Til sidst skal du udføre det:

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

Så får vi vores datatype ændret til VARCHAR(10) med at gemme alle de øvrige specifikationer:

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. Hvad er den bedste praksis for at indsætte en post, hvis den ikke allerede eksisterer?

  2. 32-bit Excel og 64-bit SQL Server

  3. MySQL 5.5 partitionstabel fra A-Z

  4. Hvordan kontrolleres (eller endda indstilles) sortering i mdb (ms access) fil?