100

I need to dump all tables in MySQL in CSV format.

Is there a command using mysqldump to just output every row for every table in CSV format?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ken
  • 2,849
  • 8
  • 24
  • 23
  • 1
    You can do it using `mysql.exe` program, try SELECT * FROM table INTO OUTFILE 'file_name'. But you should specify each table manually. – Devart Aug 20 '12 at 15:51

7 Answers7

148

First, I can give you the answer for one table:

The trouble with all these INTO OUTFILE or --tab=tmpfile (and -T/path/to/directory) answers is that it requires running mysqldump on the same server as the MySQL server, and having those access rights.

My solution was simply to use mysql (not mysqldump) with the -B parameter, inline the SELECT statement with -e, then massage the ASCII output with sed, and wind up with CSV including a header field row:

Example:

 mysql -B -u username -p password database -h dbhost -e "SELECT * FROM accounts;" \
 | sed "s/\"/\"\"/g;s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g"

"id","login","password","folder","email" "8","mariana","xxxxxxxxxx","mariana","" "3","squaredesign","xxxxxxxxxxxxxxxxx","squaredesign","mkobylecki@squaredesign.com" "4","miedziak","xxxxxxxxxx","miedziak","miedziak@mail.com" "5","Sarko","xxxxxxxxx","Sarko","" "6","Logitrans Poland","xxxxxxxxxxxxxx","LogitransPoland","" "7","Amos","xxxxxxxxxxxxxxxxxxxx","Amos","" "9","Annabelle","xxxxxxxxxxxxxxxx","Annabelle","" "11","Brandfathers and Sons","xxxxxxxxxxxxxxxxx","BrandfathersAndSons","" "12","Imagine Group","xxxxxxxxxxxxxxxx","ImagineGroup","" "13","EduSquare.pl","xxxxxxxxxxxxxxxxx","EduSquare.pl","" "101","tmp","xxxxxxxxxxxxxxxxxxxxx","_","WOBC-14.squaredesign.atlassian.net@yoMama.com"

Add a > outfile.csv at the end of that one-liner, to get your CSV file for that table.

Next, get a list of all your tables with

mysql -u username -ppassword dbname -sN -e "SHOW TABLES;"

From there, it's only one more step to make a loop, for example, in the Bash shell to iterate over those tables:

 for tb in $(mysql -u username -ppassword dbname -sN -e "SHOW TABLES;"); do
     echo .....;
 done

Between the do and ; done insert the long command I wrote in Part 1 above, but substitute your tablename with $tb instead.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Marcos
  • 4,796
  • 5
  • 40
  • 64
  • Since you need to specify columns with some joins and where clauses, This answer is better to accept. – shgnInc Nov 24 '14 at 04:14
  • 2
    This fails if the query results exceed memory on the machine you're dumping to. Any work arounds? – T. Brian Jones May 15 '15 at 19:20
  • @T.BrianJones Recommend you try a new question with details of your situation...which sounds very general to any program, btw. You probably weren't looking for the obvious "increase RAM" or "try another PC with more memory." Because yes, generally programs processing and outputting data need to fit that into memory first. In my loop, at least, each `mysql` exits and frees resources before starting the next table in the list. – Marcos May 17 '15 at 19:37
  • @T.BrianJones can you select into outfile, transfer the file, then work on it from there? It should not be hard to get this into line-at-a-time processing which should use only trivial amounts of memory. – msouth Jun 26 '15 at 20:44
  • 2
    This doesn't seem to take into account STRING column types that have double quotes in them -- they should be escaped, otherwise it's broken. Any idea how to do that? – timetofly Jul 15 '15 at 16:05
  • 2
    @Blossoming_Flower : Here is the updated regex to escape double quotes : `| sed "s/\"/\"\"/;s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g"` ([Properly escape a double quote in CSV](http://stackoverflow.com/questions/17808511/properly-escape-a-double-quote-in-csv)) – OlivierLarue Jan 07 '16 at 20:24
  • @Olivier If I want to use this inside a command that's already surrounded by `"`, how could I re-write this? I'm getting confused with all the escaping – Brian Glaz Aug 16 '16 at 19:45
  • -1: Regex looks entirely ad-hoc and not well thought out: Inconsistencies in trailing `g` on `s//` are senseless. They should ALL specify `g`, otherwise what's the point--*every occurrence* should be escaped and not just the first. `s/\n//g` why? [`sed` by default doesn't even include `\n` in the pattern buffer](https://unix.stackexchange.com/questions/26284/how-can-i-use-sed-to-replace-a-multi-line-string/235016). – antak Nov 07 '17 at 04:54
  • 1
    @Olivier , @Blossoming_Flower: maybe `| sed "s/\"/\"\"/g;s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g"` , add g option to double every " in the input? Ruby CSV expects such a convention. – kostas Jun 17 '18 at 19:20
  • 4
    Here is the sed without the quotes: sed "s/'//;s/\t/,/g;s/\n//g" – elegant dice Feb 14 '19 at 23:18
  • @BrianGlaz I would consider embedding it all in your language's HERE-DOC with variables where needed, rather than attempting to re-escape that confusing yarn ball. Ruby is pretty intuitive & friendly. – Marcos May 22 '19 at 13:03
  • i get this warning when i try to load this csv to my MySQL DB Warning: Incorrect integer value: '"1921196975"' for column 'id' at row 1 , it seems that it add " quotes to every values how to get rid of it ? – Omer Anisfeld Oct 23 '19 at 12:16
  • 1
    is there a way of doing so with mysqldump ? since large tables dump requires large RAM in MySQL while mysqldump has quick mode to retrieve row by row – Omer Anisfeld Oct 24 '19 at 06:07
  • This strikes me as a terrible idea because it's doing the escaping at the wrong end. It seems much safer (though more verbose) to `SELECT CONCAT('"',REPLACE(field,'"','""'),'",')` each field. And you'd probably need to wrap nullable fields in an `IF(field IS NULL,...,...) `, too. – Walf May 15 '23 at 02:26
37

This command will create two files in /path/to/directory table_name.sql and table_name.txt.

The SQL file will contain the table creation schema and the txt file will contain the records of the mytable table with fields delimited by a comma.

mysqldump -u username -p -t  -T/path/to/directory dbname table_name --fields-terminated-by=','
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Armance
  • 5,350
  • 14
  • 57
  • 80
  • 5
    Remember to use -T/path to something which is writable by the mysql process. – Mayank Jain May 15 '13 at 09:35
  • 13
    only works if you are running mysqldump from the same machine as the db server – Jake Jun 12 '14 at 17:35
  • 3
    if you run into mysql's secure file priv issues, do `SHOW VARIABLES LIKE "secure_file_priv";` and use the folder you are told there as the output folder in your `mysqldump` command, if yo u cannot restart the mysql server. – sjas Jan 24 '17 at 06:39
24

mysqldump has options for CSV formatting:

--fields-terminated-by=name
                  Fields in the output file are terminated by the given
--lines-terminated-by=name
                  Lines in the output file are terminated by the given

The name should contain one of the following:

`--fields-terminated-by`

\t or "\""

`--fields-enclosed-by=name`
   Fields in the output file are enclosed by the given

and

--lines-terminated-by

  • \r
  • \n
  • \r\n

Naturally you should mysqldump each table individually.

I suggest you gather all table names in a text file. Then, iterate through all tables running mysqldump. Here is a script that will dump and gzip 10 tables at a time:

MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
SQLSTMT="SELECT CONCAT(table_schema,'.',table_name)"
SQLSTMT="${SQLSTMT} FROM information_schema.tables WHERE table_schema NOT IN "
SQLSTMT="${SQLSTMT} ('information_schema','performance_schema','mysql')"
mysql ${MYSQL_CONN} -ANe"${SQLSTMT}" > /tmp/DBTB.txt
COMMIT_COUNT=0
COMMIT_LIMIT=10
TARGET_FOLDER=/path/to/csv/files
for DBTB in `cat /tmp/DBTB.txt`
do
    DB=`echo "${DBTB}" | sed 's/\./ /g' | awk '{print $1}'`
    TB=`echo "${DBTB}" | sed 's/\./ /g' | awk '{print $2}'`
    DUMPFILE=${DB}-${TB}.csv.gz
    mysqldump ${MYSQL_CONN} -T ${TARGET_FOLDER} --fields-terminated-by="," --fields-enclosed-by="\"" --lines-terminated-by="\r\n" ${DB} ${TB} | gzip > ${DUMPFILE}
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
RolandoMySQLDBA
  • 43,883
  • 16
  • 91
  • 132
23

If you are using MySQL or MariaDB, the easiest and performant way dump CSV for single table is -

SELECT customer_id, firstname, surname INTO OUTFILE '/exportdata/customers.txt'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM customers;

Now you can use other techniques to repeat this command for multiple tables. See more details here:

Anis
  • 3,349
  • 1
  • 21
  • 16
11

This worked well for me:

mysqldump <DBNAME> --fields-terminated-by ',' \
--fields-enclosed-by '"' --fields-escaped-by '\' \
--no-create-info --tab /var/lib/mysql-files/

Or if you want to only dump a specific table:

mysqldump <DBNAME> <TABLENAME> --fields-terminated-by ',' \
--fields-enclosed-by '"' --fields-escaped-by '\' \
--no-create-info --tab /var/lib/mysql-files/

I'm dumping to /var/lib/mysql-files/ to avoid this error:

mysqldump: Got error: 1290: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement when executing 'SELECT INTO OUTFILE'

Sumit
  • 2,189
  • 7
  • 32
  • 50
the
  • 21,007
  • 11
  • 68
  • 101
9

It looks like others had this problem also, and there is a simple Python script now, for converting output of mysqldump into CSV files.

wget https://raw.githubusercontent.com/jamesmishra/mysqldump-to-csv/master/mysqldump_to_csv.py
mysqldump -u username -p --host=rdshostname database table | python mysqldump_to_csv.py > table.csv
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vajk Hermecz
  • 5,413
  • 2
  • 34
  • 25
  • Heads up, mysqldump-to-csv turned out to contain some bugs in its simple code. So be prepared to bugfix it, or stay with a slower but stable solution... – Vajk Hermecz Feb 26 '15 at 16:21
0

You also can do it using Data Export tool in dbForge Studio for MySQL.

It will allow you to select some or all tables and export them into CSV format.

Devart
  • 119,203
  • 23
  • 166
  • 186