【问题标题】:Can I rename a MySQL Column without knowing the existing column name?我可以在不知道现有列名的情况下重命名 MySQL 列吗?
【发布时间】:2017-12-23 19:42:58
【问题描述】:

我正在编写一系列 MySQL 查询来操作表中的数据。我有一张由我无法控制的系统自动生成的表。当我得到它时,该表有几列:

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

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

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

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

【问题讨论】:

  • 我应该注意,查询是在数据仓库工具中执行的,我不完全确定它将接受哪些 mysql 命令的功能,但发现它接受一个非常大的我尝试过的大多数命令。
  • 设计了按日期命名列的外部系统的人应该得到pantsed
  • 使用动态 SQL 查询 info 模式来获取不在表中的列名(ID、名称、日期、标题)。如果剩下 1 列,那就是您需要更改的列名。如果超过 1 则结构发生变化,您需要错误地询问要做什么(因为您需要向 not in 添加一个新列)
  • @BillKarwin - 阿门!

标签: mysql alter-table information-schema


【解决方案1】:

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

您必须使用DESCRIBE <tablename> 或查询INFORMATION_SCHEMA.COLUMNS 来获取表中列的名称和数据类型。

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

【讨论】:

  • 谢谢,比尔! Alter Table 语句是我卡住的地方,仅仅是因为我使用的应用程序没有任何应用程序代码功能......只是一系列 MySQL 查询。不过我找到了另一种解决方法......因为我知道表中列的顺序,所以我只需使用 UNION ALL 命令,如下所示:选择'Id','Name','Date','Title', 0.00 AS 'Value' UNION ALL Select * from originaltable 然后我用第二个查询从第一个查询中选择所有 WHERE Id!='Id' 感觉就像一个 hack,但它有效!
  • 哇,这是一个 hack,但它确实有效。该应用程序必须令人抓狂。
【解决方案2】:

如果您知道定义列的位置 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)

【讨论】:

    【解决方案3】:

    我使用存储过程:

    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;
    

    【讨论】:

      【解决方案4】:

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

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

      MySQL 使用这些值作为列名,除非显式别名。 请注意,LIMIT 0 是必需的,因此您没有虚拟行。

      【讨论】:

        猜你喜欢
        • 2014-12-07
        • 1970-01-01
        • 1970-01-01
        • 2011-12-16
        • 2011-01-11
        • 2013-08-06
        • 2021-07-15
        • 1970-01-01
        • 2018-08-20
        相关资源
        最近更新 更多