94

Any ideas?

SELECT * INTO OUTFILE '/home/myacnt/docs/mysqlCSVtest.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '*'
LINES TERMINATED BY '\n'
FROM tbl_property 
WHERE managerGroupID = {$managerGroupID}

Error:

Access denied for user 'asdfsdf'@'localhost' (using password: YES)
OMG Ponies
  • 325,700
  • 82
  • 523
  • 502
Shackrock
  • 4,601
  • 10
  • 48
  • 74
  • 4
    "ALL PRIVILEGES" does not include all privileges. Relevant to this case, it does not include the `FILE` privilege, which is needed for `SELECT INTO OUTFILE` statements. I've had several troubles with this mismatch between the English and the MySQL: http://dba.stackexchange.com/a/96894/53784 – WAF Feb 27 '17 at 15:39
  • If you then run into "The MySQL server is running with the --secure-file-priv option so it cannot execute this statement" take a look here: https://stackoverflow.com/questions/32737478/how-should-i-tackle-secure-file-priv-in-mysql – sneaky Nov 30 '18 at 07:04

6 Answers6

133

Try executing this SQL command:

> grant all privileges 
  on YOUR_DATABASE.* 
  to 'asdfsdf'@'localhost' 
  identified by 'your_password';
> flush privileges; 

It seems that you are having issues with connecting to the database and not writing to the folder you’re mentioning.

Also, make sure you have granted FILE to user 'asdfsdf'@'localhost'.

> GRANT FILE ON *.* TO 'asdfsdf'@'localhost';
Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
Pablo Santa Cruz
  • 176,835
  • 32
  • 241
  • 292
  • Everything looks good with that, even in cpanel EVERYTHING is checked – Shackrock May 22 '11 at 23:38
  • 2
    @Shackrock: check out updated answer. Make sure you've granted `FILE` to the user. – Pablo Santa Cruz May 22 '11 at 23:41
  • 50
    There are two issues here. 1) GRANT ALL does not do GRANT FILE. 2) GRANT FILE only works with \*.\* (i.e. globally). Both are bugs in MySQL. – fijiaaron Sep 27 '12 at 12:14
  • 4
    FYI, think carefully before doing this is you aren't the db admin. Mine was not pleased to find I'd changed the privileges ("Nooooooo!"). :-) – Ellen Spertus Jun 21 '14 at 16:30
  • 1
    Seems like it also has issues writing to locations in the filesystem other than /var/lib/mysql, which seems contrary to the documentation. Even when the target folder is owned by mysql:mysql and everyone has rwx permissions and/or is called using sudo... (coming from Ubuntu here) – quickthyme Jan 30 '15 at 17:39
  • This worked fro me https://dev.mysql.com/doc/refman/5.5/en/cannot-create.html starting service with a directory tmpdir=c:\temp – vsingh Dec 30 '15 at 20:19
  • 2
    You don't need to use `FLUSH PRIVILEGES` after `GRANT`. That's only needed if you modify the privileges table with SQL instead of using `GRANT`. – Barmar Oct 26 '17 at 21:34
  • 1
    Didn't work for me until I restarted mysql server (MariaDB) – 6opko Feb 18 '19 at 20:50
71

Honestly I didnt bother to deal with the grants and this worked even without the privileges:

echo "select * from employee" | mysql --host=HOST --port=PORT --user=UserName --password=Password DATABASE.SCHEMA > output.txt
Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
user1028904
  • 7,450
  • 1
  • 16
  • 7
  • 7
    That's because you're just doing a regular SELECT, not a SELECT INTO OUTFILE (a .csv file in this case). – aqn Jun 18 '13 at 13:41
  • 6
    This is a bad way to do it for larger tables because the client buffers the entire result set before it puts anything out to the file. – Chris Seline Feb 06 '14 at 15:58
  • 8
    MySQL will tab delimit the file using this method, which is perfect. After trying a dozen file permissions, MySQL settings, and various grants, all spanning 5 or 6 different help pages, this worked. Save yourself the headache and use this. – Paul Kenjora Aug 14 '15 at 17:40
  • Don't forget to switch to the appropriate codepage before using this method, e.g. "chcp 1252" or "chcp 65001" if there are special characters in the exported data. – trapper_hag Jan 18 '16 at 12:14
  • Another issue with this is escaping of NULLs. Using INFILE from the output of this command will result in the string literal "NULL" being imported rather than an actual NULL, which is escaped using \N. – bluefear Mar 24 '16 at 00:20
  • I agree with Paul K. Nothing else worked except this answer. Thanks. It inspired my answer here: https://dba.stackexchange.com/a/245383/18098 – Ryan Aug 15 '19 at 00:12
  • 1
    This is the most practical answer so far, others are so dependent on privileges that not everyone has control over – Ahmad Khundaqji Sep 02 '21 at 10:43
25

As @fijaaron says,

  1. GRANT ALL does not imply GRANT FILE
  2. GRANT FILE only works with *.*

So do

GRANT FILE ON *.* TO user;
7ochem
  • 2,183
  • 1
  • 34
  • 42
e18r
  • 7,578
  • 4
  • 45
  • 40
6

Since cP/WHM took away the ability to modify User privileges as root in PHPMyAdmin, you have to use the command line to:

mysql>  GRANT FILE ON *.* TO 'user'@'localhost';

Step 2 is to allow that user to dump a file in a specific folder. There are a few ways to do this but I ended up putting a folder in :

/home/user/tmp/db

and

chown mysql:mysql /home/user/tmp/db

That allows the mysql user to write the file. As previous posters have said, you can use the MySQL temp folder too, I don't suppose it really matters but you definitely don't want to make it 0777 permission (world-writeable) unless you want the world to see your data. There is a potential problem if you want to rinse-repeat the process as INTO OUTFILE won't work if the file exists. If your files are owned by a different user then just trying to unlink($file) won't work. If you're like me (paranoid about 0777) then you can set your target directory using:

chmod($dir,0777)

just prior to doing the SQL command, then

chmod($dir,0755)

immediately after, followed by unlink(file) to delete the file. This keeps it all running under your web user and no need to invoke the mysql user.

Grindlay
  • 571
  • 5
  • 8
3

I tried all the solutions but it still wasn't sufficient. After some more digging I eventually found I had also to set the 'file_priv' flag, and restart mysql.

To resume :

Grant the privileges :

> GRANT ALL PRIVILEGES
  ON my_database.* 
  to 'my_user'@'localhost';

> GRANT FILE ON *.* TO my_user;

> FLUSH PRIVILEGES; 

Set the flag :

> UPDATE mysql.user SET File_priv = 'Y' WHERE user='my_user' AND host='localhost';

Finally restart the mysql server:

$ sudo service mysql restart

After that, I could write into the secure_file_priv directory. For me it was /var/lib/mysql-files/, but you can check it with the following command :

> SHOW VARIABLES LIKE "secure_file_priv";
Eino Gourdin
  • 4,169
  • 3
  • 39
  • 67
3

For future readers, one easy way is as follows if they wish to export in bulk using bash,

akshay@ideapad:/tmp$ mysql -u someuser -p test -e "select * from offices"
Enter password: 
+------------+---------------+------------------+--------------------------+--------------+------------+-----------+------------+-----------+
| officeCode | city          | phone            | addressLine1             | addressLine2 | state      | country   | postalCode | territory |
+------------+---------------+------------------+--------------------------+--------------+------------+-----------+------------+-----------+
| 1          | San Francisco | +1 650 219 4782  | 100 Market Street        | Suite 300    | CA         | USA       | 94080      | NA        |
| 2          | Boston        | +1 215 837 0825  | 1550 Court Place         | Suite 102    | MA         | USA       | 02107      | NA        |
| 3          | NYC           | +1 212 555 3000  | 523 East 53rd Street     | apt. 5A      | NY         | USA       | 10022      | NA        |
| 4          | Paris         | +33 14 723 4404  | 43 Rue Jouffroy D'abbans | NULL         | NULL       | France    | 75017      | EMEA      |
| 5          | Tokyo         | +81 33 224 5000  | 4-1 Kioicho              | NULL         | Chiyoda-Ku | Japan     | 102-8578   | Japan     |
| 6          | Sydney        | +61 2 9264 2451  | 5-11 Wentworth Avenue    | Floor #2     | NULL       | Australia | NSW 2010   | APAC      |
| 7          | London        | +44 20 7877 2041 | 25 Old Broad Street      | Level 7      | NULL       | UK        | EC2N 1HN   | EMEA      |
+------------+---------------+------------------+--------------------------+--------------+------------+-----------+------------+-----------+

If you're exporting by non-root user then set permission like below

root@ideapad:/tmp# mysql -u root -p
MariaDB[(none)]> UPDATE mysql.user SET File_priv = 'Y' WHERE user='someuser' AND host='localhost';

Restart or Reload mysqld

akshay@ideapad:/tmp$ sudo su
root@ideapad:/tmp#  systemctl restart mariadb

Sample code snippet

akshay@ideapad:/tmp$ cat test.sh 
#!/usr/bin/env bash

user="someuser"
password="password"
database="test"

mysql -u"$user" -p"$password" "$database" <<EOF
SELECT * 
INTO OUTFILE '/tmp/csvs/offices.csv' 
FIELDS TERMINATED BY '|' 
ENCLOSED BY '"' 
LINES TERMINATED BY '\n'
FROM offices;
EOF

Execute

akshay@ideapad:/tmp$ mkdir -p /tmp/csvs
akshay@ideapad:/tmp$ chmod +x test.sh
akshay@ideapad:/tmp$ ./test.sh 
akshay@ideapad:/tmp$ cat /tmp/csvs/offices.csv 
"1"|"San Francisco"|"+1 650 219 4782"|"100 Market Street"|"Suite 300"|"CA"|"USA"|"94080"|"NA"
"2"|"Boston"|"+1 215 837 0825"|"1550 Court Place"|"Suite 102"|"MA"|"USA"|"02107"|"NA"
"3"|"NYC"|"+1 212 555 3000"|"523 East 53rd Street"|"apt. 5A"|"NY"|"USA"|"10022"|"NA"
"4"|"Paris"|"+33 14 723 4404"|"43 Rue Jouffroy D'abbans"|\N|\N|"France"|"75017"|"EMEA"
"5"|"Tokyo"|"+81 33 224 5000"|"4-1 Kioicho"|\N|"Chiyoda-Ku"|"Japan"|"102-8578"|"Japan"
"6"|"Sydney"|"+61 2 9264 2451"|"5-11 Wentworth Avenue"|"Floor #2"|\N|"Australia"|"NSW 2010"|"APAC"
"7"|"London"|"+44 20 7877 2041"|"25 Old Broad Street"|"Level 7"|\N|"UK"|"EC2N 1HN"|"EMEA"

Akshay Hegde
  • 16,536
  • 2
  • 22
  • 36