How to Create View or Table from Prepared Statement (Select Query) - mysql

I am trying to create View from the following prepared statement:
CREATE VIEW myview AS -- this line is not working
SELECT CONCAT(GROUP_CONCAT('SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total FROM mydb.source_table' SEPARATOR '\n UNION ALL \n'),'\nORDER BY Total ASC')
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'mydb'
AND TABLE_NAME = 'source_table'
AND COLUMN_NAME NOT IN ('ID', 'Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
I am still confused with handling group_concat syntax.
I just need help on how to create View with the above prepared statement.
UPDATE 1: Stored procedure
As suggested by #nbk, I have to create into 5 stored procedures in single column to be able the data and use it to CREATE TABLE query. Here's the stored procedure version of the above codes.
CREATE DEFINER=`admin`#`%` PROCEDURE `sp_result`()
BEGIN
SELECT CONCAT(GROUP_CONCAT('SELECT ''', COLUMN_NAME,''' MyColumns FROM mydb.source_table' SEPARATOR '\n UNION ALL \n'), '\n LIMIT 0, 1 \n')
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'mydb'
AND TABLE_NAME = 'source_table'
AND COLUMN_NAME NOT IN ('ID', 'Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END
Here's the result of this stored procedure:
+-----------+
| MyColumns |
+-----------+
| Abc |
+-----------+
In order this approach to be useful to me, I want the above result to be the one of the column of my CREATE TABLE query:
Here are my attempts but no luck:
First attempt: Separate Query
CREATE TABLE my_table AS SELECT id, name, mydb.sp_result() FROM source_table; -- Error Code: 1305. FUNCTION project_x.best_vendor1_name does not exist
Second attempt: Inserted at the last part of the stored procedure
CREATE TABLE my_table AS SELECT #sql FROM source_table; -- no effect
Here, I really do not know how CREATE TABLE using the stored procedure returned data.
UPDATE 2: Illustrate Encapsulation
CREATE DEFINER=`root`#`%` PROCEDURE `proc_column_sum`()
BEGIN
DROP TABLE IF EXISTS table2;
SELECT CONCAT('
CREATE TABLE table2 AS (',GROUP_CONCAT('
SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total
FROM testdb.products '
SEPARATOR '\n UNION ALL \n'), -- runtime syntax error somewhere here
'\n ORDER BY Total ASC)') -- missing closing single quote right after ASC
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'testdb'
AND TABLE_NAME = 'products'
AND COLUMN_NAME NOT IN ('ID', 'Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END

You must put the CREATE TABLE in your prepared statement.
this example uses a temporary table only for demonstration purposes
CREATE DEFINER=`root`#`%` PROCEDURE `proc_column_sum`()
BEGIN
SELECT
CONCAT('CREATE TEMPORARY TABLE IF NOT EXISTS table2 AS (',GROUP_CONCAT('SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total FROM testdb.products ' SEPARATOR '\n UNION ALL \n'),'\nORDER BY Total ASC)')
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'testdb'
AND TABLE_NAME = 'products'
AND COLUMN_NAME NOT IN ('ID', 'Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END
you call it then
call proc_column_sum();
SELECT * FROM table2
But with this approach you have call every time the procedure to get the newest data.
I can' figure out, what went wrong in your query
CREATE DEFINER=`root`#`%` PROCEDURE `proc_column_sum`()
BEGIN
DROP TABLE IF EXISTS table2;
SELECT CONCAT('
CREATE TABLE IF NOT EXISTS table2 AS (',GROUP_CONCAT('
SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total
FROM testdb.products '
SEPARATOR '\n UNION ALL \n')
,'\nORDER BY Total ASC)')
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'testdb'
AND TABLE_NAME = 'products'
AND COLUMN_NAME NOT IN ('ID', 'Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
END

Related

MySQL UNION stored procedure pivot tables

I need to be able to Union the results of 3 Stored Procedures.
The Procedures are coded the same but produce different results.
I have tried creating temporary tables within each procedure and UNION ALL on those within another procedure, but it is not giving me the expected results.
Thank you.
DROP PROCEDURE IF EXISTS CONVERTOPCOLTOROWS;
DELIMITER $$
CREATE PROCEDURE CONVERTOPCOLTOROWS (IN n_seq INT)
BEGIN
SET #my_schema='femlinecycletime';
SET #my_table='table_seqcycletime';
SET #clause_where='`Seq`=';
SELECT GROUP_CONCAT(my_query
SEPARATOR ' UNION ALL ')
INTO #sql FROM
(SELECT
CONCAT('SELECT', QUOTE(COLUMN_NAME), ' AS `KEY`, `', COLUMN_NAME, '` AS `value` FROM `', #my_table,'`WHERE ', #clause_where, n_seq) my_query
FROM
(SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA` . `COLUMNS`
WHERE `TABLE_SCHEMA` = #my_schema
AND `TABLE_NAME` = #my_table
AND `COLUMN_NAME` BETWEEN 'OP02' AND 'OP90') AS `col1`) AS `col2`;
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
End;
$$
DELIMITER ;

Incorrect parameter count in the call to native function 'JSON_OBJECT'

I'm getting all columns from a table and fetching the result to JSON using the function JSON_OBJECT. But when i execute the stored procedure i'm getting this error.
CREATE DEFINER=`sistema`#`%` PROCEDURE `get_products_as_json`()
BEGIN
SET #fields = (
'SELECT
group_concat(\'\`\', column_name, \'\`\, \', column_name)
FROM
information_schema.columns
WHERE
table_schema = DATABASE()
AND table_name = \'products\'
ORDER BY table_name , ordinal_position'
);
SET #stmt = ('SELECT JSON_OBJECT(?) FROM products LIMIT 10');
PREPARE stmt FROM #stmt;
EXECUTE stmt USING #fields;
DEALLOCATE PREPARE stmt;
END
You cannot use prepared statements in that way.
You have to CONCAT the variable.
I also changed the first SELECT, this works too and is better to read.
DELIMITER $$
CREATE DEFINER=`sistema`#`%` PROCEDURE `get_products_as_json`()
BEGIN
SET #fields = (
SELECT
group_concat('"', column_name, '", ', column_name)
FROM
information_schema.columns
WHERE
table_schema = DATABASE()
AND table_name = 'products'
ORDER BY table_name , ordinal_position
);
SET #stmt = CONCAT('SELECT json_object(',#fields,') FROM products LIMIT 10');
PREPARE stmt FROM #stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
I added also the DELIMITER in case you don_'t use mysql workbench

How to mimic pgsql row_to_array()

I wish to get a JSON_OBJECT of a table.
While pgsql has row_to_Json, MySQL does not, and I wish to mimic this.
Of course, I could do this..
SELECT JSON_ARRAYAGG(JSON_OBJECT(id, name)) FROM my_table;
However, if I do not know the names of the fields, and I wish to do something like this:
SELECT JSON_ARRAYAGG(JSON_OBJECT(*)) FROM my_table;
Of course, this does not work. So I tried:
SET #fields = (select group_concat(my_table.res) FROM (SELECT COLUMN_NAME AS res FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='my_table') AS my_table);
SELECT JSON_OBJECT(#fields) FROM my_table;
Which does not work also, because a single string is passed to JSON_OBJECT.
How to get the JSON representation of a row from any table?
You need to use a stored procedure to execute dynamic SQL. The procedure should contain code like this:
SET #fields = (
select group_concat('"', column_name, '", `', column_name, '`')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME=table_name_param
);
SET #sql = CONCAT('SELECT JSON_OBJECT(', #fields, ') FROM `', table_name_param, '`';
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

MySQL : How to dynamically call stored procedures when inserting new row in table

I have a query that dynamically convert rows into column when inserting new row in table. However, every time I inserting new row in table I need to call the stored procedure to show the output call bian_test_db.new_procedure();. How can I make it automatically show the new insert data in view without calling the procedure.
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_procedure`()
BEGIN
SET SESSION group_concat_max_len = 1000000;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'ifnull(SUM(case when itemname = ''',
itemname,
''' then itemvalue end),0) AS ',
itemname
)
) INTO #sql
FROM
bian_test_db.history;
SET #sql = CONCAT('CREATE OR REPLACE view testing as SELECT user_id, ', #sql, '
FROM bian_test_db.history
GROUP BY user_id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
First create below procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_procedure`()
BEGIN
SET SESSION group_concat_max_len = 1000000;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'ifnull(SUM(case when itemname = ''',
itemname,
''' then itemvalue end),0) AS ',
itemname
)
) INTO #sql
FROM
bian_test_db.history;
SET #sql = CONCAT('CREATE OR REPLACE view testing as SELECT user_id, ', #sql, '
FROM bian_test_db.history
GROUP BY user_id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
And then create below trigger,which call above Procedure from it.
DELIMITER $$
CREATE TRIGGER CHANGE_ROW_YOUR_TABLE
AFTER INSERT ON YOUR_TABLE
FOR EACH ROW
BEGIN
call new_procedure;
END$$
DELIMITER ;
Hope this will help you.
You could use a trigger
CREATE TRIGGER your_trigger_name AFTER INSERT ON your_table
FOR EACH ROW
BEGIN
.... your code
END
see https://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html and https://dev.mysql.com/doc/refman/5.7/en/create-trigger.html

Error in creating temporary table in mysql

I am facing difficulty in creating temporary table in mysql.
I have a stored procedure i am creating some sql statement i need to create the sql statement output as a temporary table in my sql. Here is my procedure. any body help me please?
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_procedure`()
BEGIN
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(CASE WHEN workspaceid = ''',
workspaceid,
''' then "''''" ELSE NULL end) AS ',
CONCAT('`',workspaceid,'`')
)
) INTO #sql
FROM sms.hotelings;
SET #sql = CONCAT('SELECT t.Time, ', #sql, '
FROM sms.hotelings h, sms.hotelingtime t
GROUP BY t.Time');
-- PREPARE stmt FROM #sql;
-- EXECUTE stmt;
-- DEALLOCATE PREPARE stmt;
CREATE TEMPORARY TABLE IF NOT EXISTS table2 AS #sql;
select * from table2
drop temporary table table2;
END
I want to create a temporary table using my #sql statement.
Thanks in advance.
You have to use PREPARE if you want to use a dynamic statement
SET #sql = CONCAT('CREATE TEMPORARY TABLE IF NOT EXISTS table2 AS SELECT t.Time, ', #sql, '
FROM sms.hotelings h, sms.hotelingtime t
GROUP BY t.Time');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT * FROM table2;
DROP TEMPORARY TABLE table2;