459

I'm trying to use a select statement to get all of the columns from a certain MySQL table except one. Is there a simple way to do this?

EDIT: There are 53 columns in this table (NOT MY DESIGN)

dreftymac
  • 31,404
  • 26
  • 119
  • 182
Tom Grochowicz
  • 5,385
  • 3
  • 21
  • 18
  • 1
    Except one colum... I supose you know which one should be ignored, hence INFORMATION_SCHEMA.columns is the way. – Alfabravo Feb 23 '10 at 22:09
  • Check out [this answer](http://stackoverflow.com/questions/2365972/how-can-i-select-from-a-table-in-mysql-but-omit-certain-columns/13808457#13808457) it does what you want to do! – donL Dec 10 '12 at 20:22
  • 6
    53 columns? I would stick with SELECT * as Thomas suggests in that case... unless that extra column has a huge amount of data that would be undesirable to retrieve...? – Mike Stone Aug 12 '08 at 18:52
  • The big data column is a real issue when geographic data is held. Columns can be many megabytes in size. They work well in where clauses to find rows, but you often don't want that data in the results. – Jason Apr 19 '20 at 12:26
  • 3
    A common use for this is to exclude the auto-increment ID column. For example, to select data to be inserted into a different table, which has its own ID. – ToolmakerSteve Apr 22 '20 at 19:28
  • 4
    A common use for this is to exclude the password hash when retrieving the user info – Gianluca Ghettini Jul 09 '21 at 10:10
  • 4
    honestly it's rather ridiculous there isn't simple way to do it ffs – Enerccio Oct 27 '21 at 13:53
  • I imagine that this need may arise from the need to exclude a value to be passed on to an external resource. If the field is not very large, you could retrieve it in the SQL call anyway, and then unset with the programming language. – Giuseppe Ruffa Feb 12 '22 at 09:24

33 Answers33

251

Actually there is a way, you need to have permissions of course for doing this ...

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

PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

Replacing <table>, <database> and <columns_to_omit>

haim770
  • 48,394
  • 7
  • 105
  • 133
Mahomedalid
  • 3,074
  • 2
  • 17
  • 13
  • 23
    caveat: INFORMATION_SCHEMA queries have pretty poor performance, so be careful this type of query isn't in the critical path for anything. – Bill Karwin Sep 20 '11 at 21:08
  • 10
    Like @Jan Koritak said below, this answer doesn't actually work if the title's columns that you want to remove are also a sub-string of the title for any columns you wish to keep. [There is a better answer that is similar to this that can be found here](http://stackoverflow.com/questions/2365972/how-can-i-select-from-a-table-in-mysql-but-omit-certain-columns/13808457#13808457). – donL Dec 10 '12 at 22:11
  • 1
    This solution doesn't work if you have column names such as id, product_id, etc. http://stackoverflow.com/a/17719025/1827513 is the correct answer. – cazgp Jan 02 '14 at 11:49
  • 10
    This is way worse than just specifying the columns which is a known best practice. – HLGEM Jan 16 '14 at 18:08
  • Sure, is worse than just specifying the columns, the thing here is that sometimes you need to generate SQL from a CASE tool or a framework in just one step without using external languages. – Mahomedalid Jun 24 '14 at 22:42
  • 4
    This doesnt work if there are spaces in the column names. It should be updated to always surround the names in backticks `` – adamF Jul 24 '14 at 22:01
  • 4
    This also won't work if the column to be ignored is the last one listed in the table structure (because the replace will not match the trailing coma). – Vincent Pazeller Feb 17 '15 at 13:46
  • Really great solution for our DB whose tables include an annoyingly large XML col. – belwood Mar 18 '15 at 14:17
  • Does tying your project to mysql this tightly bring your code under GPL? IANAL, but I think you should make your stuff work on two backends so nobody can say mysql is part of your source. – doug65536 May 09 '22 at 22:39
  • for those who have problem in some specific situation i suggest change @sql to `CONCAT ("SELECT ", (SELECT GROUP_CONCAT(column_name SEPARATOR ', ') FROM information_schema.columns WHERE table_name='' AND column_name NOT LIKE ''), ' FROM ')` – Saghachi May 13 '23 at 05:14
70

(Do not try this on a big table, the result might be... surprising !)

TEMPORARY TABLE

DROP TABLE IF EXISTS temp_tb;
CREATE TEMPORARY TABLE ENGINE=MEMORY temp_tb SELECT * FROM orig_tb;
ALTER TABLE temp_tb DROP col_a, DROP col_f,DROP col_z;    #// MySQL
SELECT * FROM temp_tb;

DROP syntax may vary for databases @Denis Rozhnev

jfg956
  • 16,077
  • 4
  • 26
  • 34
bortunac
  • 4,642
  • 1
  • 32
  • 21
  • 4
    Gave me error message on 3rd step: "Column count doesn't match value count at row 1". So I changed step 2 to "UPDATE temp_tb SET id = NULL" and then it worked. – oyvey Nov 21 '16 at 07:44
  • 1
    Ok, this works. But when I run this query again, it gives me an error, that, temp_tb already exists. For how much time the temp_tb is in the memory? Apologies if it's a stupid question. P.S. upvoted your answer. – Karan Sep 26 '18 at 17:26
  • 3
    @Karan To run this query repeatedly, add another command to the beginning: `DROP TABLE IF EXISTS temp_tb; ` – gregn3 Jul 11 '19 at 17:43
  • 1
    @Karan To specify memory engine, use the command: `CREATE TEMPORARY TABLE temp_tb ENGINE=MEMORY (SELECT * FROM orig_tb); ` , otherwise it's saved to disk by default, and survives a server restart. ([thanks](https://stackoverflow.com/questions/20144394/create-table-as-select-using-memory-engine-in-ram-memory)) – gregn3 Jul 11 '19 at 18:00
  • Excellent answer. For **dropping multiple columns**, refer to [this answer](https://stackoverflow.com/a/15823531/6340496). – S3DEV Feb 13 '20 at 12:21
  • `HEY DATABASE COPY EVERYTHING TO MEMORY SO I CAN READ ONE THING;` :) – MuhsinFatih Oct 23 '20 at 12:21
52

Would a View work better in this case?

CREATE VIEW vwTable
as  
SELECT  
    col1  
    , col2  
    , col3  
    , col..  
    , col53  
FROM table
Brian Childress
  • 1,140
  • 9
  • 13
  • 33
    HAHA! Yeah, sure. Now how do you construct the view to include all BUT one of the columns. I think you see how this begs the original question. In fact, I found this thread specifically because I wanted to create a view that excluded certain columns without being forced to list all the remaining columns explicitly in the view definition. – Chris Nadovich Jan 14 '19 at 03:11
  • @ChrisNadovich but with View you just list once. – João Pimentel Ferreira Jul 04 '22 at 18:11
34

You can do:

SELECT column1, column2, column4 FROM table WHERE whatever

without getting column3, though perhaps you were looking for a more general solution?

Mike Stone
  • 44,224
  • 30
  • 113
  • 140
  • 8
    Most of the higher rated answers are mostly just finding ways to generate this exact query without typing by hand – krethika Mar 12 '14 at 21:52
  • 10
    Actually, for maintenance reasons, it is useful to have an "everything except" kind of query. Otherwise explicit field lists must be updated if new fields are added later. – leiavoia Mar 25 '14 at 17:12
  • 1
    @lev, that's correct and THEY SHOULD BE!!! BEcasue you don't know if you want to have any future columns (they may be meta data columns or ones that don't apply to a particular screen). You dont; want to harm performance by returning more than you need (which is true 100% of the time when you have an inner join) I suggest you do some reading on why select * is a SQL antipattern. – HLGEM May 22 '14 at 19:27
  • 39
    The OP states there are >50 columns so this is rather impractical. – augurar Sep 10 '15 at 18:13
  • 1
    @HLGEM Not really, I wanted to select all columns without maintaining the query every time I add a new column, except one of them, and this wouldn't simply work in my case. But anyways I applied Sean O's solution for myself – OverCoder Sep 15 '16 at 11:00
  • I think OP asked the question to explicitly avoid writing this particular query.. – Jin Wang Jun 29 '21 at 19:18
  • This is the same thing as when people want you to help them glob all the sources in their build. You can help them do that, and they shouldn't do that. Same thing with `*`. You should list them. You are supposed to have to update it when you add a new field, the code has to volunteer to get it. – doug65536 May 09 '22 at 22:26
27

If you are looking to exclude the value of a field, e.g. for security concerns / sensitive info, you can retrieve that column as null.

e.g.

SELECT *, NULL AS salary FROM users
Sean O
  • 2,276
  • 1
  • 21
  • 24
  • 22
    Why? It doesn't work. If you have a column salary, this query will just end up with the results having two columns named salary, one full of nulls and one with the actual salaries. – Myforwik Aug 29 '13 at 23:50
  • 4
    @Myforwik This query does indeed add a second `salary` column. But since it's retrieved after the *, it overwrites the original. It's not pretty, but it does work. – Sean O Aug 30 '13 at 18:17
  • You're right, @SeanO - I also didn't realise that it was replacing the original column. Very neat! – Alastair Sep 13 '13 at 05:07
  • 86
    SQL has always allowed duplicate column names in a result-set. If you want this to work you need to run it with a client application that doesn't support dupes *and* gives priority to the last dupe. The official command-line client supports dupes. HeidiSQL supports them as well. [SQL Fiddle](http://sqlfiddle.com/#!2/f7e53/1) doesn't, but displays *first* dupe, not last. To sum up: **this does not work**. – Álvaro González Oct 01 '13 at 08:24
  • 11
    Of course it doesn't work. This is great example of why you should test your answers in mysql itself, instead of through libraries that talk to mysql. – Myforwik Oct 03 '13 at 05:18
  • 9
    @SeanO, @​ Alastair, @​ Everyone, **Doesn't Override.** The server still returns sensitive data. – Pacerier Feb 05 '15 at 04:23
  • 2
    Doesn't work. Returns two columns, one with the data and one with nulls – Ethan Allen Mar 01 '17 at 19:43
  • looks like it would do the work, but instead adds a new column. – Chris Russo Sep 16 '19 at 06:18
  • 2
    If you fetch as `Object` or `Assoc` it will overwrite the columns – Ahmed Ali Feb 17 '20 at 10:41
  • Fetch as `Object` or `Assoc` doesn't allow duplicate columns so the last column (which is null) is returned. Would have been great if @SeanO mentioned that. – Frank Fotangs May 18 '22 at 09:48
26

To the best of my knowledge, there isn't. You can do something like:

SELECT col1, col2, col3, col4 FROM tbl

and manually choose the columns you want. However, if you want a lot of columns, then you might just want to do a:

SELECT * FROM tbl 

and just ignore what you don't want.

In your particular case, I would suggest:

SELECT * FROM tbl

unless you only want a few columns. If you only want four columns, then:

SELECT col3, col6, col45, col 52 FROM tbl

would be fine, but if you want 50 columns, then any code that makes the query would become (too?) difficult to read.

Arion
  • 31,011
  • 10
  • 70
  • 88
Thomas Owens
  • 114,398
  • 98
  • 311
  • 431
  • 5
    Select * is a poor choice always. Do not recommend it. Read up on why it is a SQl Antipattern. – HLGEM Jan 16 '14 at 18:03
19

While trying the solutions by @Mahomedalid and @Junaid I found a problem. So thought of sharing it. If the column name is having spaces or hyphens like check-in then the query will fail. The simple workaround is to use backtick around column names. The modified query is below

SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(CONCAT("`", COLUMN_NAME, "`")) FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;
Suraj
  • 451
  • 7
  • 17
11

If the column that you didn't want to select had a massive amount of data in it, and you didn't want to include it due to speed issues and you select the other columns often, I would suggest that you create a new table with the one field that you don't usually select with a key to the original table and remove the field from the original table. Join the tables when that extra field is actually required.

Stacey Richards
  • 6,536
  • 7
  • 38
  • 40
10

You could use DESCRIBE my_table and use the results of that to generate the SELECT statement dynamically.

jammycakes
  • 5,780
  • 2
  • 40
  • 49
9

My main problem is the many columns I get when joining tables. While this is not the answer to your question (how to select all but certain columns from one table), I think it is worth mentioning that you can specify table. to get all columns from a particular table, instead of just specifying .

Here is an example of how this could be very useful:

select users.*, phone.meta_value as phone, zipcode.meta_value as zipcode

from users

left join user_meta as phone
on ( (users.user_id = phone.user_id) AND (phone.meta_key = 'phone') )

left join user_meta as zipcode
on ( (users.user_id = zipcode.user_id) AND (zipcode.meta_key = 'zipcode') )

The result is all the columns from the users table, and two additional columns which were joined from the meta table.

cwd
  • 53,018
  • 53
  • 161
  • 198
  • 2
    thank you ,i need to select all of columns of first table and only one field from second table in joining and your answer helped me. – mohammad falahat Jun 27 '12 at 10:44
8

I liked the answer from @Mahomedalid besides this fact informed in comment from @Bill Karwin. The possible problem raised by @Jan Koritak is true I faced that but I have found a trick for that and just want to share it here for anyone facing the issue.

we can replace the REPLACE function with where clause in the sub-query of Prepared statement like this:

Using my table and column name

SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;

So, this is going to exclude only the field id but not company_id

Dharman
  • 30,962
  • 25
  • 85
  • 135
Junaid
  • 2,084
  • 1
  • 20
  • 30
7

Yes, though it can be high I/O depending on the table here is a workaround I found for it.

SELECT *
INTO #temp
FROM table

ALTER TABLE #temp DROP COlUMN column_name

SELECT *
FROM #temp
Valerian Pereira
  • 725
  • 1
  • 6
  • 16
Nathan A
  • 87
  • 1
  • 1
4

I agree with the "simple" solution of listing all the columns, but this can be burdensome, and typos can cause lots of wasted time. I use a function "getTableColumns" to retrieve the names of my columns suitable for pasting into a query. Then all I need to do is to delete those I don't want.

CREATE FUNCTION `getTableColumns`(tablename varchar(100)) 
          RETURNS varchar(5000) CHARSET latin1
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE res  VARCHAR(5000) DEFAULT "";

  DECLARE col  VARCHAR(200);
  DECLARE cur1 CURSOR FOR 
    select COLUMN_NAME from information_schema.columns 
    where TABLE_NAME=@table AND TABLE_SCHEMA="yourdatabase" ORDER BY ORDINAL_POSITION;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
  OPEN cur1;
  REPEAT
       FETCH cur1 INTO col;
       IF NOT done THEN 
          set res = CONCAT(res,IF(LENGTH(res)>0,",",""),col);
       END IF;
    UNTIL done END REPEAT;
  CLOSE cur1;
  RETURN res;

Your result returns a comma delimited string, for example...

col1,col2,col3,col4,...col53

David Poor
  • 1,261
  • 2
  • 8
  • 2
  • [Here is an answer that shows a function that accomplishes the same thing but is much simpler](http://stackoverflow.com/questions/2365972/how-can-i-select-from-a-table-in-mysql-but-omit-certain-columns/13808457#13808457)! – donL Dec 10 '12 at 22:17
4

It is good practice to specify the columns that you are querying even if you query all the columns.

So I would suggest you write the name of each column in the statement (excluding the one you don't want).

SELECT
    col1
    , col2
    , col3
    , col..
    , col53

FROM table
mbillard
  • 38,386
  • 18
  • 74
  • 98
  • It acts like a contract with the code and when looking at the query, you know exactly what data you can extract from the it without looking at the schema of the table. – mbillard Feb 23 '09 at 14:54
  • 6
    @kodecraft: It's good practice for the same reason that it's good practice to alway return the same type from a function (even if you work in a language where that's not enforced). Basically just the Principle of Least Surprise. – Daniel Pryden Sep 03 '09 at 20:47
3

Based on @Mahomedalid answer, I have done some improvements to support "select all columns except some in mysql"

SET @database    = 'database_name';
SET @tablename   = 'table_name';
SET @cols2delete = 'col1,col2,col3';

SET @sql = CONCAT(
'SELECT ', 
(
    SELECT GROUP_CONCAT( IF(FIND_IN_SET(COLUMN_NAME, @cols2delete), NULL, COLUMN_NAME ) )
    FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tablename AND TABLE_SCHEMA = @database
), 
' FROM ',
@tablename);

SELECT @sql;

If you do have a lots of cols, use this sql to change group_concat_max_len

SET @@group_concat_max_len = 2048;
hahakubile
  • 6,978
  • 4
  • 28
  • 18
3

I agree with @Mahomedalid's answer, but I didn't want to do something like a prepared statement and I didn't want to type all the fields, so what I had was a silly solution.

Go to the table in phpmyadmin->sql->select, it dumps the query: copy, replace and done! :)

Shark Lasers
  • 441
  • 6
  • 15
neelabh
  • 479
  • 6
  • 19
3

I agree that it isn't sufficient to Select *, if that one you don't need, as mentioned elsewhere, is a BLOB, you don't want to have that overhead creep in.

I would create a view with the required data, then you can Select * in comfort --if the database software supports them. Else, put the huge data in another table.

nlucaroni
  • 47,556
  • 6
  • 64
  • 86
3

At first I thought you could use regular expressions, but as I've been reading the MYSQL docs it seems you can't. If I were you I would use another language (such as PHP) to generate a list of columns you want to get, store it as a string and then use that to generate the SQL.

icco
  • 3,064
  • 4
  • 35
  • 49
2

You can use SQL to generate SQL if you like and evaluate the SQL it produces. This is a general solution as it extracts the column names from the information schema. Here is an example from the Unix command line.

Substituting

  • MYSQL with your mysql command
  • TABLE with the table name
  • EXCLUDEDFIELD with excluded field name
echo $(echo 'select concat("select ", group_concat(column_name) , " from TABLE") from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1) | MYSQL

You will really only need to extract the column names in this way only once to construct the column list excluded that column, and then just use the query you have constructed.

So something like:

column_list=$(echo 'select group_concat(column_name) from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1)

Now you can reuse the $column_list string in queries you construct.

sth
  • 222,467
  • 53
  • 283
  • 367
rplevy
  • 5,393
  • 3
  • 32
  • 31
2

I wanted this too so I created a function instead.

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)."`";
    }
}

So how it works is that you enter the table, then a column you don't want or as in an array: array("id","name","whatevercolumn")

So in select you could use it like this:

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

or

mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");
Kilise
  • 1,051
  • 4
  • 15
  • 35
2

May be I have a solution to Jan Koritak's pointed out discrepancy

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' );

Table :

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

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

Query Result:

'SELECT name_eid,sal FROM employee'
Bhavik Shah
  • 5,125
  • 3
  • 23
  • 40
2

Just do

SELECT * FROM table WHERE whatever

Then drop the column in you favourite programming language: php

while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) {
   unset($data["id"]);
   foreach ($data as $k => $v) { 
      echo"$v,";
   }      
}
Soth
  • 2,901
  • 2
  • 27
  • 27
  • 7
    Unless the column you want to exclude is a huge BLOB or something. – Bill Karwin Sep 20 '11 at 21:09
  • 1
    This is bad if you're trying to avoid the wasted data. – Kristopher Ives Sep 25 '11 at 20:13
  • 1 column from 53 should not make any difference. If it does it's probably a bad design. – Petr Peller Jun 20 '13 at 17:41
  • 1
    SElect * is a SQL antipattern and shouldl never be used in production code. – HLGEM Mar 30 '15 at 13:56
  • 1
    I don't agree that SELECT * is some kind of anti-pattern that should "never" be used in production code. It's far clearer that you've retrieved all your columns - as compared to cross-referencing a long list of columns that may, or not, in fact be all the fields. It's also, very obviously, quicker to code, by far. And there are many, many cases where the fields of the table will correspond exactly to the fields in a view or form. – Geoff Kendall Jul 17 '18 at 22:38
  • 1
    Perfect solution. Out of all the weird long and unclear solutions which I have seen so far, this one is straightforward and clear, and works perfectly. While it may not be efficient for some people with humongous databases, but for most of us this is just perfect. In my case SELECT * or SELECT individual columns doesn't make any difference, all I needed was to exclude two timestamp columns from a list which will have hardly 20-30 records per user. So no efficiency hit for me. – zeeshan Jan 08 '19 at 04:01
  • this is only a viable solution if you're the kind of person who likes php (and doesn't work for pure sql manipulation) – Rene Wooller May 30 '19 at 07:50
2

I use this work around although it may be "Off topic" - using mysql workbench and the query builder -

  1. Open the columns view
  2. Shift select all the columns you want in your query (in your case all but one which is what i do)
  3. Right click and select send to SQL Editor-> name short.
  4. Now you have the list and you can then copy paste the query to where ever.

enter image description here

DropHit
  • 1,695
  • 15
  • 28
2

The answer posted by Mahomedalid has a small problem:

Inside replace function code was replacing "<columns_to_delete>," by "", this replacement has a problem if the field to replace is the last one in the concat string due to the last one doesn't have the char comma "," and is not removed from the string.

My proposal:

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>');

Replacing <table>, <database> and `

The column removed is replaced by the string "FIELD_REMOVED" in my case this works because I was trying to safe memory. (The field I was removing is a BLOB of around 1MB)

Mat
  • 202,337
  • 40
  • 393
  • 406
2

While I agree with Thomas' answer (+1 ;)), I'd like to add the caveat that I'll assume the column that you don't want contains hardly any data. If it contains enormous amounts of text, xml or binary blobs, then take the time to select each column individually. Your performance will suffer otherwise. Cheers!

OJ.
  • 28,944
  • 5
  • 56
  • 71
1

I would like to add another point of view in order to solve this problem, specially if you have a small number of columns to remove.

You could use a DB tool like MySQL Workbench in order to generate the select statement for you, so you just have to manually remove those columns for the generated statement and copy it to your SQL script.

In MySQL Workbench the way to generate it is:

Right click on the table -> send to Sql Editor -> Select All Statement.

1

The accepted answer has several shortcomings.

  • It fails where the table or column names requires backticks
  • It fails if the column you want to omit is last in the list
  • It requires listing the table name twice (once for the select and another for the query text) which is redundant and unnecessary
  • It can potentially return column names in the wrong order

All of these issues can be overcome by simply including backticks in the SEPARATOR for your GROUP_CONCAT and using a WHERE condition instead of REPLACE(). For my purposes (and I imagine many others') I wanted the column names returned in the same order that they appear in the table itself. To achieve this, here we use an explicit ORDER BY clause inside of the GROUP_CONCAT() function:

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

I have a suggestion but not a solution. If some of your columns have a larger data sets then you should try with following

SELECT *, LEFT(col1, 0) AS col1, LEFT(col2, 0) as col2 FROM table
MR_AMDEV
  • 1,712
  • 2
  • 21
  • 38
1

If it's always the same one column, then you can create a view that doesn't have it in it.

Otherwise, no I don't think so.

Gareth Simpson
  • 36,943
  • 12
  • 47
  • 50
0

If you use MySQL Workbench you can right-click your table and click Send to sql editor and then Select All Statement This will create an statement where all fields are listed, like this:

SELECT `purchase_history`.`id`,
    `purchase_history`.`user_id`,
    `purchase_history`.`deleted_at`
FROM `fs_normal_run_2`.`purchase_history`;
SELECT * FROM fs_normal_run_2.purchase_history;

Now you can just remove those that you dont want.

Adam
  • 25,960
  • 22
  • 158
  • 247
0

The question was about MySQL, but I still think it's worth mentioning that at least Google BigQuery and H2 support a * EXCEPT syntax natively, e.g.

SELECT * FROM actor

Producing:

|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|

Whereas

SELECT * EXCEPT (last_update) FROM actor

Producing:

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

Maybe, a future version of MySQL will support this syntax as well?

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
-2

Im pretty late at throing out an answer for this, put this is the way i have always done it and frankly, its 100 times better and neater than the best answer, i only hope someone will see it. And find it useful

    //create an array, we will call it here. 
    $here = array();
    //create an SQL query in order to get all of the column names
    $SQL = "SHOW COLUMNS FROM Table";
        //put all of the column names in the array
        foreach($conn->query($SQL) as $row) {
            $here[] = $row[0];
        }
    //now search through the array containing the column names for the name of the column, in this case i used the common ID field as an example
    $key = array_search('ID', $here);
    //now delete the entry
    unset($here[$key]);
Nick
  • 643
  • 3
  • 7
  • 19
  • It maybe neat, but it does not answer the question: he hasn't asked about php, and you don't give a select statement or a result of what he wants, but only a php array containing the columns he want. – gou1 May 15 '13 at 16:10
  • 3
    –1. This isn’t SQL code, and there is no `SELECT` statement here—the word doesn’t even occur once. – Frungi Jul 23 '13 at 10:12
  • This is only neater to the extent that (a) you are more comfortable with PHP than SQL, or (b) you like spreading your code over multiple lines for readability. I'd concede point (b). Your approach would also be less performant, though the difference would be minor in many use cases. Also see other comments on your question. Not worth shouting about, so suggest you remove your inappropriate comment from the original question. – mc0e Sep 11 '13 at 09:32
-8

Select * is a SQL antipattern. It should not be used in production code for many reasons including:

It takes a tiny bit longer to process. When things are run millions of times, those tiny bits can matter. A slow database where the slowness is caused by this type of sloppy coding throughout is the hardest kind to performance tune.

It means you are probably sending more data than you need which causes both server and network bottlenecks. If you have an inner join, the chances of sending more data than you need are 100%.

It causes maintenance problems especially when you have added new columns that you do not want seen everywhere. Further if you have a new column, you may need to do something to the interface to determine what to do with that column.

It can break views (I know this is true in SQl server, it may or may not be true in mysql).

If someone is silly enough to rebuild the tables with the columns in a differnt order (which you shouldn't do but it happens all teh time), all sorts of code can break. Espcially code for an insert for example where suddenly you are putting the city into the address_3 field becasue without specifying, the database can only go on the order of the columns. This is bad enough when the data types change but worse when the swapped columns have the same datatype becasue you can go for sometime inserting bad data that is a mess to clean up. You need to care about data integrity.

If it is used in an insert, it will break the insert if a new column is added in one table but not the other.

It might break triggers. Trigger problems can be difficult to diagnose.

Add up all this against the time it take to add in the column names (heck you may even have an interface that allows you to drag over the columns names (I know I do in SQL Server, I'd bet there is some way to do this is some tool you use to write mysql queries.) Let's see, "I can cause maintenance problems, I can cause performance problems and I can cause data integrity problems, but hey I saved five minutes of dev time." Really just put in the specific columns you want.

I also suggest you read this book: http://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers-ebook/dp/B00A376BB2/ref=sr_1_1?s=digital-text&ie=UTF8&qid=1389896688&sr=1-1&keywords=sql+antipatterns

HLGEM
  • 94,695
  • 15
  • 113
  • 186