Удаление нескольких баз данных с именами, соответствующими шаблону

Я хочу, чтобы все базы данных начинались со слова.

abc
xyz
cms_db1
cms_db2
cms_xyz
pqr

В приведенном выше примере я хотел бы отбросить все базы данных со слова "cms". Я думаю, maatkit или shell script могут это сделать. Каков наилучший подход?

Ответ 1

Путь к Linux:

#!/bin/bash

DB_STARTS_WITH="cms"
MUSER="root"
MPWD="yourpass"
MYSQL="mysql"

DBS="$($MYSQL -u$MUSER -p$MPWD -Bse 'show databases')"
for db in $DBS; do

if [[ "$db" =~ "^${DB_STARTS_WITH}" ]]; then
    echo "Deleting $db"
    $MYSQL -u$MUSER -p$MPWD -Bse "drop database $db"
fi

done

Конечно, используйте drop часть на свой страх и риск;)

Ответ 2

Здесь чисто mySQL-решение в двух запросах:

SELECT CONCAT('DROP DATABASE `', SCHEMA_NAME, '`;')
FROM `information_schema`.`SCHEMATA`
WHERE SCHEMA_NAME LIKE 'cms_%';

Затем скопируйте и вставьте полученный набор записей и запустите

Ответ 3

Мне пришлось улучшать neurinos script из-за специальных символов в моем пароле, отсутствовала "drop DATABASE..." и не работало сравнение для выражения DB_STARTS_WITH. На сервере Ubuntu работало следующее script:

#!/bin/bash

DB_STARTS_WITH="grp"
MUSER="root"
MPWD="YOUR_PASSWORD"
MYSQL="mysql"

DBS="$($MYSQL -u $MUSER -p"$MPWD" -Bse 'show databases')"
for db in $DBS; do

if [[ "$db" == $DB_STARTS_WITH* ]]; then
    echo "Deleting $db"
    $MYSQL -u $MUSER -p"$MPWD" -Bse "drop database $db"
fi

done

Ответ 4

Я бы использовал что-то вроде:

echo "SHOW DATABASES LIKE 'cms_%'" \
  | mysql \
  | tail -n +2 \
  | xargs -n1 mysqladmin -f drop

Если у вас нет имени пользователя и пароля по умолчанию, установленного внутри ~/my.cnf, вам может потребоваться указать имя пользователя и пароль с помощью переключателей -u и -p для команд mysql/mysqladmin выше.

(Edit - добавлено -n arg to tail.)

Ответ 5

Если вы хотите полностью оставаться в пределах MySQL/MariaDB (т.е. без использования сценариев bash и т.д.), вы можете сделать следующее:

DELIMITER //
CREATE PROCEDURE clean()
BEGIN
    SET @query := (SELECT CONCAT('DROP DATABASE ', SCHEMA_NAME, ';') FROM `information_schema`.`SCHEMATA` WHERE SCHEMA_NAME LIKE 'dbtVDB%' LIMIT 1);
    WHILE @query != '' DO
        PREPARE stmt FROM @query;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
        SET @query := (SELECT CONCAT('DROP DATABASE ', SCHEMA_NAME, ';') FROM `information_schema`.`SCHEMATA` WHERE SCHEMA_NAME LIKE 'cms%' LIMIT 1);
    END WHILE;
    DELETE FROM mysql.db WHERE mysql.db.Db LIKE 'cms%';
END;
//
DELIMITER ;
CALL clean();
DROP PROCEDURE clean;

Ответ 6

Способ Linux:

for db_name in $(mysql -u USER -pPASS -e "show databases like 'cms_%'" -ss)
do
     mysql -u USER -pPASS -e "drop database ${db_name}";
done

Ответ 7

Мне понравился ответ, предлагающий цикл "for" из оболочки. В моем случае у меня были имена подкаталогов, соответствующие моим именам базы данных, поэтому я сделал массивы, а затем использовал их в команде.

(Я мог бы сделать это, используя каталог данных mysql, чтобы подумать об этом, даже если бы у меня не было настроек, которые у меня были. На моем bitnami VM это /Опт/BitNami/MySQL/данные).

  • созданный массив из подмножества файлов: tbtdirs = (tbt * 2015 *)

  • Протестировать потенциально жуковую команду сначала w/ "echo": для d в ${tbtdirs [@]}; do echo mysql -pPASS -e "удалить базу данных $d"; сделано

  • опустил все базы данных в массиве: для d в ${tbtdirs [@]}; do mysql -pPASS -e "удалить базу данных $d"; сделано

Работал как шарм! Также был изменен цикл для удаления подкаталогов. Я довольно долго использовал командную строку Linux, прежде чем узнал, насколько полезны команды bash.

Ответ 8

Используя @léo-alves-de-araujo, я изменил его, чтобы спросить пользователя/пароль (более безопасный путь) из командной строки (с помощью linux)

#!/bin/bash 
echo -n "Enter Mysql User:"
read user
echo -n "Enter Mysql Password:"
read -s password
for db_name in $(mysql -u $user --password=$password -e "SHOW DATABASES LIKE 'cms_%'" -ss 2>/dev/null)
do
        mysql -u $user --password=$password -e "DROP DATABASE ${db_name}" 2>/dev/null;
done

Ответ 9

Улучшено решение @neurino, чтобы избежать хранения учетных данных MySQL в script и передачи их через командную строку (возможно, она будет видна в списке процессов)

#!/bin/bash

DB_STARTS_WITH="cms"
MYSQL="mysql"

read -p "Enter MySQL user name: " MYSQL_USER
read -s -p "Enter password: " MYSQL_PASSWORD

CREDENTIALS_FILE="$(mktemp)"
chmod 600 $CREDENTIALS_FILE
cat > $CREDENTIALS_FILE <<- EOM
[client]
user=$MYSQL_USER
password=$MYSQL_PASSWORD
EOM

trap "{ rm -f $CREDENTIALS_FILE; }" EXIT

DATABASES="$(echo "show databases;" | $MYSQL --defaults-file=$CREDENTIALS_FILE)"

for DATABASE in $DATABASES; do
    if [[ $DATABASE =~ ^${DB_STARTS_WITH} ]]; then
        echo Removing $DATABASE...
        echo "drop database $DATABASE" | $MYSQL --defaults-file=$CREDENTIALS_FILE
    fi
done

Ответ 10

Импровизация на превосходном ответе @cloakedninjas, для облегчения поиска всех запросов для выполнения в одной строке.

Во-первых, вы можете установить максимальное значение для group_concat_max_len на максимально возможное значение для этого конкретного сеанса:

SET SESSION group_concat_max_len = @@max_allowed_packet;

Теперь вы можете подготовить строку запроса (выполнить позже), используя SQL. Используя information_schema, мы можем получить имя всех баз данных, соответствующих шаблону. Теперь используйте Concat() для подготовки одного запроса DROP DATABASE .., а затем используйте Group_Concat(), чтобы объединить их все в одну строку, чтобы упростить поиск.

SELECT GROUP_CONCAT(CONCAT('DROP DATABASE '', SCHEMA_NAME, '';') 
                    SEPARATOR ' ') AS query_to_execute
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME LIKE 'cms_%'

Теперь скопируйте строку в query_to_execute и запустите ее отдельно.