combine two before insert on triggers mysql - mysql

I have a pair of triggers on one table that concat 3 columns into one. I need to do this same thing with different formatting into another column. Mysql tells me i cant have the same trigger at the same time. Is there a way to combine the two sets of triggers so that they are each calling two things? I have looked for this and cant seem to find an answer or figure it out. Just adding the SET call into it throws the error. Thanks
Here are the current working triggers if they are seperated.
Set 1
CREATE TRIGGER combinedDescNameinsert_trigger
BEFORE INSERT ON markers
FOR EACH ROW
SET new.combinedDescName = CONCAT(new.descName, '-', new.DoorGroupID, '-', new.DoorID);
CREATE TRIGGER combinedDescNameupdate_trigger
BEFORE UPDATE ON markers
FOR EACH ROW
SET new.combinedDescName = CONCAT(new.descName, '-', new.DoorGroupID, '-', new.DoorID);
Set 2
CREATE TRIGGER combinedDoorNameinsert_trigger
BEFORE INSERT ON markers
FOR EACH ROW
SET new.combinedDoorName = CONCAT(new.descName, ' - DoorGroupID: ', new.DoorGroupID, ' - DoorID: ', new.DoorID);
CREATE TRIGGER combinedDoorNameupdate_trigger
BEFORE UPDATE ON markers
FOR EACH ROW
SET new.combinedDoorName = CONCAT(new.descName, ' - DoorGroupID: ', new.DoorGroupID, ' - DoorID: ', new.DoorID);

Just like, IF...THEN, LOOP, stored procedures, etc... triggers with multiple statements must enclose them in BEGIN...END. Since such statements need terminated themselves, the delimiter must be temporarily changed to differential between body statements' ends and the end of the trigger itself.
DELIMITER $$
CREATE TRIGGER combinedDescNameinsert_trigger
BEFORE INSERT ON markers
BEGIN
FOR EACH ROW
SET new.combinedDescName = CONCAT(new.descName, '-', new.DoorGroupID, '-', new.DoorID);
SET new.combinedDoorName = CONCAT(new.descName, ' - DoorGroupID: ', new.DoorGroupID, ' - DoorID: ', new.DoorID);
END$$
CREATE TRIGGER combinedDescNameupdate_trigger
BEFORE UPDATE ON markers
FOR EACH ROW
BEGIN
SET new.combinedDescName = CONCAT(new.descName, '-', new.DoorGroupID, '-', new.DoorID);
SET new.combinedDoorName = CONCAT(new.descName, ' - DoorGroupID: ', new.DoorGroupID, ' - DoorID: ', new.DoorID);
END$$
DELIMITER ;

Related

How to loop through all the tables on a database to update columns

I'm trying to update a column (in this case, a date) that is present on most of the tables on my database. Sadly, my database has more than 100 tables already created and full of information. Is there any way to loop through them and just use:
UPDATE SET date = '2016-04-20' WHERE name = 'Example'
on the loop?
One painless option would be to create a query which generates the UPDATE statements you want to run on all the tables:
SELECT CONCAT('UPDATE ', a.table_name, ' SET date = "2016-04-20" WHERE name = "Example";')
FROM information_schema.tables a
WHERE a.table_schema = 'YourDBNameHere'
You can copy the output from this query, paste it in the query editor, and run it.
Update:
As #PaulSpiegel pointed out, the above solution might be inconvenient if one be using an editor such as HeidiSQL, because it would require manually copying each record in the result set. Employing a trick using GROUP_CONCAT() would give a single string containing every desired UPDATE query in it:
SELECT GROUP_CONCAT(t.query SEPARATOR '; ')
FROM
(
SELECT CONCAT('UPDATE ', a.table_name,
' SET date = "2016-04-20" WHERE name = "Example";') AS query,
'1' AS id
FROM information_schema.tables a
WHERE a.table_schema = 'YourDBNameHere'
) t
GROUP BY t.id
You can use SHOW TABLES command to list all tables in database. Next you can check if column presented in table with SHOW COLUMNS command. It can be used this way:
SHOW COLUMNS FROM `table_name` LIKE `column_name`
If this query returns result, then column exists and you can perform UPDATE query on it.
Update
You can check this procedure on sqlfiddle.
CREATE PROCEDURE UpdateTables (IN WhereColumn VARCHAR(10),
IN WhereValue VARCHAR(10),
IN UpdateColumn VARCHAR(10),
IN UpdateValue VARCHAR(10))
BEGIN
DECLARE Finished BOOL DEFAULT FALSE;
DECLARE TableName VARCHAR(10);
DECLARE TablesCursor CURSOR FOR
SELECT c1.TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS c1
JOIN INFORMATION_SCHEMA.COLUMNS c2 ON (c1.TABLE_SCHEMA = c2.TABLE_SCHEMA AND c1.TABLE_NAME = c2.TABLE_NAME)
WHERE c1.TABLE_SCHEMA = DATABASE()
AND c1.COLUMN_NAME = WhereColumn
AND c2.COLUMN_NAME = UpdateColumn;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET Finished = TRUE;
OPEN TablesCursor;
MainLoop: LOOP
FETCH TablesCursor INTO TableName;
IF Finished THEN
LEAVE MainLoop;
END IF;
SET #queryText = CONCAT('UPDATE ', TableName, ' SET ', UpdateColumn, '=', QUOTE(UpdateValue), ' WHERE ', WhereColumn, '=', QUOTE(WhereValue));
PREPARE updateQuery FROM #queryText;
EXECUTE updateQuery;
DEALLOCATE PREPARE updateQuery;
END LOOP;
CLOSE TablesCursor;
END
This is just an example how to iterate through all tables in database and perform some action with them. Procedure can be changed according to your needs.
Assuming you are using MySQL, You can use Stored Procedure.
This post is a very helpful.
Mysql-loop-through-tables

Cannot create trigger in mysql at phpmyadmin

I'm trying to create an ID by combining fields after a row has been inserted into the database in phpmyadmin. I get an error on line 3 of the following trigger statement:
DROP TRIGGER IF EXISTS `scanID2`;
CREATE DEFINER=`root`#`localhost`
TRIGGER `scanID2`
AFTER INSERT ON db_name.`scan_data`
FOR EACH ROW
BEGIN
UPDATE db_name.scan_data
SET #data1 = concat(RIGHT(scanContent,2), RIGHT(operatorID,2), RIGHT(deviceID,2), RIGHT (scanDate, '-', ''), REPLACE (scanTime, ':', ''));
INSERT INTO db_name.scan_data(scanID) VALUES (#data1);
END
//
The error is:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE DEFINER=`root`#`localhost`
TRIGGER `scanID2`
AFTER INSERT ON db_name' at line 2
OK, so I figured how to get the query executed. The trigger has been created but I don't think it does what it's supposed to do. The records don't get updated. Here's the new code:
BEGIN
SET #data1 = concat(RIGHT(scanContent,2), RIGHT(operatorID,2), RIGHT(deviceID,2), REPLACE (scanDate, '-', ''), REPLACE (scanTime, ':', ''));
INSERT INTO vacseen1_connect.scan_data(scanID) VALUES (#data1);
END
There are several things to consider:
Use BEFORE event for the trigger instead of AFTER. This way you can set the value of scanID the same time a row is being inserted.
Use NEW keyword to access fields of a row being inserted.
Since it's one statement trigger now you don't need to change delimiter and use BEGIN ... END block.
You most likely meant to use REPLACE for scanDate.
Try
CREATE TRIGGER scanID2
BEFORE INSERT ON scan_data
FOR EACH ROW
SET NEW.scanID = CONCAT(
RIGHT(NEW.scanContent, 2),
RIGHT(NEW.operatorID, 2),
RIGHT(NEW.deviceID, 2),
REPLACE(NEW.scanDate, '-', ''),
REPLACE (NEW.scanTime, ':', '')
);
Here is a SQLFiddle demo

MySQL Trigger to Auto-Update (or insert) Column Field

I have an SQL query I can run that looks like:
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ' ', 1), ' ', -1) AS first_name,
If( length(name) - length(replace(name, ' ', ''))>1,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ' ', 2), ' ', -1) ,NULL)
as middle_name,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ' ', 3), ' ', -1) AS last_name
FROM people
While this is works great to split up the full name into first_name, middle_name, and last_name I need a way to have this done automatically; can't go in and run the query and manually update the table each time a person is added.
I've tried to play around with this query in the form of a trigger but keep getting errors, generally the error states "Not allowed to return a result set from trigger"
Any help getting this working would be great
In a BEFORE INSERT trigger, use the qualifier NEW. to reference values assigned to columns of the row being inserted. For example, NEW.col would reference the value supplied for the column col.
Assign a value (or expression) to NEW.col to replace the value supplied for column col, and the value assigned will be inserted instead.
A trigger to accomplish something similar to SELECT statement would look something like this:
DELIMITER $$
CREATE TRIGGER mytrigger
BEFORE INSERT ON mytable
FOR EACH ROW
BEGIN
SET NEW.first_name = SUBSTRING_INDEX(SUBSTRING_INDEX( NEW.name, ' ', 1), ' ', -1);
SET NEW.last_name = SUBSTRING_INDEX(SUBSTRING_INDEX( NEW.name, ' ', 3), ' ', -1);
SET NEW.middle_name = IF(LENGTH( NEW.name) - LENGTH(REPLACE( NEW.name, ' ', ''))>1
,SUBSTRING_INDEX(SUBSTRING_INDEX( NEW.name, ' ', 2), ' ', -1)
,NULL);
END$$
DELIMITER ;
The error you are getting:
Error: 1415 SQLSTATE: 0A000 (ER_SP_NO_RETSET)
Message: Not allowed to return a result set from a %s
Is due to a documented restriction that applies to both FUNCTION and TRIGGER. (This restriction also applies to a PROCEDURE that is called from the context of a FUNCTION or TRIGGER.)

Check MySQL database for unique value over many tables

I'm looking for a way to easily check each table of a MySQL database and make sure that a certain field contains one value only. I have tables named Authors, Titles, Places, etc.
Each table contains a field called xuser and it needs to ask "does the field xuser contain the value xy in all records of all tables".
Can someone push me in the right direction how to do this with a SQL query if this is possible?
Thanks for reading, regards
Nico
I've created stored procedure which checks all table for provided db:
DELIMITER $$
DROP PROCEDURE IF EXISTS `UTL_CHECK_BACKUP_FOR_USER` $$
CREATE PROCEDURE `UTL_CHECK_BACKUP_FOR_USER`(
IN i_database_name VARCHAR(255),
IN i_user_column_name VARCHAR(255),
IN i_user_column_value VARCHAR(255),
OUT o_result TINYINT(1)
)
BEGIN
DECLARE v_table_name VARCHAR(255);
DECLARE v_last_row_fetched TINYINT(3) DEFAULT 0;
DECLARE tables_cursor CURSOR FOR
SELECT table_name
FROM information_schema.tables
WHERE table_schema = i_database_name
;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_last_row_fetched = 1;
SET v_last_row_fetched = 0;
OPEN tables_cursor;
SET #query =
CONCAT(
'SELECT SUM(IF(user_column=''',
i_user_column_value,
''', 1, -1)) = 1 INTO #o_result FROM ( SELECT ''test'' AS user_column FROM information_schema.tables WHERE 1<>1 '
)
;
table_loop: LOOP
FETCH tables_cursor INTO v_table_name;
IF (v_last_row_fetched = 1) THEN
LEAVE table_loop;
END IF;
SET #query =
CONCAT(
#query,
' UNION SELECT DISTINCT(',
i_user_column_name,
') AS user_column FROM ',
v_table_name
)
;
END LOOP table_loop;
CLOSE tables_cursor;
SET v_last_row_fetched=0;
SET #query =
CONCAT(
#query,
' ) all_xusers;'
)
;
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET o_result = COALESCE(#o_result, 0);
END $$
DELIMITER ;
Just deploy this stored procedure to database.
And then it could be executed in the following way:
-- db_name, user_column_name, user_column_value, result
call UTL_CHECK_BACKUP_FOR_USER('test', 'xuser', 'xxx', #result);
select #result;
To get the rows from all three tables where xuser has the same value in all three tables you could use:
SELECT *
FROM authors a
JOIN titles t
ON t.xuser = a.xuser
JOIN places p
ON p.xuser = t.xuser
If you want to look at a specific xuser value you could add the following WHERE clause:
WHERE a.xuser = 'xy'
The first thing comes to my mind:
select sum(if(xuser='xxx', 1, -1)) = 1
from (
select distinct(xuser) from authors
union
select distinct(xuser) from titles
union
select distinct(xuser) from places
) all_xusers;
This will return 1 (true) if all tables contains records belonging ONLY to 'xxx' user. Otherwise (if there is no 'xxx' records or there is some other user records) it will return 0 (false).

MySql replacing spaces with hyphens

A day ago, I asked this question on stackoverflow. Sure, that works well, but does anyone know how I can do the same thing in a MySql statement without any php involved?
Eg: select preg_replace(:songName,' ', '-') //Ugh, this is wrong.
What I'm trying to do Is replace spaces with a -. But sometimes, when there is a space, I'll get more -
Eg: Metallica - Hero of the Day ends up as Metallica---Hero-of-the-Day
Any chance of making it just: Metallica-Hero-of-the-Day
BTW: It's not only song names I'm replacing.
I'm ok with a simple MySql replace, but I can see doing the above is going to need more than that.
I would replace spaces with hyphens first, then deal with any multiple hyphens that may have been created:
select replace(replace(replace(songTitle, ' ', '-'), '---', '-'), '--', '-')
I've replaced --- and -- separately because there are edge cases which overall would require both, and in that order.
See SQLFiddle
Use a user defined function like this(use delimetres accordingly)
CREATE FUNCTION replace_spaceWithHyphen(textToReplace varchar(100))
RETURNS TEXT
BEGIN
DECLARE occHyphen int;
DECLARE occSpace int;
set occHyphen = 1;
set occSpace = 1;
WHILE (occHyphen <> 0 || occSpace <> 0) DO
SELECT LOCATE('--',textToReplace) into occHyphen;
SELECT LOCATE(' ',textToReplace) into occSpace;
SELECT REPLACE(textToReplace,' ','-') into textToReplace;
SELECT REPLACE(textToReplace,'--','-') into textToReplace;
END WHILE;
RETURN textToReplace;
END;
Then call your select like this:
SELECT replace_spaceWithHyphen('Metallica - Hero of the Day');
Answer would be:
TEXT
Metallica-Hero-of-the-Day
SAMPLE FIDDLE
This should work:
select
replace(
replace(
replace('Metallica - Hero of the Day', '-', ' ')
, ' ', '')
, ' ', '-')
You may write your query. It is so easy for you.
Suppose you have a table named class(id, classname) with two fields. Now you insert in your table in classname field i.e. Metallica - Hero of the Day.
Now you can execute this by below given program.
mysql_connect('localhost','root','');
mysql_select_db('dbname'); // Please insert your dbname
$query = mysql_query('SELECT classname, REPLACE(classname," ","-") from class');
$record = mysql_fetch_array($query);
echo $record['REPLACE(classname," ","-")'];
It will give output. i.e. Metallica---Hero-of-the-Day.
and if you replace your query with. I have taken help from Bohemian answer for below query.
$query = mysql_query("SELECT classname, replace(replace(replace(classname, ' ', '-'), '---', '-'), '--', '') from class");
$record = mysql_fetch_array($query);
echo $record["replace(replace(replace(classname, ' ', '-'), '---', '-'), '--', '')"];
You will get result i.e. Metallica-Hero-of-the-Day
That's it. Easy.
Thanks
You can try this method.
UPDATE TABLE_NAME SET column_name = REPLACE(column_name, old_value, new_value);
For Example
UPDATE TABLENAME SET column_name = REPLACE(column_name, '-', ' ');
Hope this will helps you.