selecting first column from all tables in a mysql database - mysql

i have a column named "name" which is present in all tables in mysql database.
I wanted to list all the names in all tables so i used the following query
select name from (SELECT table_name FROM information_schema.tables WHERE table_type='BASE TABLE') as abc
But it did not work for me and instead it returned me the table_name column alone.
Then i used show tables and stored the output in another table called table_list then i executed the following query
select name from (select table_name from table_list) as abc
This also returned me the same result i.e. all table names.
Can i know what is that i am doing wrong and what is the right way to do it?
I am using MySQL 5.4 and i want to either write a subquery or a procedure or a function purely in mysql.

There is PREPARE and EXECUTE which can run a sql statement from inside a user variable, so could probably use something similar to (untested!)
SET #a = "";
SELECT #a := CONCAT('(select name from ',GROUP_CONCAT(table_name SEPARATOR ') UNION (select name from '),')') FROM information_schema.tables WHERE table_type='BASE TABLE' GROUP BY 1;
PREPARE stmt FROM #a;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

What you need is a way to have variables in SQL (so you can say select * from $name where $name in (select ...)). SQL doesn't allow that.
My suggestion is to split the process up:
First run this query:
select 'select distinct name from ' || table_name || ' union'
from select table_name from table_list
That'll give you the selects to run. Put them into a small script, remove the last "union" and run that script.
[EDIT] If MySQL supports an "eval" operator in stored procedures (i.e. where you can build SQL from parts and then run it), you could do this. I checked the docs and it doesn't look like there is an eval. You could also write an extension in C (see chapter 22) that either implements the lookup or an "eval" function.
But my guess is that your database won't change all the time. So the most simple solution would be to write a small SQL script that creates the code for a view (that is a string; it doesn't actually create the view ). Every time the DB changes, you simply run the script to recreate the view and afterwards, you can run the query against the view to get a list of all names.

Related

ı can't use variables in MySQL commands

set #tmpGuid = REPLACE( uuid(),'-',''); set #fieldName = concat('deneme' , '_' , #tmpGuid); ALTER TABLE table_name RENAME COLUMN deneme to #fieldName;
https://i.stack.imgur.com/ciQ44.png
how can use my variable on mysql commands
Variables are meant to store data, not code. In SQL, table and column names count as the latter. From User-Defined Variables:
User variables are intended to provide data values. They cannot be used directly in an SQL statement as an identifier or as part of an identifier, such as in contexts where a table or database name is expected, or as a reserved word such as SELECT.
Many DBMS don't allow DDL statements to be parameterised. I.e. alter, create statements and such.
However this doesn't mean it's impossible. What you'd need to do is convert your statement to dynamic SQL, which you can manipulate in every way possible (including inserting parameters into the string).
Then simply executing it.
In your example:
SET #tmpGuid = REPLACE( uuid(),'-','');
SET #fieldName = concat('deneme' , '_' , #tmpGuid);
SET #sql = CONCAT('ALTER TABLE table_name RENAME COLUMN deneme to ', #fieldName);
PREPARE dynamic_SQL FROM #sql;
EXECUTE dynamic_SQL;
DEALLOCATE PREPARE dynamic_SQL;
Ofcourse using dynamic SQL has it's own troubles, and opens up potential risks. But it's the only way to do something like this.
See it in action: Here

Storing query results from EXECUTE in a view - MySQL

I am trying to store the output of the following query into a view or a temporary table. I know that view requires the SELECT statement but I was wondering if it could work as well with the EXECUTE command.
This is my query:
SET #por= NULL;
SELECT
CONCAT(GROUP_CONCAT(
DISTINCT
CONCAT('SELECT * FROM ', table_name)
SEPARATOR '\r\nUNION\r\n'
), '\r\nUNION\r\n', 'select * from table1')
INTO
#union_por_tables
FROM
information_schema.tables
WHERE
table_schema = 'schema' AND table_name LIKE '%por%';
PREPARE stmt1 FROM #union_por_tables;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1
This query return me 250000 rows and I want to store them. Can someone help me?
What you described is referred to as materialized view
From what I know at the moment, MySQL doesn't support materialized views. You can simulate it by inserting data in an actual table, thus maintaining the cache manually.
MariaDB implements materialized views via something they refer to as flexviews. The docs are here: https://mariadb.com/kb/en/library/flexviews/
You might explore the option of trying out MariaDB and its flexviews feature for your particular use case.

Mysql select all existing tables from current database using stored procedure

I am still trying to solve this Mysql issue. I'm not a dba but need to figure out how to do it.
I need to run a select statement over all (50k) existing tables from current db.
Please note that union is not the correct way for me since I have more than 50k tables, I need to solve this with a loop.
So far, I have been trying with two approaches without success:
First: using a subquery and the information_schemma like:
Select *
from
(SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema = 'my_db')
or
Select * from (show tables;);
Second: using a stored procedure like:
delimiter //
CREATE PROCEDURE get_all_tables()
BEGIN
DECLARE a varchar(100);
DECLARE cur1 CURSOR FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'my_db';
OPEN cur1;
But neither is doing what I want.
It yields syntax or conceptual errors.
BTW: I already solve this using an external perl script performing a "show tables" and running a select withing a loop.
This is ok but I think this should be solved with pure mysql.
Any idea would be welcome.
Leo.
SELECT * FROM (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema = 'my_db')
First of all, you can't do this in any implementation of SQL. The table name must be known by the query at prepare-time, not at run-time. You can't select from a string, you have to select from a table identifier.
It's the difference between these two queries:
SELECT * FROM MyTable -- identifier
SELECT * FROM 'MyTable' -- string value (this won't work)
By the way, most programming languages have a similar concept, of a function or class name being different from the name of that function or class. You can't execute a function by its name using the same syntax as you would execute it by its identifier.
<?php
$result = myFunction();
$result = 'myFunction'(); // nonsense
But some languages do have ways of getting around this:
<?php
$funcName = 'myFunction';
$result = $funcName();
In SQL, you can get around this limitation by using the table name as you build a new SQL query as a string. Then prepare and execute that SQL query string at runtime. This is called a dynamic SQL query.
But like the PHP example above of using a variable to store the name of the function, using dynamic SQL requires multiple steps. You can't combine the query to get your table names into the same query that uses the results.
You were on the right track with your stored procedure that opens a cursor for the set of table names. But you can't open cursors from dynamic SQL statements in stored procedures.
You can do what you need pretty easily using dynamic SQL in a scripting language like PHP or Python.

How to delete all MySQL tables beginning with a certain prefix?

I've found another thread on this question, but I wasn't able to use its solutions, so I thought I'd ask with more clarity and detail.
I have a large MySQL database representing a vBulletin forum. For several years, this forum has had an error generated on each view, each time creating a new table named aagregate_temp_1251634200, aagregate_temp_1251734400, etc etc. There are about 20,000 of these tables in the database, and I wish to delete them all.
I want to issue a command that says the equivalent of DROP TABLE WHERE TABLE_NAME LIKE 'aggregate_temp%';.
Unfortunately this command doesn't work, and the Google results for this problem are full of elaborate stored procedures beyond my understanding and all seemingly tailored to the more complex problems of different posters.
Is it possible to write a simple statement that drops multiple tables based on a name like match?
There's no single statement to do that.
The simplest approach is to generate a set of statements, and execute them individually.
We can write a simple query that will generate the statements for us:
SELECT CONCAT('DROP TABLE `',t.table_schema,'`.`',t.table_name,'`;') AS stmt
FROM information_schema.tables t
WHERE t.table_schema = 'mydatabase'
AND t.table_name LIKE 'aggregate\_temp%' ESCAPE '\\'
ORDER BY t.table_name
The SELECT statement returns a rowset, but each row conveniently contains the exact SQL statement we need to execute to drop a table. (Note that information_schema is a builtin database that contains metadata. We'd need to replace mydatabase with the name of the database we want to drop tables from.
We can save the resultset from this query as a plain text file, remove any heading line, and voila, we've got a script we can execute in our SQL client.
There's no need for an elaborate stored procedure.
A little googling found this:
SELECT 'DROP TABLE "' + TABLE_NAME + '"'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'prefix%'
This should generate a script.
Source: Drop all tables whose names begin with a certain string
From memory you have to use prepared statements, for example: plenty of samples on stack exchange
I would recommend this example:
SQL: deleting tables with prefix
The SQL from above, this one includes the specific databasename - it builds it for you
SELECT CONCAT( 'DROP TABLE ', GROUP_CONCAT(table_name) , ';' )
AS statement FROM information_schema.tables
WHERE table_schema = 'database_name' AND table_name LIKE 'myprefix_%';
Here is a different way to do it:
MySQL bulk drop table where table like?
This will delete all tables with prefix "mg_"
No need to copy and paste rowsets and in phpadmin copying and pasting is problematic as it will cut off long table names and replace them with '...' ruining set of sql commands.
Also note that '_' is a special character so thats why 'mg_' should be encoded as 'mg\_'
(and FOREIGN_KEY_CHECKS needs to be disabled in order to avoid error messages)
SET FOREIGN_KEY_CHECKS = 0;
SET GROUP_CONCAT_MAX_LEN=32768;
SET #tables = NULL;
SELECT GROUP_CONCAT('`', table_name, '`') INTO #tables
FROM information_schema.tables
WHERE table_schema = (SELECT DATABASE()) and table_name like 'mg\_%';
SELECT IFNULL(#tables,'dummy') INTO #tables;
SET #tables = CONCAT('DROP TABLE IF EXISTS ', #tables);
PREPARE stmt FROM #tables;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET FOREIGN_KEY_CHECKS = 1;

getting table name from a table and using the table name to access data

I want to create a database where there is a list of table names stored in a table. Now with the help of this list I can access the other tables.
Ex :-
Table name :- table_list (2 column i.e. table_name,table_id)
table_list attributes
authentication 1
basic_info 2
contact 3
I can directly access these tables using select statement but I want to access them using the table_list table preferably using select statement.
I tried
select * from (select table_name as x from table_list where id=2) as y
But could not get the proper output.
It is called Prepared Statements and their only use is when you want to implement your mentioned need in one request. Otherwise you can easily retrieve table names in a programming language and create your next statement using the data in hand. Here's how Prepared Statements work:
SELECT table_name INTO #tbl FROM my_tables WHERE id = 1 LIMIT 1;
SET #sql := CONCAT('SELECT * FROM ', #tbl);
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
TRY THIS
select * from (SELECT TABLE_NAME FROM TABLE_LIST WHERE ID=2)as y
The table name (an "identifier") must be a static part of the SQL text issed to the database; the identifier can't be supplied "on the fly", either as a parameter or as a result from another SQL query.
To do what you want to do, you will need a two step approach. You can use one (or more) SQL statements to obtain the identifiers you need (table name, column names, etc.), and then use that to dynamically create a second SQL statement, as a string.
The identifiers (table names, column anmes) can not be provided as parameters or "bind variables", they must be a static part of the SQL text.
For example, to generate the statement:
SELECT CONCAT('SELECT * FROM `',table_name,'` ORDER BY 1') AS stmt
FROM table_list
WHERE id = 2
(The coding details are dependent on what language you are using.)
Since you are sure that the table name you want to access is x, just check whether such a table exists using a query and use x for future purpose.