I want to get headerless CSV data from the output of a query to MySQL on the command line. I'm running this query on a different machine from the MySQL server, so all those Google answers with "INTO OUTFILE" are no good.
So I run mysql -e "select people, places from things"
. That outputs stuff that looks kinda like this:
+--------+-------------+
| people | places |
+--------+-------------+
| Bill | Raleigh, NC |
+--------+-------------+
Well, that's no good. But hey, look! If I just pipe it to anything, it turns it into a tab-separated list:
people places
Bill Raleigh, NC
That's better- at least it's programmatically parseable. But I don't want TSV, I want CSV, and I don't want that header. I can get rid of the header with mysql <stuff> | tail -n +2
, but that's a bother I'd like to avoid if MySQL just has a flag to omit it. And I can't just replace all tabs with commas, because that doesn't handle content with commas in it.
So, how can I get MySQL to omit the header and give me data in CSV format?
As a partial answer:
mysql -N -B -e "select people, places from things"
-N
tells it not to print column headers.-B
is "batch mode", and uses tabs to separate fields.If tab separated values won't suffice, see this Stackoverflow Q&A.
The above solutions only work in special cases. You'll get yourself into all kinds of trouble with embedded commas, embedded quotes, other things that make CSV hard in the general case.
Do yourself a favor and use a general solution - do it right and you'll never have to think about it again. One very strong solution is the
csvkit
command line utilities - available for all operating systems via Python. Install viapip install csvkit
. This will give you correct CSV data:That produces comma-separated data with the header still in place. To drop the header row:
That produces what the OP requested.
It is how to save results to CSV on the client-side without additional non-standard tools. This example uses only
mysql
client andawk
.One-line:
Logical explanation of what is needed to do
First, let see how data looks like in RAW mode (with
--raw
option). the database and table are respectivelyt
anddump3
You can see the field starting from "new line" (in the first row) is splitted into three lines due to new lines placed in the value.
--raw
option) - each record changed to the one-line texts by escaping characters like\
<tab>
andnew-lines
The clue is to save data in CSV format with escaped characters.
The way to do that is to convert special entities which
mysql --batch
produces (\t
as tabs\\
as backshlash and\n
as newline) into equivalent bytes for each value (field). Then whole value is escaped by"
and enclosed also by"
. Btw - using the same characters for escaping and enclosing gently simplifies output and processing, because you don't have two special characters. For this reason all you have to do with values (from csv format perspective) is to change"
to""
whithin values. In more common way (with escaping and enclosing respectively\
and"
) you would have to first change\
to\\
and then change"
into\"
.And the commands' explanation step by step:
How about using sed? It comes standard with most (all?) Linux OS.
sed 's/\t/<your_field_delimiter>/g'
.This example uses GNU sed (Linux). For POSIX sed (AIX/Solaris)I believe you would type a literal TAB instead of
\t
Example (for CSV output):
mysqldump
utility can help you, basically with--tab
option it's a wrapped forSELECT INTO OUTFILE
statement.Example:
This will create csv formatted file
/tmp/Country.txt
I wound up writing my own command-line tool to take care of this. It's similar to
cut
, except it knows what to do with quoted fields, etc. This tool, paired with @Jimothy's answer, allows me to get a headerless CSV from a remote MySQL server I have no filesystem access to onto my local machine with this command:csvmaster on github