Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run a query foreach databases (mysql)

Tags:

mysql

I'm looking for a straight way to run a query on all databases hosted on my mysql server.

I have a bunch of Magento installations and I want to truncate all Magento log table on all databases:

  • log_customer
  • log_visitor
  • log_visitor_info
  • log_url
  • log_url_info
  • log_quote
  • report_viewed_product_index
  • report_compared_product_index
  • report_event
  • catalog_compare_item

I think it something very easy to accomplish in mysql but I cannot find a straight answer/solution.

*UPDATE *
According to @Ollie Jones it is not possible to do it without a STORE PROCEDURE or a server side language ( PHP or whatever )

UPDATE 1
I choose to follow the PHP approach (@samitha) for 2 reasons:

  1. STORE PROCEDURE looks more complicated
  2. Query on 'information_schema' table is very slow ( at least if you have many DB/TABLES)
like image 200
WonderLand Avatar asked Dec 28 '13 17:12

WonderLand


People also ask

How do I search an entire database in MySQL?

Find data across a MySQL connection by using the text search feature on any number of tables and schemas. From the schema tree, select the tables, schemas, or both to search and then right-click the highlighted items and click Search Data Table from the context menu.

How can I see all MySQL databases in CMD?

To list all databases in MySQL, run the following command: mysql> show databases; This command will work for you no matter if you have an Ubuntu VPS or CentOS VPS. If you have other databases created in MySQL, they will be all listed here.

How can I see all tables in MySQL?

MySQL SHOW TABLES command example To use the SHOW TABLES command, you need to log on to the MySQL server first. On opening the MySQL Command Line Client, enter your password. Select the specific database. Run the SHOW TABLES command to see all the tables in the database that has been selected.


2 Answers

  SELECT DISTINCT SCHEMA_NAME AS `database`
    FROM information_schema.SCHEMATA
   WHERE  SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql')
   ORDER BY SCHEMA_NAME

gets you a list of all the non-MYSQL databases on your system.

  SELECT TABLE_SCHEMA AS `database`,
         TABLE_NAME AS `table`
    FROM information_schema.TABLES
   WHERE TABLE_TYPE = 'BASE TABLE'
   ORDER BY TABLE_SCHEMA, TABLE_NAME

gets you a list of all the actual tables (excluding SYSTEM VIEWs like the TABLES table, and user-defined views) in all the databases.

Then, you should implement logic in your program to ensure that, for each database, it really is a Magento database before you truncate certain tables. Otherwise, you might become a despised person among your co-workers. :-)

Edit

Here's a stored procedure.

You need to edit it to do exactly what you need it to do; in particular, it counts rows rather than truncating tables, and it doesn't contain the correct list of log tables. (It would be irresponsible for me to publish such a wildly destructive stored procedure; you should edit it yourself to do the destructive part.)

DELIMITER $$
DROP PROCEDURE IF EXISTS `zap_magento_logs`$$

CREATE PROCEDURE `zap_magento_logs`()
BEGIN

    -- declare variables for database and table names
    DECLARE dbname VARCHAR(128) DEFAULT '';
    DECLARE tbname VARCHAR(128) DEFAULT '';

    DECLARE done INTEGER DEFAULT 0;

    -- declare cursor for list of log tables
    DECLARE log_table_list CURSOR FOR 
      SELECT TABLE_SCHEMA AS `database`,
             TABLE_NAME AS `table`
        FROM `information_schema`.TABLES
       WHERE TABLE_TYPE = 'BASE TABLE'
         AND TABLE_NAME IN 
         (
            'log_customer',
        'log_visitor',
        'log_visitor_info',
        'log_url',
        'log_url_info',
        'log_quote'
         )
       ORDER BY TABLE_SCHEMA, TABLE_NAME;

    -- declare NOT FOUND handler
        DECLARE CONTINUE HANDLER 
        FOR NOT FOUND SET done = 1;

    OPEN log_table_list;

    log_table: LOOP

        FETCH log_table_list INTO dbname, tbname;

        IF done = 1 THEN
        LEAVE log_table;
        END IF;

        -- create an appropriate text string for a DDL or other SQL statement
        SET @s = CONCAT('SELECT COUNT(*) AS num FROM  ',dbname,'.',tbname);
        PREPARE stmt FROM @s;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt; 
    END LOOP    log_table;
    CLOSE log_table_list;

END$$

DELIMITER ;

You run this by issuing the SQL command

  CALL zap_magento_logs();
like image 52
O. Jones Avatar answered Oct 23 '22 13:10

O. Jones


A PHP approach would be:

$tables = array(
    'log_customer',
    'log_visitor',
    'log_visitor_info',
    'log_url',
    'log_url_info',
    'log_quote',
    'report_viewed_product_index',
    'report_compared_product_index',
    'report_event',
    'catalog_compare_item',
);

$dbh = new PDO('mysql:host=localhost;', 'USERNAME', 'PASSWORD', array(
    PDO::ATTR_PERSISTENT => true
));


$sql = $dbh->query('SHOW DATABASES');
$getAllDbs = $sql->fetchALL(PDO::FETCH_ASSOC);

foreach ($getAllDbs as $DB) {  

        foreach ($tables as $table) {
            $dbh->query('TRUNCATE TABLE ' . $DB['Database'] . '.' . $table);

    };
};
like image 6
underscore Avatar answered Oct 23 '22 13:10

underscore