0

This line:

use test; SELECT `xyflagged`.`Article number`, `xyflagged`.`Flag` INTO outfile 'Test1618' fields terminated by ',' ENCLOSED BY '\"' lines terminated by '\n' FROM xyflagged;

However, this works:

"use test; SELECT * INTO outfile 'Test1618' fields terminated by ',' ENCLOSED BY '\"' lines terminated by '\n' FROM xyflagged;

I've looked at several solutions on SO, such as this and this and several more about escaping strings. Obviously, it has something to do with the space in the column name (I don't have control over that). So I tried various combinations:

use test; SELECT `xyflagged`.`Article number`, `xyflagged`.`Flag` INTO outfile 'Test1618' fields terminated by ',' ENCLOSED BY '\"' lines terminated by '\n' FROM xyflagged;

use test; SELECT `Article number`, `Flag` INTO outfile 'Test1618' fields terminated by ',' ENCLOSED BY '\"' lines terminated by '\n' FROM xyflagged;

use test; SELECT [xyflagged].[Article number], [xyflagged].[Flag] INTO outfile 'Test1618' fields terminated by ',' ENCLOSED BY '\"' lines terminated by '\n' FROM xyflagged;

as suggested by the various answers and the brackets especially appear to have worked for some but not for me.

I've tried it like this:

mysql -u me -paaaaaaaaaaaaaaa -e "use test; SELECT `xyflagged`.`Article number`, `xyflagged`.`Flag` INTO outfile 'Test1618' fields terminated by ',' ENCLOSED BY '\"' lines terminated by '\n' FROM xyflagged";

and also like this:

mysql -u me -paaaaaaaaaaaaaaa << EOF
use test; SELECT `xyflagged`.`Article number`, `xyflagged`.`Flag` INTO outfile 'Test1618' fields terminated by ',' ENCLOSED BY '\"' lines terminated by '\n' FROM xyflagged;
EOF

The error is always:

ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ' INTO outfile 'Test1618' fields terminated by ...' at line 1

Maybe it is something basic or obvious, but I think I've tried every combination and I can't make it work.

The other suggested questions/answers that marked this as a duplicate do not address my question. The first one is very general (and ofcourse useful), and already addressed by the first answer. The second one doesn't take into account the variable in the SQL command as noted in my longish comment. Also, the answer is the only complete answer I have found and very different from any other answer I have come across (yet).

0

1 Answer 1

5

Bash will perform interpolation on any double-quoted string. backticks signify command substitution in this context. So the following doesn't work because bash attempts to run xyflaged and replace it with the output of the command.

mysql -u me -paaaaaaaaaaaaaaa -e "use test; SELECT
`xyflagged`.`Article number`, `xyflagged`.`Flag` INTO outfile
'Test1618' fields terminated by ',' ENCLOSED BY '\"' lines terminated
by '\n' FROM xyflagged";

Single quoted strings are not subject to interpolation. But, single quotes are also strange in bash because they disable all special characters. That means you can't escape a single quote with a backslash in a single quoted string becuase the backslash is not special; '\'' is not a valid bash expression.

His next one is called a "heredoc". It has the same problem of string interpolation.

mysql -u me -paaaaaaaaaaaaaaa << EOF
use test; SELECT `xyflagged`.`Article number`, `xyflagged`.`Flag` INTO outfile 'Test1618' fields terminated by ',' ENCLOSED BY '\"' lines terminated by '\n' FROM xyflagged;
EOF

But, if you put the heredoc end-of-file delineator (EOF here) within single quotes, it will disable special characters in the heredoc. This works better because since you're not enquoting the stiring in single quotes, they don't have special significance to bash:

mysql -u me -paaaaaaaaaaaaaaa << 'EOF'
use test; SELECT `xyflagged`.`Article number`, `xyflagged`.`Flag` INTO outfile 'Test1618' fields terminated by ',' ENCLOSED BY '\"' lines terminated by '\n' FROM xyflagged;
EOF

Or, you can provide the input in a file (the name / extension is irrelevant) and bash will provide that files' contents to the standard input of the program:

mysql -u me -paaaaaaaaaaaaaaa < my-commands.sql

I prefer this last invocation because if you give it a sane extension (like .sql in this case) most editors are smart enough to do syntax highlighting on the file which makes it easier to edit.

Here's an exmaple of how that might work. Given the file cmd.sql:

$ cat cmd.sql
use test;
select * 
INTO outfile '/var/lib/mysql-files/Test1618' 
fields terminated by ',' 
ENCLOSED BY '"' 
lines terminated by '\n' 
FROM test;

And a table something like this:

CREATE TABLE `test` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` text,
  PRIMARY KEY (`id`)
);
INSERT INTO `test` VALUES (1,'erik258'),(2,'nbk'),(3,'Chiwda');

You can invoke something like this:

mysql < cmd.sql

And the result will be at the specified OUTFILE:

$ cat /var/lib/mysql-files/Test1618
"1","erik258"
"2","nbk"
"3","Chiwda"

Edit: Dynamic filename.

INTO OUTFILE doesn't have good support for variable filenames in itself. So it makes sense to replace the filename externally.

In bash, an easy way to replace content is sed.

If the command contains a replacement __DATE__:

select *
INTO outfile '/var/lib/mysql-files/test__DATE__.csv'
fields terminated by ','
ENCLOSED BY '"'
lines terminated by '\n'
FROM test;

You can use sed to replace DATE before you feed it to mysql:

sed -e "s:__DATE__:$(date +%Y-%m-%d):" cmd.sql  | mysql test

Now bash creates a pipe from sed's output to mysql's input. sed uses the filename cmd.sql as a source of input, and modifies it with the replacement expression before it is output.

Now file should exit in its expected location:

$ ls /var/lib/mysql-files
test2024-03-16.csv
Sign up to request clarification or add additional context in comments.

7 Comments

your last command makes no sense, as he want to make a csv file
I don't get your point @nbk. There's no connection between the source of the command's input and what the command does. You can provide commands to mysql from one file, which tell mysql to write a different file. See example for proof of concept.
now it is clearer what you mean
Wow! Really good explanations and I learned lots of new things. I should have added in my question that none of these solutions work (at least out of the box) because I am not really using a static filename (but I left that out so as not to confuse the issue). So instead of 'Test1618' it is really '$FILENAME' which is constructed from a fixed string and today's date. Which means both your solutions break, I think? I can probably figure out a way to write the .sql on the fly and then read it in, but I wonder if there is a cleaner solution...
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.