在MySQL中选择除一列之外的所有列?

462

我正在尝试使用select语句获取某个MySQL表中除了某一列之外的所有列。有没有简单的方法可以做到这一点?

编辑:该表中有53个列(不是我设计的)。


6
53个列?在这种情况下,我会像Thomas建议的那样坚持使用SELECT *...除非额外的列有大量数据需要检索,这可能不是我们想要的。 - Mike Stone
1
除了一列...我想你知道应该忽略哪一列,因此INFORMATION_SCHEMA.columns是正确的方式。 - Alfabravo
3
常见用途是排除自动递增的ID列。例如,选择要插入到另一个具有自己ID的表中的数据。 - ToolmakerSteve
4
常见的用法是在检索用户信息时排除密码哈希值。 - Gianluca Ghettini
4
老实说,没有简单的方法来做这件事情,这相当荒谬。 - Enerccio
显示剩余3条评论
33个回答

2

Mahomedalid的答案有一个小问题:

在replace函数中,代码替换了"<columns_to_delete>,"为"",如果要替换的字段是连接字符串中的最后一个,则这种替换会存在问题,因为最后一个字段没有逗号“,”而且不会从字符串中删除。

我的建议:

SET @sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME),
                  '<columns_to_delete>', '\'FIELD_REMOVED\'')
           FROM INFORMATION_SCHEMA.COLUMNS
           WHERE TABLE_NAME = '<table>'
             AND TABLE_SCHEMA = '<database>'), ' FROM <table>');

替换 <table>, <database> 和 `

在我的情况下,已删除的列将被字符串 "FIELD_REMOVED" 替换,这对我有用,因为我试图节省内存。(我要删除的字段是大约1MB的BLOB)


2
也许我有解决Jan Koritak指出的差异的方法。
SELECT CONCAT('SELECT ',
( SELECT GROUP_CONCAT(t.col)
FROM
(
    SELECT CASE
    WHEN COLUMN_NAME = 'eid' THEN NULL
    ELSE COLUMN_NAME
    END AS col 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'
) t
WHERE t.col IS NOT NULL) ,
' FROM employee' );

表格:

SELECT table_name,column_name 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'

================================

table_name  column_name
employee    eid
employee    name_eid
employee    sal

================================

查询结果:

'SELECT name_eid,sal FROM employee'

2

虽然我同意Thomas的答案(+1; ),但是我想要补充一点,假设你想要的那一列几乎没有数据。如果它包含大量文本、xml或二进制对象,则需要花费时间逐个选择每个列。否则,您的性能会受到影响。干杯!


2
我使用这个方法,虽然它可能与主题无关 - 使用MySQL Workbench和查询构建器 -
  1. 打开列视图
  2. Shift选择您需要在查询中使用的所有列(在您的情况下除了一个,这就是我所做的)
  3. 右键单击并选择发送到SQL Editor-> name short。
  4. 现在您有了列表,然后可以将查询复制粘贴到任何地方。

enter image description here


2

我也希望如此,因此我创建了一个函数。

public function getColsExcept($table,$remove){
    $res =mysql_query("SHOW COLUMNS FROM $table");

    while($arr = mysql_fetch_assoc($res)){
        $cols[] = $arr['Field'];
    }
    if(is_array($remove)){
        $newCols = array_diff($cols,$remove);
        return "`".implode("`,`",$newCols)."`";
    }else{
        $length = count($cols);
        for($i=0;$i<$length;$i++){
            if($cols[$i] == $remove)
                unset($cols[$i]);
        }
        return "`".implode("`,`",$cols)."`";
    }
}

如何使用它呢?你需要输入表格,然后是一个你不想要的列或者一个数组:array("id","name","whatevercolumn")

在select语句中,你可以这样使用:

mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");

或者

mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");

1

被接受的答案存在几个缺点。

  • 如果表名或列名需要反引号,则无法成功
  • 如果要省略的列在列表中最后一个,则失败
  • 它需要列出表名两次(一次用于选择,另一次用于查询文本),这是冗余和不必要的
  • 它可能会以错误的顺序返回列名

所有这些问题都可以通过简单地在GROUP_CONCATSEPARATOR中包含反引号并使用WHERE条件而不是REPLACE()来克服。对于我的目的(以及许多其他人的目的),我希望列名按照它们在表中出现的顺序返回。为了实现这一点,在GROUP_CONCAT()函数内部使用显式的ORDER BY子句:

SELECT CONCAT(
    'SELECT `',
    GROUP_CONCAT(COLUMN_NAME ORDER BY `ORDINAL_POSITION` SEPARATOR '`,`'),
    '` FROM `',
    `TABLE_SCHEMA`,
    '`.`',
    TABLE_NAME,
    '`;'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE `TABLE_SCHEMA` = 'my_database'
    AND `TABLE_NAME` = 'my_table'
    AND `COLUMN_NAME` != 'column_to_omit';

1
我想提供另一个解决方案,特别是当您需要删除少量列时。您可以使用类似 MySQL Workbench的数据库工具来为您生成选择语句,因此您只需手动删除所生成语句中的那些列,并将其复制到SQL脚本中。
在MySQL Workbench中生成它的方式是:
右键单击表->发送到Sql编辑器->选择全部语句。

1
如果始终是同一列,那么您可以创建一个不包含它的视图。
否则,我认为不行。

1

我有一个建议,但没有解决方案。 如果你的一些列具有更大的数据集,则应尝试以下操作:

SELECT *, LEFT(col1, 0) AS col1, LEFT(col2, 0) as col2 FROM table

0
这个问题是关于MySQL的,但我仍然认为值得提到至少Google BigQuery和H2本地支持* EXCEPT语法,例如:
SELECT * FROM actor

生成:

|actor_id|first_name|last_name   |last_update            |
|--------|----------|------------|-----------------------|
|1       |PENELOPE  |GUINESS     |2006-02-15 04:34:33.000|
|2       |NICK      |WAHLBERG    |2006-02-15 04:34:33.000|
|3       |ED        |CHASE       |2006-02-15 04:34:33.000|

然而

SELECT * EXCEPT (last_update) FROM actor

生成:

|actor_id|first_name|last_name   |
|--------|----------|------------|
|1       |PENELOPE  |GUINESS     |
|2       |NICK      |WAHLBERG    |
|3       |ED        |CHASE       |

也许,MySQL 的未来版本也会支持这种语法吧?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接