I've googled pretty hard on this topic but didn't manage to find anything relevant.
MySQL question: is it possible to display the database that holds the table row in a select query?
For example, I have 3 databases each with the same structure. I run something like this:
select database(), id, name, created_on from (
select * from db1.user
union all
select * from db2.user
union all
select * from db3.user) as q where id = "123";
In this case, the database() refers to the current database that the query is being run from. I want to change it to show the database name that's holding the row and table instead (db1,db2 or db3)
I am not sure if this is possible so I'm hoping someone will have a clue on this. Thanks!
The thing is that the DATABASE() function returns the name of the current default database. This won't be the same as the database used in the query when you are explicitly including the database as part of the query.
An alternative would be to include the name of the database in your select, thus:
select db, id, name, created_on from (
select "db1" as db, user.* from db1.user
union all
select "db2" as db, user.* from db2.user
union all
select "db3" as db, user.* from db3.user) as q where id = "123";
Be aware that that "database" is a reserved word (because it refers to the database function, so remember that if you decide to change the name I've used from "db".
You can achieve the desired result by following below tricky steps.
1) First, create db_name column in the user table of all three databases.
2) Then,In your insert into query add db_name's value as database(), hence while insertion, it will store respective database name ( i.e. When insert query is being executed from db1 then the value of db_name will be db1, similarly db_name column of db2 and db3 will have values db2 and db3 respectively.
3) Then in your query just replace database() by db_name.
Thus you will get respective database name.
Related
Im writing a migration and Im trying to query a table only if it exists in the db. In some envs it will exist and in others it wont which is why i want to check if it exists. The table of interest is called OLD_PASSWORD. I do the following.
SELECT ID, PASSWORD
FROM OLD_PASSWORD;
WHERE EXISTS
(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'OLD_PASSWORD);
This fails '.dbcSQLSyntaxErrorException: Table "USER_OLD_PASSWORDS" not found;' which makes sense because it wont exist in some envs.
I also tried something like
IF (EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'OLD_PASSWORD'))
BEGIN
SELECT ID,
PASSWORD
FROM OLD_PASSWORD
END
but it's not compatible with mysql.
Best approach was to query INFORMATION_SCHEMA.TABLES from Java, and then do the query from OLD_PASSWORD if it returns something.
You forgot the ' sign at the end of query before the ).
Nonetheless, this is cartesian select. Use in instead. i.e
password in (select password ...) etc.
I'm trying to craft a straight SQL (not stored procedure) query that finds all databases in a MySQL database server with a table whose name matches a pattern and has a certain collation, and then use the list of those database names and table names to get a specific value out of the tables that match the pattern.
For this query:
I do not know the names of the databases on the server (they must be queried)
I do not know the names of the tables in the database that could match (they must be compared against a pattern of %options)
For example, if I have 3 databases:
DB1 with tables:
something
f_options (containing a row where the value for a column called option_name is 'test' and the value for the option_value column is 'y')
DB2 with tables:
something
DB3 with tables:
something_else
zeoptions (containing a row where the value for a column called option_name is 'test' and the value for the option_value column is 'z')
Then I want a query that:
Finds databases with tables who match the collation and naming scheme
Select the values of the rows where the column called option_name has a row whose value is "test" in the column
For example, in the above 3 database tables, it would see Database 1 and 3 have a matching table, and it would return the values 'y' and 'z'
I'm trying to do this without using stored procedures or views (just a simple SQL statement).
So far I've gotten a working system that does 1. By querying the MySQL information_schema table, I can get the names of the databases + matching tables using this:
SELECT s.dbname, s.tablename FROM ( SELECT
`information_schema`.`TABLES`.`TABLE_SCHEMA` dbname ,
`information_schema`.`TABLES`.`TABLE_NAME` tablename FROM
`information_schema`.`TABLES` WHERE `information_schema`.`TABLES`.`TABLE_NAME` LIKE
'%options' AND `information_schema`.`TABLES`.`TABLE_COLLATION` LIKE
'utf8mb4_unicode_ci' ) as s;
Now the problem is figuring out how to write a SELECT statement who uses the above SQL statement as a subquery to populate the FROM
Right now this is what I have (though there's an obvious SQL error in how the FROM statement currently works). If I can solve the FROM statement issue I can finish the rest
SELECT `s.dbname`.`s.tablename`.`option_value` FROM `s.dbname`.`s.tablename`
( SELECT `information_schema`.`TABLES`.`TABLE_SCHEMA` dbname ,
`information_schema`.`TABLES`.`TABLE_NAME` tablename FROM
`information_schema`.`TABLES` WHERE
`information_schema`.`TABLES`.`TABLE_NAME` LIKE '%options' AND
`information_schema`.`TABLES`.`TABLE_COLLATION` LIKE 'utf8mb4_unicode_ci' ) as s
WHERE `s.dbname`.`s.tablename`.`option_name` LIKE 'test';
Which can be simplified to
SELECT `s.dbname`.`s.tablename`.`option_value` FROM `s.dbname`.`s.tablename`
( the working query above ) as s
WHERE `s.dbname`.`s.tablename`.`option_name` LIKE 'test';
Does anyone know how I can fix the
FROM `s.dbname`.`s.tablename` ( SELECT ... ) as s
part?
How can I duplicate my databases with limited number of rows in the tables.
Basically the duplicated db must have the same properties of original database but limited rows in the tables.
Try this, first create a similar table using
CREATE TABLE tbl_name_duplicate LIKE tlb_name;
then insert limited number of records into it using
INSERT INTO tbl_name_duplicate(SELECT * FROM tlb_name LIMIT 10);
to insert 10 records
Another approach, is to use the --where option in the mysqldump, so you could create something similar to a SQL query:
SELECT * FROM table_name WHERE id > (SELECT MAX(id) FROM table_name) - 10
re-written for the mysqldump (but you'll have to dump each table at a time, not the whole database):
mysqldump [options] --where="id > (SELECT MAX(id) FROM table_name) - 10" | mysql --host=host --user=user --password=password some_database
More information at MySQL Reference Guide.
Suppose I have a database data1 which gives me this:
show tables;
table1
table2
table3
Now instead of individually executing "select * from each table" i want to create a procedure which goes through each database shown in "show databases;" resultset, and then executes select * from each table of that database. I thought of using cursors which would scroll down the resultset, hold each database name in a variable and then execute select statement on each table of that database traversing in the same way. Can someone kindly help me out with how to use cursors in this case, as i am only aware of using cursors for SELECT and UPDATE statements.
btw i use MYSQL.
I'll refrain from asking why you would do this. Here is a general strategy in pseudocode;
[words in parentheses are (SQL commands and tables) which will run on your mySQL server.]
Connect to your mySQL server with your favourite tool/programming language and:
-- (USE information_schema;)
for db in (select distinct table_schema from tables;)
do:
for table in (select table_name from tables where table_schema='$db';)
do:
select field,column,attribute from $table;
done
done
Good luck!
you can get the query from infromation_Schema instead of 'show datbases'
I can get all the tables containing column 'hostname' using:
select select table_name from information_schema.columns
where column_name='hostname';
If I knew the names of all the tables I could use a union like:
SELECT * FROM ((SELECT hostname FROM table1)
UNION (SELECT hostname FROM table2)
...
UNION (SELECT hostname FROM tableN)) AS hosttable where hostname = 'hostA';
But I don't know how to combine the above two concepts without using an external script or stored procedure.
SQL queries must list the tables and columns explicitly. You can't write a query that takes the name of a table from the result of another column searched in the same query.
The solution is the one you have already found: write one SQL query against the information schema to get a list of table names, and then use those results to build a second SQL query, interpolating the table names into the appropriate place in the query.
You can do this in a stored procedure with PREPARE and EXECUTE, or you can do it in application code.