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?
Related
how we can check if a column exists on Table in MySQL without using Stored Procedure. MySQL v3.23 which won't support writing Store Procedure.
v3.23 ?? If You know the table name and column name then try describe tablename or show create tablename if you know only column name select * from information schema.columns where column_name = columnname. Show tables should show all tables then manually select column name from the listed tables.
But this version is so ancient I have no idea if any of these will work
Try this, counting the columns in your table using the information_schema.COLUMNS.
SELECT COUNT(*) FROM information_schema.`COLUMNS`
WHERE table_schema = 'your_database_name'
AND table_name='your_table_name'
AND column_name='your_column_name';
The INFORMATION_SCHEMA COLUMNS Tabletable provides information about columns in tables.
Link
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.
I have a Microsoft stored procedure that queries two MySQL databases using OpenQuery. The two MySQL databases should be have the same schemas, so I can run the same query on both.
However, we will soon alter the MySQL schemas, and add a column to a table. But the two MySQL databases won't happen at the same time, and I don't know the exact date of the releases.
I therefore want to write the query so that if the new column exists, then I use it in my select. If not, then I use a default value.
Is this possible? (That is have a query that handles differences in the table schema?)
(Not to be confused with 'coelesce' where the field definitely exists, but is simply null.)
You can use the following SELECT statement:
SELECT *
FROM information_schema.COLUMNS
WHERE
TABLE_SCHEMA = 'database name' AND TABLE_NAME = 'your table name'
AND COLUMN_NAME = 'the column name you want to check for'
If the above returns a value, your column is there. If not, then run your alternative SELECT statement
Updated statement:
IF EXISTS (SELECT *
FROM OPENQUERY(servername, 'SELECT *
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = ''database name''
AND TABLE_NAME = ''your table name''
AND COLUMN_NAME = ''the column name you want to check for'' ))
I am working on a WPF application which installs if MySQL is installed,
so before installation I want to check whether mysql.proc table exists or not.
I googled about it and ended up with a query
select * from information_schema.Tables
where Table_schema = Schema() and Table_Name = 'mysql.proc'
This query returns an empty row.
I also tried simple select statement
select * from mysql.proc,
and this returned a table with the names of all the stored procedures, but if this table didn't exists then it throws an exception in the c# code.
So is there any way that I can fire a query from c# and get a boolean value depending on whether mysql.proc table exists or not?
Try SHOW TABLES FROM mysql LIKE 'proc'. If there are no result rows, the table doesn't exist. If there is one row, the table exists. Note that this approach isn't portable across RDBMSs, though that doesn't seem to be a concern of yours.
As for your first query, SCHEMA() returns the default database, so if it's not "mysql", the query will fail. Likewise, data in the Table_Name column doesn't include the database name, so comparing to 'mysql.proc' will always fail.
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.