Running the same query on multiple databases in one query (MySQL) - mysql

I have multiple databases with the same structure but different unrelated names, and I want to run this query on all of them:
SELECT FROM <dbname>.`cms_users` WHERE `email` LIKE '%admin.something%'
I searched a bit in the information_schema and found a table called SCHEMATA that contains the databases' names which is ultimately what I need to run the query above and I can do so manually by just replacing the database name myself and creating the query. However I want to do it automatically using a mysql loop but I'm not very certain how can I do this and how can I concatenate the database name to the query and run it.
My pseudo code for this would be as follows:
array dbnames= select `SCHEMA_NAME` from `information_schema`.`SCHEMATA`;
loop start on dbnames
SELECT FROM dbnames[index].`cms_users` WHERE `email` LIKE '%admin.bilsi%';
loop end
Any help to put this or a better logic into mysql syntax? Thanks.

SQL Server and other RDBMS products allow you do scripting in the console. You can use anything you can use in stored procedures. MySQL is unfortunately much more limited and does not allow flow control constructs outside of stored procedures and functions. That means no loops, no if-statements, no cursors. You can use variables, but only the ones that start with #.
Furthermore, if you do a loop, you'll be sending multiple result-sets back to the client. If you're just running queries from a console, this is fine. If the results are something you intend for a program to use, this may not be desirable (it may not be desirable in either case).
If you are doing this in a one-off sort of way, get a list of databases manually, and then use copy and paste to build a query using UNION ALL, like so:
SELECT FROM `first_db`.`cms_users` WHERE `email` LIKE '%admin.bilsi%'
UNION ALL
SELECT FROM `second_db`.`cms_users` WHERE `email` LIKE '%admin.bilsi%'
UNION ALL
SELECT FROM `third_db`.`cms_users` WHERE `email` LIKE '%admin.bilsi%';
If you expect the number of databases to be changing and you don't want to have to update your query, or you are sending it from a program, you can use dynamic SQL. This means building a query in a string variable and then submitting it using MySQL's prepared statement functionality.
On the console, you can use something like this (see: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html):
SELECT GROUP_CONCAT(CONCAT("SELECT FROM `", SCHEMA_NAME, "`.`cms_users` WHERE `email` LIKE '%admin.bilsi%'") SEPARATOR ' UNION ALL ')
INTO #stmt_sql
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME NOT IN('mysql', 'test', 'tmp', 'information_schema', 'sys', 'performance_schema');
PREPARE stmt FROM #stmt_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
This generates the query I showed above using information from the INFORMATION_SCHEMA pseudo-database, namely, the list of databases by name (which MySQL incorrectly calls schemas). The rest is just the boilerplate code needed to prepare and execute a prepared statement, as per the linked documentation.
There are other ways, but they are even more tedious and won't buy you much.

Related

Does latest Mysql and Postgres prepare every query automatically?

I come across this in sqlx docs:
On most databases, statements will actually be prepared behind the scenes whenever a query is executed. However, you may also explicitly prepare statements for reuse elsewhere with sqlx.DB.Prepare():
Although I can't find proof that databases actually prepare every query.
So is it true, should I use prepare manually?
MySQL and PostgreSQL definitely don't prepare every query. You can execute queries directly, without doing a prepare & execute sequence.
The Go code in the sqlx driver probably does this, but it's elective, done to make it simpler to code the Go interface when you pass args.
You don't need to use the Prepare() func manually, unless you want to reuse the prepared query, executing it multiple times with different args.

USE statemet does not work in phpMyAdmin

I use SQL tab in phpMyAdmin to test statements, but some queries does not work, like, USE query; But, for example, after running USE statement and then using USE DATABASE() to check, null value returned.
USE dbname;
USE dbname
USE `dbname`;
I want to be able to run SQL statements on specific database; and this is possible after selecting (after using USE statement) database. I can click on the database name on the left sidebar and then run SQL statements, I know; But why is not possible to use "USE" statement to select database directly?
The USE statement doesn't return anything. This is why you are seeing null. It is functioning correctly.
USE sets the connection to use the database in the statement for future statements.

how to i use SET #variable to set values for variables in mysql for query in yii

my query such as having mysql variable declaration
SET #var1=0, #var2=0;
these variables are used in the select query
which works fantastic in phpmyadmin
but then if i write it as query in yii doesnt work
throws exception doesnt not execute but then if i remove
SET #var1=0, #var2=0;
then query executes but with no data fetched from db because it requires the set variables to fetch the result
how do i declare the set values of mysql in yii?is there any way out
As long as you reuse the same CDbCommand, you can issue multiple queries to the DB using the same connection. That will do what you need (and is what phpMyAdmin does).
Your problem is that you're doing two queries on different connections to the DB and your #vars aren't lasting between connections.
If you have set statements, you're probably writing something that is a little more procedural than a single sql statement is designed to deliver.
I would look at write in a stored procedure to the the job (http://forums.mysql.com/read.php?98,358569). Although they are a bit old school - they will probably do what you want quite effectively.

Changing current mysql database in a procedure?

For our system we are using multiple databases with the same structure. For example when we have 1000 customers, there will be 1000 databases. We've chosen to give each customers his own database, so we can delete all his data at once without any hassle.
Now I have to update the database structure several times a year. So I began to write a stored procedure which loops through all schemas. But I got stuck with executing a dynamic USE statement.
My code is as follows:
DECLARE V_SCHEMA VARCHAR(100);
SET V_SCHEMA = 'SomeSchemaName';
SET #QUERYSTRING = CONCAT('USE ', V_SCHEMA);
PREPARE S FROM #QUERYSTRING;
EXECUTE S;
DEALLOCATE PREPARE S;
When I execute this code I get an error which says Error Code: 1295. This command is not supported in the prepared statement protocol yet. So I assume that I cannot change the active database in a procedure.
I have searched the internet, but the only thing I found was creating a string of each alter query and prepare/execute/deallocate it. I hope there is a better solution for this. I could write a shell script that loops through the schemas and executes a SQL file on them, but I prefer a stored procedure that takes care of this.
Does anyone know how to make this work?
Thank you for your help!
EDIT: I use the latest stable version of MySQL 5.6
If there are some known databases, then try to write a CASE.
Otherwise, do not execute USE statement using prepared statements; instead, build other statements (SELECT, INSERT, UPDATE, ...) with full name - <database name> + '.' + <object name>, and execute them using prepared statements.
If you put your structure changes into a stored procedure in a temporary schema, you can do this within a Workbench SQL window.
You can build your iteration script using a query against the information_schema, e.g.
SELECT GROUP_CONCAT(CONCAT('USE ',schema_name,'; CALL tmp.Upgrade')
SEPARATOR ';\n') AS BldCode
FROM information_schema.schemata
WHERE schema_name NOT IN
('information_schema', 'performance_schema', 'mysql', 'sakila', 'world', 'tmp')
Since you cannot execute this as a prepared statement, you can copy the SQL result into a new SQL window, and run that.
Please note that the structure changes stored procedure would need to operate on the current schema, rather than specifying schemas.

How can I run an sql command on all databases at once?

I have circa 80 wordpress blogs, which write about my various sites. I want to update all posts in all databases for a specific string of text, in this instance, a domain name.
The script works perfectly fine, on one database, but I will need to make several changes, to ALL databases which will simply take far too long.
I need to be able to run these commands across every database at once, rather than one database at a time.
My script, as it works currently on a single database:
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://www.old-domain.com', 'http://mixudo.com');
Many thanks
Try executing this query:
SELECT CONCAT('UPDATE ',
schema_name, '.\'wp_posts\' SET \'post_content\' = REPLACE(post_content, \'http://www.old-domain.com\', \'http://mixudo.com\');')
FROM information_schema.schemata
WHERE schema_name NOT IN ('information_schema','mysql','performance_schema','phpmyadmin', 'webauth');
and then reexecuting the result.
Source: https://dba.stackexchange.com/a/20251
Create a list of database names with usernames/passwords that you need the script to be executed on
For each database in this list do:
Log into that database and select it
Run the script on that database
That is the only way to do your task safely.
You can get a list of databases on a mysql server using the SHOW DATABASES command. Using that as input you can write a shell script in whatever language you are capable that will foreach() through the list of databases, and running the UPDATE statement on each, by executing
use DBNAME;
Where DBNAME is the variable in the foreach. The update statement should work the same on all the databases, as I assume each db has the same set of tables with the same tablenames in each.
To Ed Heal's point, this also assumes you're using the root/admin user for the server so that it will have rights to update all the tables.