我可以在不知道现有列名称的情况下重命名 MySQL 列吗?

Can I rename a MySQL Column without knowing the existing column name?

我正在编写一系列 MySQL 查询来处理 table 中的数据。我有一个 table 是由我无法控制的系统自动生成的。当我得到它时,table 有几列:

ID、姓名、日期、标题和包含十进制值的列。

每次外部系统自动生成table时,它都会用当前日期命名包含小数值的值。目前,该列名为“16_Jul_17”,因为那是系统 运行 的最后一天。

我需要一种可靠的方法来查询 table(并重命名列),而不需要知道十进制值列的当前名称。有没有办法执行以下选项之一:

  1. 在不知道列名的情况下重命名小数值列
  2. 我可以使用 information_schema 来获取名称,但是我该如何使用它来重命名该列

您可以使用 ALTER TABLE CHANGE COLUMN 语句重命名列,但您必须先知道列的名称。

您必须使用 DESCRIBE <tablename> 或查询 INFORMATION_SCHEMA.COLUMNS 来获取 table.

中列的名称和数据类型

获得列名后,您可以为该列的 ALTER TABLE 语句格式化字符串。您应该使用应用程序代码执行此操作。

如果知道第N个列被定义的位置,可以使用查询来恢复第N个列名:

select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TBL_NAME'
AND ORDINAL_POSITION = POSITION_YOUR_COLUMN

之后,您可以专门手动更改此列(通过 ALTER TABLE)或通过脚本自动更改(在 shell、python、...中生成 ALTER)

我找到了适合我的解决方法。我不知道它一般有多适用,但对于我的应用程序来说,它就像一个魅力。
由于我从外部来源知道 table 中列的顺序,因此我简单地使用 UNION ALL,如下所示:

Select 'Id', 'Name', 'Date', 'Title', 0.00 AS 'Value' LIMIT 0
UNION ALL
Select * from original_table

MySQL 使用值作为列名,除非明确别名。 请注意,LIMIT 0 是必需的,这样您就没有虚拟行。

我使用存储过程:

create procedure renamecolumn(in theTable varchar(128), in oldColumn varchar(128), in newColumn varchar(128)) begin
  set @oldType := (select 
    concat(COLUMN_TYPE,
    if(IS_NULLABLE="NO"," not null",""),
    if(COLUMN_DEFAULT is not null,concat(" default ",if(DATA_TYPE!="int","'",""),COLUMN_DEFAULT,if(DATA_TYPE!="int","'","")),""),
    if(COLUMN_KEY="PRI"," primary key","")," ",EXTRA) from information_schema.columns 
  where table_name = theTable and column_name = oldColumn and table_schema = database());

  set @exist := (select count(*) from information_schema.columns 
                 where table_name = theTable and column_name = newColumn and table_schema = database());
  set @alterstmt   := (select concat("alter table " ,theTable, " change column ", oldcolumn, " ", newColumn, " ", @oldType));
  set @warningstmt := (select concat("a column with the name '" ,newColumn, "' already exists in ", theTable));
  set @sqlstmt     := if( @exist > 0, 'select @warningstmt as warning', @alterstmt);
  PREPARE stmt FROM @sqlstmt;
  EXECUTE stmt;
end;