Inserting to selected table name - mysql

I have got a table called Aliases in my MySQL database.
Looks like this:
------------------
| Id | Alias |
------------------
|1 | 'TabX' |
------------------
|2 | 'TabY' |
...
| | |
------------------
And I need to insert to those tables like this:
INSERT INTO (SELECT Alias FROM Aliases WHERE id=1) (somevalue) VALUES (value);
This doesn't work. Please help.

You can reach it with prepared statements:
SET #alias = (SELECT Alias FROM Aliases WHERE id = 1);
SET #sql = CONCAT('INSERT INTO ', #alias, ' (somevalue) VALUES (value)');
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;

You need to make PROCEDURE for that. And use prepared statements for this purpose. You need procedure like that:
DELIMITER $$
DROP PROCEDURE IF EXISTS `DB`.`INSERT_VAR`$$
CREATE DEFINER=`user`#`host` PROCEDURE INSERT_VAR(IN tableName VARCHAR(200))
BEGIN
SET #insert_query=CONCAT("INSERT INTO ", tableName, " (id) SELECT id FROM test");
PREPARE stmtInsert FROM #insertTab;
EXECUTE stmtInsert;
END$$
DELIMITER ;
You need to modify this procedure to fit your needs.

Try this
INSERT INTO table_name
SELECT Alias
FROM Aliases
WHERE id = 1

Related

dynamically build mysql insert statement within trigger

i'm trying to create a trigger within my schedule table that will automatically dump the new info into the hourmap table. the issue that i'm having is that within the hourmap table, the employee names are the column headers. this means that i have to dynamically build the column header so that the input hours are placed in the appropriate column. below is the script that im currently trying to get to work but i keep running into issues. either mysql workbench will just stop working and shut down, or when i hit apply, everything appears to run successfully, however, the trigger is never actually created.
schedule table looks like this:
------------------------------
id|project_id|employee_id|hours|
--|----------|-----------|-----|
1 | 11 | 22 |8 |
--------------------------------
hourmap table looks like this:
----------------------------------------
id|ProjectID |ScheduleID |sam|jon|smith|
--|----------|-----------|---|---|-----|
----------------------------------------
the employee table looks like this;
------------
id|Employee|
--|--------|
1 |sam |
2 |jon |
22|smith |
------------
my trigger statement looks like this:
CREATE DEFINER=`root`#`localhost` TRIGGER `projectscheduler`.`schedule_AFTER_INSERT` AFTER INSERT ON `schedule` FOR EACH ROW
SET #EMPNAME=(SELECT Employee FROM employees WHERE id = NEW.employee_id);
BEGIN
INSERT INTO hourmap (ProjectID, ScheduleID, #EMPNAME)
VALUES (NEW.project_id, NEW.id, NEW.hours);
END
here is my attempt at a stored procedure, however, still no luck.
USE `projectscheduler`$$
CREATE DEFINER=`root`#`localhost` TRIGGER `projectscheduler`.`schedule_AFTER_INSERT` AFTER INSERT ON `schedule` FOR EACH ROW
BEGIN
SET #sql = NULL;
SELECT CONCAT('SELECT Emoloyee FROM employees WHERE id = NEW.id') INTO #sql;
SET #sql = CONCAT('INSERT INTO hourmap (ProjectID, ScheduleID, `',#sql,'`) VALUES(NEW.project_id, NEW.id, NEW.hours)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
ERROR 1336: Dynamic SQL is not allowed in stored function or trigger

execute expression stored in a column

I need some help about executing expression(bitwise) stored in a column of a table.
Input :
ID | expression
----|-------------
1 | 1&0
2 | (1&1)|(0&1)
Desired Output :
ID | expression | value
----|-------------|-------
1 | 1&0 | 0
2 | (1&1)|(0&1) | 1
I am trying something like below but it is not executing the expression.
PREPARE stmt from 'select ? into #outvar';
set #invar = '1&0';
execute stmt using #invar;
select #outvar;
The output of above is 1&0 but the desired output is 0.
Actually I want to store the output in a variable as framed in my above pseudo code.
I have built you a procedure to do this
DROP TABLE IF EXISTS test10;
DROP PROCEDURE IF EXISTS `sp_test10`;
create table test10 (ID int, expression VARCHAR(20));
insert into test10 values ( 1 , '1&0');
insert into test10 values ( 2 , '(1&1)|(0&1)');
CREATE PROCEDURE sp_test10 (IN IN_ID int, OUT OUT_VAL INT)
BEGIN
SELECT expression INTO #exp FROM test10 WHERE ID=IN_ID;
SET #q = CONCAT('SELECT ',#exp,' INTO #exp ');
PREPARE stmt1 FROM #q;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
SET OUT_VAL = #exp;
END\\
;
call sp_test10(2,#result);
select #result;
Results :
call sp_test10(1,#result) returns 0
call sp_test10(2,#result) returns 1
http://rextester.com/live/SMLB31207
Using prepared statements, what are sent to server in the second round are treated literally. They can't be part of SQL. You shouldn't use placeholders for this:
SET #invar = '(1&1)&(0&1)';
SET #s = CONCAT('SELECT ', #invar, ' INTO #outvar');
PREPARE stmt FROM #s;
EXECUTE stmt;
SELECT #outvar;

MYSQL Procedure call saved query in table

That I need is
Save all of query in one table
query_id | sql_query
1 | select * from ms_user
2 | select * from ms_privileges
Create Procedure
this procedure will call
call my_procedure(query_id)
I tried the code below
DROP PROCEDURE IF EXISTS mp_test;
CREATE PROCEDURE global_procedire(IN id_query int(10));
BEGIN
SET #Query = 'SELECT sql_query from ms_query where query_id = id_query';
SET #Query = CONCAT(#Query);
PREPARE stmt FROM #Query;
EXECUTE stmt;
END

can we run code in mysql without creating a procedure

I want to create a sql file for my dba that will check whether index exists on a table. IF doesn't exist-create it.
I found many examples that use stored procedure, but I only want to run it once.
Something like this:
-- Creates an index if it does not already exist in MySQL.
START TRANSACTION;
SET IndexIsThere = 0;
SET given_table = 'IDR_CHGS';
SET given_index = 'FK_IDR_PATIENT_PT_ID_idx1';
SELECT COUNT(1) INTO IndexIsThere
FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_name = given_table
AND index_name = given_index;
IF IndexIsThere = 0 THEN
SET #sqlstmt = CONCAT('CREATE INDEX ',given_index,' ON ', given_database,'.',given_table,' (',given_columns,')');
PREPARE st FROM #sqlstmt;
EXECUTE st;
DEALLOCATE PREPARE st;
SELECT CONCAT('Created index ', given_table,'.', given_index, ' on columns ', given_columns) AS 'CreateIndex status';
ELSE
SELECT CONCAT('Index ', given_index,' Already Exists on Table ', given_database,'.',given_table) AS 'CreateIndex status';
END IF;
COMMIT;
Is this doable?
MySQL doesn't support IF/THEN/ELSE constructs outside of stored routines or triggers.
If you use PREPARE and EXECUTE, you could simply form a string that has the CREATE INDEX statement if there is no index, and a no-op statement (e.g. a comment) if not.
SELECT COALESCE(CONCAT('SELECT \'index ', S.INDEX_NAME, ' exists already\''),
'CREATE INDEX `idx_x` ON test.foo (`x`)') INTO #sql
FROM (SELECT NULL) AS d
LEFT OUTER JOIN INFORMATION_SCHEMA.STATISTICS AS S
ON (S.TABLE_SCHEMA, S.TABLE_NAME, S.INDEX_NAME) = ('test', 'foo', 'idx_x');
PREPARE s from #sql;
EXECUTE s;
If the index exists, #sql will be:
mysql> select #sql;
+-------------------------------------+
| #sql |
+-------------------------------------+
| SELECT 'index idx_x exists already' |
+-------------------------------------+
If the index does not exist, #sql will be:
mysql> select #sql;
+----------------------------------------+
| #sql |
+----------------------------------------+
| CREATE INDEX `idx_x` ON test.foo (`x`) |
+----------------------------------------+
By the way, all CREATE and ALTER statements implicitly commit before and after the statement, so there's no purpose in using start transaction and commit in the way you're doing. See http://dev.mysql.com/doc/refman/5.6/en/implicit-commit.html

find out list of inverted hierarchy in mysql

Imagine I have a table (Mysql myISAM) with a child->parent relationship (categories and multiple levels of subcategories)
+--------+---------+
| id |parent_id|
+--------+---------+
| 1 | null |
| 2 | 1 |
| 3 | 2 |
| 4 | 7 |
| 5 | 1 |
| 6 | 5 |
+--------+---------+
How would you find all children of some ID, like querying for id 1 would output :
2,5,3,6 ? (order has no importance)
So in other words, how to do a reverted children lookup on this parent_link ?
At the moment, I cycle in php and query for the parent_id, then again and concatenate all the results in a string while there are results, but this is so slow...
Ok, so thanks to Deepak code, I managed to write this, a bit shorter readable, it accepts a table as parameter and returns also the depth of the element.
DELIMITER $$
CREATE PROCEDURE get_children(IN V_KEY INT,IN SOURCETABLE VARCHAR(255))
proc:
BEGIN
DECLARE vid text;
DECLARE count int;
DROP TABLE IF EXISTS `temp_child_nodes`;
CREATE TEMPORARY TABLE temp_child_nodes(id int, depth int);
SET vid = V_KEY;
SET #val = '';
SET count = 0;
WHILE (vid is NOT NULL) DO
SET #sql = CONCAT("INSERT INTO temp_child_nodes(id,depth) SELECT id,'",count,"' from ",SOURCETABLE," where parent_id IN (",vid,")");
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
SET #tsql = CONCAT("SELECT GROUP_CONCAT(id) INTO #val from ",SOURCETABLE," where parent_id IN (", vid, ")");
PREPARE stmt2 FROM #tsql;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
SET vid = #val;
SET count = count + 1;
END WHILE;
#output data
SELECT * from temp_child_nodes;
END
$$
DELIMITER ;
create table my_table(
id int,
parent_id int
);
insert into my_table values
(1,null),
(2,1),
(3,2),
(4,7),
(5,1),
(6,5);
This stored procedure will get you all the children of any given id
DELIMITER $$
DROP PROCEDURE IF EXISTS get_children$$
CREATE PROCEDURE get_children(IN V_KEY INT)
proc:
BEGIN
DECLARE vid text;
declare oid text;
DECLARE count int;
CREATE TEMPORARY TABLE temp_child_nodes(
id int
);
SET vid = V_KEY;
INSERT INTO temp_child_nodes(id) SELECT id from my_table where parent_id = vid;
SELECT GROUP_CONCAT(concat("'",id,"'")) INTO oid from my_table where parent_id = vid;
SET vid = oid;
SET count = 0;
SET #val = '';
WHILE (vid is NOT NULL) DO
SET #sql = CONCAT("INSERT INTO temp_child_nodes(id) SELECT id from my_table where parent_id IN (",vid,")");
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
SET #tsql = CONCAT("SELECT GROUP_CONCAT(id) INTO #val from my_table where parent_id IN (", vid, ")");
PREPARE stmt2 FROM #tsql;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
SET vid = #val;
SET count = count + 1;
END WHILE;
#SELECT count;
SELECT * from temp_child_nodes;
#SELECT oid;
END
$$
DELIMITER ;
CALL get_children(1);
mysql> CALL get_children(1);
+------+
| id |
+------+
| 2 |
| 5 |
| 3 |
| 6 |
+------+
4 rows in set (0.22 sec)
Query OK, 0 rows affected (0.22 sec)
Here is the sqlfiddle demo for your query
http://sqlfiddle.com/#!2/ca90e/6
if there can be 'n' number of child then you need to use a stored procedure