how to get data from dynamic table in sql - mysql

How can I get data from chosen table of my database?
I'm going to work with database in c# application and I have the database includes that tables:
MyTable1;
MyTable2;
...
And I have tbl variable that is equal to tbl = "MyTable2";. I want to execute the code as following:select * from tbl
I try to execute this code:
SELECT *
FROM (
SELECT TABLE_NAME
FROM information_schema.tables
WHERE TABLE_NAME = 'MyTable1'
);
But the code returned error that Every derived table must have its own alias
I want to get all data from table whose name is equal to my variable (tbl) and its value can also be changed. How can I do it?

You might be able to do this using a prepared statement in MySQL:
SELECT TABLE_NAME
INTO #table
FROM information_schema.tables
WHERE TABLE_NAME = 'MyTable1';
SET #query = CONCAT('SELECT * FROM ', #table);
PREPARE stmt FROM #query;
EXECUTE stmt;

SELECT *
FROM (
SELECT TABLE_NAME
FROM information_schema.tables
WHERE TABLE_NAME = 'MyTable1'
) AS Blah

Try this:
DECLARE #SELECT nvarchar(500)
SET #SELECT = 'SELECT * FROM ' + #tbl
EXECUTE sp_executesql #SELECT

Related

MySQL find column name where it's value match the pattern

How to search the entire database for column name equal to my rule and specific value as well.
Let's say that i want to search for column name like voucher where it's value contain that word value10
So far i can find the column name but i don't know how to match with value as well.
SELECT column_name FROM information_schema.columns
WHERE TABLE_SCHEMA = 'dbname' AND column_name LIKE '%voucher%'
So the end goal is to find any column name like voucher containing value10 within it's content.
Procedure code:
CREATE PROCEDURE search_tables ( IN column_pattern TEXT,
IN value_pattern TEXT )
BEGIN
SELECT GROUP_CONCAT (CONCAT( ' SELECT ''',
TABLE_NAME,
'.',
COLUMN_NAME,
''' AS `table.column`, ',
COLUMN_NAME,
' AS `value`\nFROM ',
TABLE_NAME,
'\nWHERE ',
COLUMN_NAME,
' LIKE ''',
value_pattern,
'''' )
SEPARATOR ' UNION ALL ')
INTO #query
FROM INFORMATION_SCHEMA.COLUMNS
WHERE column_name LIKE column_pattern
AND TABLE_SCHEMA = DATABASE();
PREPARE stmt FROM #query;
EXECUTE stmt;
DROP PREPARE stmt;
END
Test tables:
CREATE TABLE table1 (val1 VARCHAR(8), val2 TEXT);
INSERT INTO table1 VALUES
('a_01_a','b_11_b'),
('c_211_c','d_311_d'),
('e_55_e','f_00_f');
CREATE TABLE table2 (val3 CHAR(6), field4 VARCHAR(64));
INSERT INTO table2 VALUES
('x_1123','ghjghj_11_tyuyu'),
('8901_t','sdf_SDF_sdf');
Call:
CALL search_tables('%val%', '%11%');
Output:
table.column value
table1.val1 c_211_c
table1.val2 b_11_b
table1.val2 d_311_d
table2.val3 x_1123
fiddle
Create a stored procedure to loop through meta data table INFORMATION_SCHEMA to fetch all tables with column_name of choice. Further dynamic SQL is used to scan each of the tables retrieved for columns having the value of choice.
DDL and DML for setting the data for testing :
create table TESTA(COLMNA char(255),COLMNC char(255));
create table TESTB(COLMNA char(255),COLMNB char(255));
create table TESTC(COLMND char(255),COLMNA char(255));
insert into TESTA values('value0','someothercolmn');
insert into TESTB values('value0','anothersomeothercolmn');
insert into TESTB values('value1','Yetanothercolumn');
Test is to search all tables having column_name as COLMNA with value as value0. The procedure will accept column_name and column_Value, hence can be used across the database, just need to pass values as appropriate.
CREATE PROCEDURE Findtables( colmn_name VARCHAR(64),colmn_value VARCHAR(64) )
BEGIN
DECLARE tablename CHAR(64);
DECLARE c1 CURSOR FOR
SELECT table_name
FROM information_Schema
WHERE column_name = colmn_name;
OPEN c1;
lable_loop:LOOP
FETCH c1 INTO tablename;
select tablename;
SET #sql = CONCAT('SELECT * FROM ', tablename, ' WHERE ',colmn_name,' = "',colmn_value ,'" ;');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP lable_loop;
CLOSE c1;
END;
Call the stored procedure :
CALL Findtables('COLMNA','value0');
Output :
tablename
TESTA
COLMNA COLMNC
value0 someothercolmn
tablename
TESTB
COLMNA COLMNB
value0 anothersomeothercolmn
tablename
TESTC
COLMND COLMNA
Demonstration of the solution can be found in DBFIDDLE link [https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=4888a6160faf97fb75665832d6610293][1]
PS : I have to create INFORMATION_SCHEMA table in dbfiddle as metadata tables are not accessible.

How to call MySQL function for every column that is present in table?

I need to call a mySQL function for all columns in a table.
I know how to do it for a particular column
Like this:
UPDATE `table_name` set `column_name` = function_name(`column_name`)
But i have no clue how to do it for all columns at once.
Thanks in advance.
Little clarification: I dont want to manually mention all columns, as i probably could have 200 columns table.
But i have no clue how to do it for all columns at once.
You just can't - there is no such shortcut in the update syntax.
You can do this with a single update statement, but you need to enumerate each and every column, like:
update table_name set
column_name1 = function_name(column_name1),
column_name2 = function_name(column_name2),
column_name3 = function_name(column_name3)
An alternative would be to use dynamic SQL to programatically generate the proper query string from catalog table information_schema.columns, and then execute it. This seems uterly complicated for what looks like a one-shot task... But here is sample code for that:
-- input variables
set #table_schema = 'myschema';
set #table_name = 'mytable';
set #function_name = 'myfunction';
-- in case "GROUP_CONCAT()" returns more than 1024 characters
set session group_concat_max_len = 100000;
-- build the "set" clause of the query string
select
#sql := group_concat(
'`', column_name, '` = ', #table_schema, '.', #function_name, '(`', column_name, '`)'
separator ', '
)
from information_schema.columns
where table_schema = #table_schema and table_name = #table_name;
-- entire query string
set #sql := concat('update ', #table_schema, '.', #table_name, ' set ', #sql);
-- debug
select #sql mysql;
-- execute for real
prepare stmt from #sql;
execute stmt;
deallocate prepare stmt;

Cannot use prepare statement on locally declared variable

In a procedure I want to select a value from a specific table in all databases. I developed a code and reached to this point:
BEGIN
DECLARE dynamic_query LONGTEXT;
SET SESSION group_concat_max_len = 100000000;
SET dynamic_query = (
SELECT
GROUP_CONCAT(
"SELECT option_name AS _key, option_value as _value from ",
TABLE_NAME,
" where option_name like '",
"something%'" SEPARATOR ' union ')
FROM
(
SELECT
CONCAT(`database_name`,'.',`table_prefix`,'options') as TABLE_NAME
FROM `tablename`
WHERE `database_name` <> '' AND `table_prefix` <> ''
) AS tmp
);
SELECT dynamic_query;
END
And I copy the output and execute it and it works fine. But when I add a prepare statement like below I get an error which is mentioned in this bug.
PREPARE result_query FROM dynamic_query;
EXECUTE result_query;
DEALLOCATE PREPARE result_query;
Is there any other way so I can get my desired output?
P.S.: I'm using SET SESSION group_concat_max_len = 100000000; to expand group_concat's limit but I prefer another way because the number of databases are growing.

Mysql UNION with dynamic query

i have the following problem. I inherited a software that uses a database prefix for every customer.
All tables have the same structure and columns. For a data migration to new version i want to union all these tables
and set a customer foreign key instead and get rid of all the subtables. i'm looking for a way to create
a view for this task because i also want to stay backwards compatible for now.
I found this dynamic query which seems to do what i want
but i can't execute on my mysql server. I assume it was written for another sql server.
The table name structure is (about 80 customer tables):
customer1_faxe
customer2_faxe
customer3_faxe
customer4_faxe
...
How would you approach this problem?
DECLARE #SelectClause VARCHAR(100) = 'SELECT *'
,#Query VARCHAR(1000) = ''
SELECT #Query = #Query + #SelectClause + ' FROM ' + TABLE_NAME + ' UNION ALL '
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%_faxe'
SELECT #Query = LEFT(#Query, LEN(#Query) - LEN(' UNION ALL '))
EXEC (#Query)
This query is using SQL Server syntax. You need something like this:
declare #SelectClause varchar(8000);
declare #Query varchar(8000);
set #SelectClause = 'SELECT *';
SELECT #Query := group_concat(#SelectClause, ' FROM ', TABLE_NAME SEPARATOR ' UNION ALL ')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%_faxe';
prepare stmt from #Query;
execute stmt;
Note that the group_concat() with separator simplifies the logic.

Lower case column names when using SELECT

I'm using the Kohana framework and I need to convert column names to lowercase. I don't have control of the db table structure. I want to do the following:
SELECT LOWER(*) FROM .....
but MYSQL does not like that. Whats the proper way of outputting the lower case column names if I don't know what the column names will be?
Found here http://dev.mysql.com/doc/refman/5.0/en/columns-table.html
SELECT LOWER(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Table'
Below you can see both MSSQL and MySQL syntax for creating a dynamic query using the column results from the query above.
MSSQL Syntax
DECLARE #ColumnNames [nvarchar](1024)
SELECT #ColumnNames = COALESCE(#ColumnNames + ', ', '') + LOWER(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Table'
DECLARE #Sql [nvarchar](1024) = 'SELECT ' + #ColumnNames + ' FROM Table ' --Remember to put spaces after SELECT and before FROM
EXEC(#Sql)
With this you are dynamically building your query and then executing it.
MySQL Syntax
SELECT #ColumnNames := GROUP_CONCAT(LOWER(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Table';
SET #Sql = CONCAT('SELECT ', #ColumnNames, ' FROM Table ');
PREPARE stmt1 FROM #Sql;
EXECUTE stmt1;