MariaDB: select all fields but one field is modified [duplicate] - mysql
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)
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>
(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
Would a View work better in this case?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
You can do:
SELECT column1, column2, column4 FROM table WHERE whatever
without getting column3, though perhaps you were looking for a more general solution?
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
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.
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;
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.
You could use DESCRIBE my_table and use the results of that to generate the SELECT statement dynamically.
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.
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
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
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
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
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.
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.
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;
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! :)
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!
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,";
}
}
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)
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.
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");
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'
I use this work around although it may be "Off topic" - using mysql workbench and the query builder -
Open the columns view
Shift select all the columns you want in your query (in your case all but one which is what i do)
Right click and select send to SQL Editor-> name short.
Now you have the list and you can then copy paste the query to where ever.
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.
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.
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';
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
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.
Related
select * from two tables with same column names mySQL
Let us say I have two tables with many columns so I do not want to name the column names explicitly in my query but i want to avoid duplicate names. If I do: CREATE TABLE new_table SELECT a.*, b.* FROM table1 a INNER JOIN table2 b ON a.myID = b.myId WHERE a.age > 10 and b.ice = 'melted' I will get an error saying: duplicate column name myId, I could also get more errors if more column names in a and b are the same. How can I avoid this issue by automatically adding a prefix to all column names in a.* and b.* w/o explicitly mentioning all the column names - very tedious to do so! Thanks!
Unfortunately, you will have to list the columns in case table have matching column names. However, you can use information_schema to get the column names, format those and copy paste in the query to save the pain, e.g.: SELECT GROUP_CONCAT(CONCAT('a.', COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'schema' AND TABLE_NAME = 'table'; The above query should give you comma separated column names with a. prefix. You can then use the same query for table b, get the names out and use it in the main SELECT query. Update As #Uueerdo has rightly said, you can add alias to columns as well, e.g.: SELECT GROUP_CONCAT(CONCAT('a.', COLUMN_NAME, ' AS a_', COLUMN_NAME)) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'schema' AND TABLE_NAME = 'table';
In my experience ORMs will run an initial DESCRIBE query so it can do this sort of stuff for you once it has the column names. But if you insist on doing it dynamically in a single query, you could do this with pure MySQL: -- config SET #database = 'your_database'; SET #tableA = 'table1'; SET #tableB = 'table2'; -- table alias "a" columns SET #fieldsA = NULL; SELECT GROUP_CONCAT(CONCAT('a.', COLUMN_NAME), ' AS ',CONCAT('`a.', COLUMN_NAME,'`')) INTO #fieldsA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = #database AND TABLE_NAME = #tableA; -- table alias "b" columns SET #fieldsB = NULL; SELECT GROUP_CONCAT(CONCAT('b.', COLUMN_NAME), ' AS ',CONCAT('`b.', COLUMN_NAME,'`')) INTO #fieldsB FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = #database AND TABLE_NAME = #tableB; -- some variables for readability SET #fields = CONCAT(' ', #fieldsA, ',', #fieldsB,' '); SET #tableAliasA = CONCAT(' ',#database, '.', #tableA,' a '); SET #tableAliasB = CONCAT(' ',#database, '.', #tableB,' b '); -- generate our final query SET #query = CONCAT('CREATE TABLE new_table SELECT', #fields, 'FROM', #tableAliasA, 'INNER JOIN', #tableAliasB, 'ON a.myID = b.myId WHERE a.age > 10 and b.ice = ''melted'''); -- finally run the query: PREPARE stmt1 FROM #query; EXECUTE stmt1; DEALLOCATE PREPARE stmt1; -- if you have problems with the above query, uncomment the following to get the query so you can run it separately -- SELECT #query; I'd strongly advise against using this sort of solution though. I'd sooner run an initial DESCRIBE query as earlier stated, then generate your query based on that. Another solution is to create a temporary table as a copy of the second table, then rename problematic columns, then proceed to join on it to produce the data you need to create your new_table. MySQL has no issues with result columns having the same name, the issue here is trying to create a table with two columns with the same name. So essentially what you're trying to do is a star select but excluding a column. Another approach is to just select only the primary key from both: SELECT a.myID as `aId`, b.myId as `bId` then create your table containing only that. Then if you ever need data from a particular table, just LEFT JOIN on it to grab the information you're looking for. You can take this a step further and set up a VIEW to do this sort of thing for you. VIEWs can join tables for you and make it very easy to select whatever columns you're looking for. You can also setup multiple VIEWs as well. Also note that views behave just like tables for the purpose of joins. You can JOIN a view with a table, or you can join a view with a view, etc. So rather than do what you're trying to do -- creating a new table with the data from two other tables -- consider whether you're actually looking for a VIEW.
Search all columns of a table using a single where condition with single keyword in mysql
I have a table which consists of 64 different fields. i am going to search with a single keyword in it, Results should match the keyword from any field. Give some suggestions.
SELECT * FROM `some_table` WHERE CONCAT_WS('|',`column1`,`column2`,`column3`,`column4`,`column64`) # single condition, many columns LIKE '%VT%' Voila. The '|' separator, by the way, is to prevent you finding coincidental matches where, e.g., column1 ends in 'V' and column2 starts with 'T', which would give you a false positive in a search for "VT". I'm not sure if the above method is faster than the OR method (I would guess they're the same speed) , but it definitely involves less typing if you're writing the query by hand.
you can use the where with multiple condition with OR like where name = 'expected' OR rate ='expected' OR country ='expected'
I can't see a way around your query being simple but long: SET #term = "Somesearch"; SELECT id, title FROM sometable WHERE col1 LIKE '%#term%' OR col2 LIKE '%#term%' OR col3 LIKE '%#term%' ...; Instead of using a MySQL variable, you can just use a language-specific variable but for the sake of examples, I thought I'd stick with MySQL itself. The "..." is where you'd place the other 61 columns/fields.
Another possibility would be to use FOR XML to get all columns to print to a single field... like this: SELECT c.* FROM ( SELECT a.* ,( SELECT * FROM table_to_search b WHERE a.KeyField = b.KeyField FOR XML RAW) AS `Full_Text_Record` FROM table_to_search a) c WHERE c.`Full_Text_Record` LIKE '%Search_string%' Might take a while to run if it is a particularly large table, but it should brute force you to find out if that string exists in any given table.
If you can translate this SQL Server syntax to MySQL WHERE name = #keyword OR country = #keyword OR department = #keyword OR #keyword IS NULL -- match all when search text is empty
Simplest solution would be to use multiple ORs. select * from TAB where col1 like "%VAR%" OR col2 like "%VAR%" OR......col64 like "%VAR%"; You can use like or = as per the requirement, but it will require to change your query every time you add a new column. As an alternative, you can take SQLDump for that table and then search that file. With some Googling, See if this project is useful - http://code.google.com/p/anywhereindb/. Searches all the fields and praised by many. Try to use the information from information_schema table. Look for all the columns in the table. Now, try to form your query using this information.
You could write one query that will generate a query for every column in your table. In the example below the schema ("owner") is 'DEV_USER' The table with your 64 fields is called 'CUSTOMER_INFO' The criteria in the search is any column with a value of 'VT' in it: select 'SELECT ' || COLUMN_NAME || ' FROM CUSTOMER_INFO WHERE ' || COLUMN_NAME || q'# LIKE '%VT%';#' FROM ALL_TAB_COLS WHERE OWNER = 'DEV_USER' AND TABLE_NAME = 'CUSTOMER_INFO'; This one query will generate a query for each field for you. The results of running the above would be; SELECT ADDRESS_1 FROM CUSTOMER_INFO WHERE ADDRESS_1 LIKE '%VT%'; SELECT ADDRESS_2 FROM CUSTOMER_INFO WHERE ADDRESS_2 LIKE '%VT%'; SELECT CITY FROM CUSTOMER_ADDRESSES_QASB WHERE CITY LIKE '%VT%'; SELECT STATE_PROVINCE FROM CUSTOMER_INFO WHERE STATE_PROVINCE LIKE '%VT%'; SELECT ZIP_POSTAL_CODE FROM CUSTOMER_INFO WHERE ZIP_POSTAL_CODE LIKE '%VT%'; WHERE LATITUDE LIKE '%VT%'; ... and so on for each column in the table Then you just paste those queries that were generated from your first query into another tab and run them. Hope that helps. :-)
You can use dynamic SQL to generate and execute a query that searches all the columns. DELIMITER $$ CREATE PROCEDURE searchAllCols(inDB VARCHAR(64), inTable VARCHAR(64), search VARCHAR(32)) BEGIN SET #matches = ( SELECT GROUP_CONCAT(CONCAT('`', COLUMN_NAME, '` LIKE "%', search, '%"') SEPARATOR ' OR ') FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = inTable and table_schema = inDB); SET #query = CONCAT('SELECT * FROM `', inDB, '`.`', inTable, '` WHERE ', #matches); PREPARE stmt FROM #query; EXECUTE stmt; END $$ DELIMITER ; CALL searchAllCols('table_to_search', 'searchString');
Select specific columns, along with the rest
I have a table with a lot of columns. Some of these are DATETIME, which I turn into Unix timestamps with UNIX_TIMESTAMP(). So I don't have to type out all the other columns I want from the table, is there a way of doing something like: SELECT UNIX_TIMESTAMP(t.start) AS start, UNIX_TIMESTAMP(t.end) AS end, t.theOtherColumns FROM table t Where t.theOtherColumns is the rest of the columns in the table. To explain further; I want to select all the columns from the table, perform operations on some of them, but not type out each column name into the query. When I do, say, SELECT UNIX_TIMESTAMP(t.start) AS start, UNIX_TIMESTAMP(t.end) AS end, t.theOtherColumns FROM table t It selects start and end twice. I only want to return the start and end columns from UNIX_TIMESTAMP(), and exclude those columns from the t.* set.
What you can do is use this answer to help build the results you want. A possible solution would look like SET #sql = CONCAT('SELECT UNIX_TIMESTAMP(t.start) AS start, UNIX_TIMESTAMP(t.end) as end,', (SELECT GROUP_CONCAT(COLUMN_NAME) FROM information_schema.columns WHERE table_schema = 'test' AND table_name = 't' AND column_name NOT IN ('start', 'end')), ' from test.t'); PREPARE stmt1 FROM #sql; EXECUTE stmt1; *Replace test with the name of the schema that contains your table t.
Try t.* it works under Oracle.
I don't believe there is a way to do this as you suggested, but you can do this SELECT t.*, UNIX_TIMESTAMP(t.start) AS start, UNIX_TIMESTAMP(t.end) as end ...
MySQL concat() to create column names to be used in a query?
I would like to concatenate column names in a way that the first part of the column name is a string and the second part is a number which is the result of another query. For example: SELECT CONCAT('column', mytable.mycolumn) FROM table ... Can this be done in some way. This way it doesn't give me errors but I don't get the expected result and it seems the concatenation doesn't work.
I previously said that this couldn't be done, but I was wrong. I ended up needing something like this myself so I looked around, and discovered that server-side prepared statements let you build and execute arbitrary SQL statements from strings. Here is an example I just did to prove the concept: set #query := ( select concat( "select", group_concat(concat("\n 1 as ", column_name) separator ','), "\nfrom dual") from information_schema.columns where table_name = 'columns') ; prepare s1 from #query ; execute s1 ; deallocate prepare s1 ;
If the number of columns is fixed, then a non-dynamic approach could be: select case mytable.mycolumn when 1 then column1 -- or: when 'a' then columna when 2 then column2 when ... else ... end as my_semi_dynamic_column from ...
I don't believe you can do this with CONCAT() and CONCAT_WS(). I'd recommend using the langauge you are working with the create the field names. Doing it this way would be pretty scary, depending on where the data in the database came from.
I would suggest looking at information_schema. The following code is untested but should theoretically work. Obviously replace your table name with an appropriate table name or link to information_schema.tables and use the table_type in your where clause select concat('column', column_name) from information_schema.columns where table_name ='your table name'
Select all columns except one in MySQL?
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)
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>
(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
Would a View work better in this case? CREATE VIEW vwTable as SELECT col1 , col2 , col3 , col.. , col53 FROM table
You can do: SELECT column1, column2, column4 FROM table WHERE whatever without getting column3, though perhaps you were looking for a more general solution?
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
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.
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;
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.
You could use DESCRIBE my_table and use the results of that to generate the SELECT statement dynamically.
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.
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
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
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
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
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.
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.
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;
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! :)
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!
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,"; } }
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)
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.
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");
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'
I use this work around although it may be "Off topic" - using mysql workbench and the query builder - Open the columns view Shift select all the columns you want in your query (in your case all but one which is what i do) Right click and select send to SQL Editor-> name short. Now you have the list and you can then copy paste the query to where ever.
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.
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.
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';
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
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.