MySQL INTO OUTFILE: Как переопределить существующий файл?
У меня есть большой SQL-скрипт, который создает CSV-файл. Я хочу настроить cron-задачу, которая будет выполняться каждую ночь, чтобы создавать свежий CSV-файл и делать его доступным на сайте.
К примеру, я сохраняю свой файл по пути '/home/sites/example.com/www/files/backup.csv'.
Мой SQL-запрос выглядит следующим образом:
SELECT * INTO OUTFILE '/home/sites/example.com/www/files/backup.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM ( ....
Однако MySQL выдаёт ошибку, если файл уже существует:
File '/home/sites/example.com/www/files/backup.csv' already exists
Существует ли способ заставить MySQL перезаписывать файл?
Я мог бы использовать PHP для проверки наличия файла и его удаления перед созданием нового, но было бы удобнее, если бы я мог сделать это непосредственно в MySQL.
5 ответ(ов)
Вопрос: Почему не использовать rm -f /home/sites/example.com/www/files/backup.csv
в скрипте, выполняемом через cron?
Ответ: Вы можете выполнить эту команду внутри MySQL, используя команду для перехода в оболочку: \!
. Например:
Mysql> \! rm -f /home/sites/example.com/www/files/backup.csv
Это позволяет избежать потенциальных проблем, связанных с выполнением команд оболочки напрямую в cron. В случае выполнения команд через MySQL, вы также можете сохранять логи и обрабатывать ошибки более эффективно.
Для такой задачи я бы поместил код в bash-скрипт и удалил файл:
#!/bin/bash
rm /path/to/backup.csv
./backup_sql_query.sh # Здесь находится скрипт для резервного копирования в формате CSV.
Однако лучшее решение — добавить метку времени к файлу. В наши дни дисковое пространство не так уж и дорого.
В вашем случае действительно нет другого способа использовать динамические SQL-запросы. Но вы можете создать хранимую процедуру, которая принимает имя файла в качестве параметра и выполняет динамический запрос. Вот пример:
CREATE PROCEDURE export_dynamic(IN file_name CHAR(64))
BEGIN
SET @myvar = CONCAT('SELECT * INTO OUTFILE "', file_name, '" FROM Table1');
PREPARE stmt1 FROM @myvar;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END;
Эта процедура создает SQL-запрос, который выбирает все данные из Table1
и экспортирует их в указанный файл. Не забудьте, что у пользователя, выполняющего эту процедуру, должны быть достаточные права для записи в файловую систему.
Вот перевод на русский в стиле ответа на StackOverflow.com:
3 шага для правильного выполнения резервного копирования
Ваше резервное копирование будет выполняться каждую ночь, пока вы спите (или нет).
ШАГ 1: Создайте хранимую процедуру для вашего SQL
CREATE PROCEDURE backupCSV()
SELECT * INTO OUTFILE '/home/sites/example.com/www/files/backup.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM ( ....
ШАГ 2: Создайте скрипт "/home/backupCSV.sh", чтобы удалить старый файл и вызвать хранимую процедуру
echo "$(date +"%Y-%m-%d %T") СТАРТ СКРИПТА ОБСЛУЖИВАНИЯ"
rm /home/sites/example.com/www/files/backup.csv
echo "$(date +"%Y-%m-%d %T") УСПЕШНО >> Старый файл удалён"
mysql --user=[user] --password=[password] [dataBaseName] --execute="CALL backupCSV();"
echo "$(date +"%Y-%m-%d %T") УСПЕШНО >> Новый файл создан"
echo "$(date +"%Y-%m-%d %T") КОНЕЦ СКРИПТА ОБСЛУЖИВАНИЯ"
ШАГ 3: Обновите Crontab для ежедневного выполнения скрипта
# m h dom mon dow user command
0 3 * * * root sh -x /home/backupCSV.sh
ШАГ 4 (по желанию): поблагодарите меня 😉
Теперь ваше резервное копирование будет выполняться автоматически каждый день. Не забудьте заменить [user]
, [password]
и [dataBaseName]
своими данными.
Вам нужно просто перейти в оболочку из MySQL и выполнить команду rm
для удаления файла перед тем, как вы попытаетесь его переписать. Например:
Mysql> \\! rm -f /home/sites/example.com/www/files/backup.csv
Обратите внимание, что использование команды rm
может удалить файл без возможности восстановления, поэтому будьте осторожны.
Как предотвратить SQL-инъекции в PHP?
SQL-инъекция, обхватывающая mysql_real_escape_string()
SQL: выбрать только строки с максимальным значением в столбце
Какой лучший порядок сортировки использовать для MySQL с PHP? [закрыто]
Удаление с использованием JOIN в MySQL