0

Using the info from this other StackOverFlow question I can query the list of all databases that have the same table:

SELECT 
    table_name, table_schema AS dbname
FROM 
    INFORMATION_SCHEMA.TABLES
WHERE 
    table_name = 'myCommonTableName'

This will give me the list of database that have the table I'm interested in. My question is now how can I view the values of those tables instead of just the names of the tables. In other words something along the lines of:

SELECT 
    myCommonTableName.id 
FROM 
   [all tables from all databases - query above]
WHERE
    myCommonTableName.someValue > someTest

In other words I want to get all the rows from all the identical tables (multi-tenant) for all the databases that match a specific criteria. I need to do this for user and account management. Is it possible? And if so how?

UPDATE To further clarify as there seems to be some confusion, I do NOT want to do this:

SELECT * FROM myTable WHERE myTable.id = (SELECT id FROM anotherTable WHERE someOtherCondition).

What I'm trying to do is something like:

SELECT * FROM [databaseList].myTable WHERE myTable.id = 1.

Or to be more precise:

for(listOfDatabases)
    SELECT * FROM [database.x].myTable WHERE myTable.id = 1

Basically I want to get all the results from all myTable in all my databases where they have the same ID value of 1. It's actually a different WHERE clause but you get the idea.

Stephane Grenier
  • 15,527
  • 38
  • 117
  • 192
  • @Shadow This is NOT a duplicate question. in your links to duplicate questions it's assumed you already know the databases and can use joins, unions, etc. In my case I don't know the databases and there could be one but there could also be many. In other words my query needs to find both the tables and databases as well as the data from those tables. The questions you referred only work if you have at most a handful of databases AND you know the databases AND you're trying to join them, I'm NOT trying to join them. – Stephane Grenier Sep 25 '17 at 02:24

1 Answers1

-1

You will need to wrap your /usr/bin/mysql interactions with a higher level language, like bash, python, or java. Pick an implementation language.

You suggested (essentially) select id from myCommonTableName. You will need to either use that query within a certain DB environment (/usr/bin/mysql --database=myDbName), or else select id from myDbName.myCommonTableName.

The sticky wicket is that DB names are not known apriori. You have an initial information_schema.tables query that supplies DB names, and you will need bash or another language to insert those DB names into fully qualified SELECT statements.

You've not yet granted permission to use a particular auxiliary language. But suppose we settle on bash, and mysql_creds supplies suitable credentials for DB login, and you've created a very nice template query. Then a solution might look like this:

echo 'select table_schema as dbname from information_schema.tables where ...' |
    mysql_creds --database=mysql > /tmp/dbnames.txt
for DBNAME in `cat /tmp/dbnames.txt`
do
    cat template.sql | mysql_creds --database=${DBNAME} | tee /tmp/result-${DBNAME}.txt
done

Feel free to sed the template if you want $DBNAME to be part of each query.

You might find it helpful to run wc -l or diff -u over /tmp/result-*.txt

One could write a stored procedure LOOP that does

set @q = concat('select option_value from ', scName, '.wp_options ...'
PREPARE stmt1 FROM @q;
EXECUTE stmt1;

but at that point we have left SQL92 far behind, we are computing strings and running eval on them, works out pretty similar in mysql, bash, or others. The OP hasn't yet described what scripting approach is best suited to his needs. Writing code is seldom difficult, but eliciting requirements often is.

Assume the template query mentions @DB@.myCommonTableName as part of a select. If we wish to impose a new requirement, like "no more than two DB connections shall be created", then it is straightforward to incorporate that into a loop:

echo 'select table_schema as dbname from information_schema.tables where ...' |
    mysql_creds --database=mysql > /tmp/dbnames.txt
rm -f /tmp/queries.sql
for DBNAME in `cat /tmp/dbnames.txt`
do
    sed -e "s/@DB@/${DBNAME}/"  < template.sql  >> /tmp/queries.sql
done
cat /tmp/queries.sql | mysql_creds --database=mysql | tee /tmp/results.txt
J_H
  • 17,926
  • 4
  • 24
  • 44
  • That's what I'm afraid of and why I'm asking it here... – Stephane Grenier Sep 25 '17 at 02:06
  • No, you do not need to involve any scripting languages, see the following answer in the 2nd duplicate question: https://stackoverflow.com/a/13865114/5389997 – Shadow Sep 25 '17 at 02:10
  • I don't see how this question is an exact duplicate of either of those questions. In the first, the DB names mydatabase{1,2} were known apriori, as with the names database{1,2} that appear in the accepted answer of the second. The OP will need to synthesize such queries after consulting information_schema.tables. But so far, he insists we use only [tag] mysql to construct the answer. It looks like additional scripting support will be needed to resolve his question. – J_H Sep 25 '17 at 02:21
  • @Shadow It's NOT a duplicate, I'm not trying to join multiple tables rather than I'm trying to query the same data from similar tables across an unknown number of database. In other words I want to do "SELECT name FROM database.table" across all the databases that have that table and combine them into a single result. The question you referred wouldn't work if I had 100 databases – Stephane Grenier Sep 25 '17 at 02:26
  • @JH If it can only be done outside of SQL then the actual implementation is not required. I'm basically looking to see if it's possible within SQL or not, and if so how. That's why I never specified any additional languages. – Stephane Grenier Sep 25 '17 at 03:05
  • I suppose it works out to semantics, like whether "stored procedure LOOP" is "pure" or as bad as `bash`. If we're sticking to SQL92 (no `eval`) then it's infeasible, you would need to wrap with an outer loop. If we're fond of vendor support like pl/sql (oracle) or mysql's stored procedures, then sure, pick your poison, there's lots of ways to implement it. – J_H Sep 25 '17 at 03:07
  • I have several options outside of SQL but it would be really helpful if it could be done in a single SQL query because if I have to do a loop, and say I have several hundred connection, then that's hundreds of connections, even with pooling, to the database each time I want to run that query. If it's not possible and I want to minimize connections then I could run a stored procedure, but other than that the only option I can see is a loop through the results if I use an outside language which is very bad... – Stephane Grenier Sep 25 '17 at 03:13
  • It is a duplicate, answers to both questions demonstrate how to query tables from multiple databases. The answer I specifically linked above in an earlier comment does not do joins, it uses a loop solution in pure sql to get the values of multiple tables. Since the loop in the duplicate topic is done within a stored procedure in mysql, a single connection is enough. – Shadow Sep 25 '17 at 05:38
  • @J_H the OP already knows how to get the table names dynamically. Just need to combine what he slready knows with the answers from the duplicate topics. – Shadow Sep 25 '17 at 05:41