Error in creating temporary table in mysql - 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;

Related

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

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

How to use variable in drop table statement mysql?

I want to use variable name in drop table statement in mysql.
set #dropable:='table_name';
DROP TABLE IF EXISTS #dropable;
You could try using a prepared statement here:
SET #droptable := 'table_name';
SET #sql := CONCAT('DROP TABLE IF EXISTS ', #droptable);
PREPARE stmt FROM #sql;
EXECUTE stmt;

How to set the result of a query as a queryable table?

I am trying to use the result of a query as a table.
This query works fine:
SELECT date, number FROM `table_A`
The query below as well --> its result is table_B as a string of character not the table itself
SELECT nametable FROM `list_repository` WHERE id=1
But the combined one does not:
SELECT date, number FROM (SELECT nametable FROM `list_repository` WHERE id=1) A
I expect the resulting query to be
SELECT date, number FROM `table_B`
I tried to set a variable but it does not work either:
DECLARE x VARCHAR(150) ;
SET table=( SELECT `nametable` FROM `list_repository` WHERE id=1);
SELECT * from `table`. But it would not work
Thank you for your help!
Identifiers (db, table, column names etc) in SQL are static. Therefore you can't populate them at run-time. But you can build a query as a string and execute it via dynamic SQL. Something along the lines of
SET #sql = NULL;
SELECT CONCAT("SELECT * FROM ", nametable)
INTO #sql
FROM list_repository
WHERE id = 1;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
An example of wrapping it up into a stored procedure
DELIMITER //
CREATE PROCEDURE sp1 (IN id INT)
BEGIN
SET #sql = NULL;
SELECT CONCAT("SELECT * FROM ", nametable)
INTO #sql
FROM list_repository
WHERE id = id;
SELECT #sql;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END//
And then invoking it
CALL sp1(1);

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

Is there a way to test for null on all columns in a wildcard select?

PSEUDO:
select * from foo where [every column is not null]
Is there a way to do this without specifying the actual column names?
A possible solution that I can think of involves using dynamic-SQL
SELECT GROUP_CONCAT(column_name SEPARATOR ' IS NOT NULL AND ')
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_schema = SCHEMA()
AND table_name = 'foo'
GROUP BY table_name;
SET #sql = CONCAT('SELECT * FROM foo WHERE ', #sql, ' IS NOT NULL');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Here is SQLFiddle demo
Obviously it can be wrapped into a stored procedure with a parameter for a table name
DELIMITER $$
CREATE PROCEDURE sp_select_all_not_null(IN tbl_name VARCHAR(64))
BEGIN
SELECT GROUP_CONCAT(column_name SEPARATOR ' IS NOT NULL AND ')
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_schema = SCHEMA()
AND table_name = tbl_name
GROUP BY table_name;
SET #sql = CONCAT('SELECT * FROM ', tbl_name, ' WHERE ', #sql, ' IS NOT NULL');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
DELIMITER ;
And then use it
CALL sp_select_all_not_null('foo');
Here is SQLFiddle demo for that