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
Related
I want to update a Column_A based on Column_B_DDMONTHNAMEYEAR value in mysql.The challenge here is the Column_B has dynamic name.
Trying to automate the below update query.
Update test set Column_A = (CASE when Column_B_DDMONTHNAMEYEAR = 0 then "ZERO"
when Column_B_DDMONTHNAMEYEAR =10 then "TEN"
else "OTHER" end );
Every month beginning the table test get dropped and create with Column_B_DDMONTHNAMEYEAR.
,where the DDMONTHNAMEYEAR will be last day of previous month.
When the table test created in August then the column name is <>_31JUL2021
likewise if the table created in September the column name is <>_31AUG2021
While this is a suboptimal design decision, one way to resolve the situation would be to build and execute a statement within a stored procedure:
DELIMITER ;;
DROP PROCEDURE IF EXISTS MonthlyUpdate;;
CREATE PROCEDURE MonthlyUpdate()
BEGIN
SELECT CONCAT('UPDATE `test` SET `Column_A` = (CASE WHEN `Column_B_', UPPER(DATE_FORMAT(Now(), '%d%b%Y')), '` = 0 THEN "ZERO" WHEN `Column_B_', UPPER(DATE_FORMAT(Now(), '%d%b%Y')), '` = 10 THEN "TEN" ELSE "OTHER" END);') INTO #sqlStr;
PREPARE stmt FROM #sqlStr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END ;;
DELIMITER ;
Then you can call the procedure like this:
CALL MonthlyUpdate();
You will probably want to build on this, first confirming that the dynamic column name exists, then running the prepared statement, but that's outside the scope of this answer.
I want to create a stored procedure in Mysql that removes a certain temporary table (if it exists) and then creates this temporary table in the database 'prs1'.
The procedure that I have created is this:
CREATE PROCEDURE `CrearTablaTemporal`(table_name VARCHAR(100))
BEGIN
SET #TablaTemporal = table_name;
SET #sql_query1 = CONCAT('DROP temporary table if exists ',#TablaTemporal);
PREPARE stmt1 FROM #sql_query1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
SET #sql_query2 = CONCAT('CREATE TEMPORARY TABLE IF NOT EXISTS prs1.',#TablaTemporal,' (ean13 VarChar(13)) Engine=MyISAM');
PREPARE stmt2 FROM #sql_query2;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
END
When I execute the stored procedure, no error appears but if I execute the following SQL sentence it tells me that the table does not exist:
When I execute the stored procedure from my project (created in Xojo) I don't get any error but I don't know how to check if it is created perfectly since from programs with Navicat, Valentina Studio, etc. when I check the database, the table doesn't exist.
The question is, how do I keep the table open, insert values and retrieve the query?. I explain myself, my application has the connection open permanently to the database all the time until I close the application. In my method, I start the transaction, execute the sentence that creates the temporary table (thanks to the stored procedure) and finish the transaction. I don't close the connection to the database but then I don't know how to maintain the table.
How could I solve it, please?.
Thank you very much.
Sergio
Temporary tables are only available in the session in which they were created. As soon as the connection is terminated, temporary tables are dropped.
A common usecase for using temporary tables are test frameworks, where you use temporary tables to avoid further cleanup.
Session 1:
mysql> delimiter !!
mysql> CREATE PROCEDURE CreateTable(table_name VARCHAR(100))
-> BEGIN
-> SET #a:= CONCAT("CREATE OR REPLACE TEMPORARY TABLE ", table_name, " (a int)");
-> EXECUTE IMMEDIATE #a;
-> END!!
Query OK, 0 rows affected (0,01 sec)
mysql> delimiter ;
mysql> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
| 4118 |
+-----------------+
1 row in set (0,00 sec)
mysql> describe foobar;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| a | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
1 row in set (0,00 sec)
Session 2:
mysql> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
| 4119 |
+-----------------+
1 row in set (0,01 sec)
mysql> describe foobar;
ERROR 1146 (42S02): Table 'test.foobar' doesn't exist
So in case you need to check integrity or content of a temporary table, you need to do that either within the same connection or you have use non temporary tables.
Finally I have the solution with the help of all those who have written to me. I program in Xojo so the queries to the database are made from this program. With Georg's help I have realized that the temporary table only exists in that session and if you close it, the temporary table is deleted. This is how I solved my problem.
I have created a method with these steps:
// Start the transaction
DB.SQLExecute("START TRANSACTION")
// Drop the temporary table if it exists and if not we create it.
We must use these two SQL sentences:
'DROP temporary table if exists #TemporalTable'
'CREATE temporary table if NOT exists #TablaTemporal(field1 VarChar(13))
// OPTIONAL: check if the created time table exists (see below)
// Insert the values into the temporary table
Dim stmSQL As String
DB.SQLExecute("START TRANSACTION")
stmSQL = "INSERT INTO #TablaTemporal(field1)"
stmSQL = stmSQL + " VALUES(?)"
Dim ps As MySQLPreparedStatement = DB.Prepare(stmSQL)
If BBDD.Error = True Then MsgBox DB.ErrorMessage
ps.BindType( 0, MySQLPreparedStatement.MYSQL_TYPE_STRING)
ps.Bind( 0, field1)
ps.SQLExecute
DB.Commit
Return Not DB.Error
//Recover the results of the consultation against the time table
Dim stmSQL As String = "SELECT * FROM #Template"
Return DB.SQLSelect( stmSQL )
//Drop the temporary table
DROP temporary table if exists 'Temporary Table
// Finish the transaction
DB.CommitTransaction
To check and verify if the temporary table exists, I have created a "stored procedure" in the MySQL database that has this code:
CREATE PROCEDURE check_table_exists(table_name VARCHAR(100))
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET #err = 1;
SET #err = 0;
SET #table_name = table_name;
SET #sql_query = CONCAT('SELECT 1 FROM ',#table_name);
PREPARE stmt1 FROM #sql_query;
IF (#err = 1) THEN
SET #table_exists = 0;
ELSE
SET #table_exists = 1;
DEALLOCATE PREPARE stmt1;
END IF;
END
Then from Xojo we only have to call the procedure with this code:
Dim stmSQL As String = "CALL check_table_exists('#TableTemporal')""
ExecuteSQL(stmSQL) database
And execute this SQL query:
Dim stmSQL As String = "SELECT #table_exists"
Return DB.SQLSelect(stmSQL)
If the result is '1', the table has been created and exists; and if it is '0', the table does not exist.
I hope this can help someone... in my case it was for pure self-learning.
A greeting,
Sergio
I have main_table:
SELECT PORT_ID, DATA from main_table
i need run trigger AFTER INSERT main_table which sort DATA to the other tables:
INSERT INTO #PORT_ID (DATA) VALUE (#DATA)
return an error message:
dynamic sql is not allowed in stored function or trigger resolved.
Any idea?
Many thanks
Workarround
I do a simply workarround, 1, save a SQL query into new table as a whole text. 2, run an EVENT per second with EXECUTE saved query
This is to big for a comment.
A simple Procedure that only executes the insert as prepared statement
CREATE DEFINER=`root`#`localhost` PROCEDURE `procedure_stmt`(IN test TEXT)
BEGIN
SET #sql = test;
PREPARE stmt2 FROM #sql;
EXECUTE stmt2;
END
ANd as a trigger
BEGIN
SET #sql = CONCAT('INSERT INTO ','gps_', NEW.PORT,' (DATA) VALUES (',NEW.DATTA,')');
CALL procedure_stmt(#sql);
END$$
DELIMITER ;
If you had posted tables and data i would have tested it further.
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
I have a stored procedure in MySQL that calls a function that inserts values into a table.
The insert statement is like
INSERT INTO Table1 SELECT * from Table2
Table2 has a variable name, depending on the date the procedure is called, like
table_201410 , if the procedure was called in October 2014. Soevery month, the procedure should make the select from another table.
I have read some answers about preparing and executing, however as I am new to MySQL/Programming. I am a bit lost.
You can use a prepared statement like this:
DELIMITER $$
DROP PROCEDURE copy_table $$
CREATE PROCEDURE copy_table ()
BEGIN
set #table_name = date_format(now(),'%Y%m'); -- getting year and month
-- concatenating
set #sql = concat('INSERT INTO Table1 SELECT * from table_',#table_name);
-- creating a prepared statement and executing
PREPARE insert_stmt FROM #sql;
EXECUTE insert_stmt;
DEALLOCATE PREPARE insert_stmt;
END$$
DELIMITER ;