I am trying to create a trigger (this is my first trigger, and question, so be gentle) that will insert new rows into two different tables.
* Edit *
Adding this in as I forgot to mention it until ypercube answered.
I am trying to avoid listing all of the column names, as in the real world usage the table this will be used on has a very large number of columns (not my design, too late to refactor).
* End Edit *
Here's what I have so far.
CREATE TABLE test_table (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
message VARCHAR(255)
);
CREATE TABLE test_table_copy LIKE test_table;
DELIMITER $$
CREATE TRIGGER copy_test_table_data AFTER INSERT ON test_table
FOR EACH ROW
BEGIN
INSERT INTO test_table_copy SELECT * FROM NEW;
END;$$
DELIMITER ;
Unfortunately this results in an error.
mysql> INSERT INTO test_table VALUES (1, 'This is a message');
ERROR 1146 (4502): Table 'test_db.NEW' doesn't exist
I am not quite sure what the problem is, I thought NEW referred the table data was being inserted into?
You could possibly get a list of column names in that table from information_schema views, then use them to create a prepared statement (using cursor to iterate column names) and CONCAT() function to glue together the query string. Then execute the prepared statement.
Seems very contrived even to me, and I'm not sure it would work (and if it did, how efficient it would be)
Related
Im trying to get this program to add a new row into two different tables: bilde and student.
The values entered into bilde should come from the values used in student.
At this point i get this message: error code: 1136. Column count dosen't match value at row 1, and im not quite sure what to do to fix this.
DELIMITER $$
DROP PROCEDURE IF EXISTS NyStudent $$
CREATE PROCEDURE NyStudent (
brukernavn VARCHAR(45)
,fornavn VARCHAR(45)
,etternavn VARCHAR(45)
,klassekode INT
)
BEGIN
START TRANSACTION;
INSERT INTO bilde (filnavn, beskrivelse)
VALUES (CONCAT('bilder/', fornavn, '.jpg'), CONCAT('bilde av ', fornavn, ' ', etternavn));
INSERT INTO student
VALUES ('donaldduck','donald','duck','1');
COMMIT;
END$$
DELIMITER ;
CALL NyStudent('donaldduck','donald','duck','1');
Try adding the column names in the 'INSERT INTO' statement for students, as that should be the major reason for column count error.
Also, Even when we insert values for every column of the table, it is a best practice to include column names after INSERT INTO statement. Following this would avoid any breakage in code to a certain extent, even on schema changes in the future.
Within a MySQL 8 database I have two identical tables in different schemas with one being used as a staging table for its equivalent production table. The tables contain 200+ columns with more to be added in the future, making explicitly defining values for column names difficult.
I need to INSERT or UPDATE values in the production table with those in the staging table using an AFTER INSERT trigger, where all values of a row within the production table are replaced upon the existence of a duplicate PRIMARY KEY. Note that the production table has its PRIMARY KEY defined.
After this, I should delete all rows from the staging table.
Here is the code I have tried:
CREATE TRIGGER stage.my_table_after_insert AFTER INSERT ON my_table
FOR EACH ROW
BEGIN
REPLACE INTO prod.my_table
SELECT * FROM new;
DELETE FROM stage.my_table
END
I don't get why are You doing so, but why arent you doing something like:
REPLACE INTO prod.my_table
SELECT * FROM stage.my_table;
DELETE FROM stage.my_table;
You cant alter a table within its own contained trigger. Additionally, using a trigger will execute all SQL statements once per row (inefficient in this case). Therefore, a procedure is instead used to perform the required functions, using the following:
DELIMITER $$
CREATE PROCEDURE stage.load_data()
BEGIN
REPLACE INTO prod.my_table
SELECT * FROM stage.my_table;
DELETE FROM stage.my_table;
END$$
DELIMITER ;
I'm running a wateranalyzer and want to save the sensor-data in a MariaDB.
I split the data into 2 tables: one for the automated part and one table which stores data I enter manually:
Tables:
I'm having a hard time (with just basic knowledge about databases) to figure out how I can "bind" ID and DateTime from one table to the other one, so if manual data is added, ID is incremented by 1 and the actual Date and Time is set in DateTime.
I bet I can do this somehow in PHPmyadmin?
thanks for your time!
using triger. this example for you.
DELIMITER //
CREATE TRIGGER contacts_after_insert
AFTER INSERT
ON contacts FOR EACH ROW
BEGIN
DECLARE vUser varchar(50);
-- Find username of person performing the INSERT into table
SELECT USER() INTO vUser;
-- Insert record into audit table
INSERT INTO contacts_audit
( contact_id,
deleted_date,
deleted_by)
VALUES
( NEW.contact_id,
SYSDATE(),
vUser );
END; //
DELIMITER ;
Is it anything more complex than having an ID in Wasser that matches the other ID? That is, first insert into Luft, then get the id and only then, INSERT INTO Wasser....
(A Trigger seems unnecessarily complicated.)
As Rick Suggested, you need to have an ID column in the second table that references ID in first table. Trigger is a better option if the process of getting the ID and inserting it along with other columns (pH, Redox...) into the second table is complicated.
Make ID in the second table as a foreign key to the ID in first table.
I can't seem to get one of the triggers im trying to make to work at the moment it looks like this (has been messed around with alot in an attempt to get it to work so probably doesn't make any sense now)
CREATE TRIGGER `insertproductebay` AFTER INSERT ON `product`
FOR EACH ROW INSERT INTO eBayLinked
(product_id,company_id,eBay_ID,ebay_token_id,ebay_username)
SELECT ebay_token_id,ebay_username
FROM
'company'
WHERE
'company_id' = 'company_id'
VALUES
(NEW.product_id,NEW.company_id,NEW.eBay_ID,ebay_token_id,ebay_username)
The following makes it past the 1065 error
Care must be taken to use back-ticks around table and column names, and not to use single quotes there.
drop trigger if exists `insertproductebay`;
DELIMITER $$
CREATE TRIGGER `insertproductebay` AFTER INSERT ON `product`
FOR EACH ROW
INSERT INTO eBayLinked
(product_id,company_id,eBay_ID,ebay_token_id,ebay_username)
SELECT NEW.product_id,NEW.company_id,NEW.eBay_ID,ebay_token_id,ebay_username
FROM `company`
WHERE `company_id` = 'company_id'
$$
DELIMITER ;
The remaining problem as I see it could be what are you meaning by
WHERE `company_id` = 'company_id'
in a trigger. Because a trigger is a faceless piece of code that runs in the background, succeeding or failing silently. In other words, there is no user interface associated with it.
You can't mix the INSERT ... SELECT and INSERT ... VALUES syntaxes in that way. However, you can provide literal values in a select list, thusly:
CREATE TRIGGER insertproductebay AFTER INSERT ON product FOR EACH ROW
INSERT INTO eBayLinked
(product_id, company_id, eBay_ID, ebay_token_id, ebay_username)
SELECT NEW.product_id, NEW.company_id, NEW.eBay_ID, ebay_token_id, ebay_username
FROM company
WHERE company_id = NEW.company_id
I'm having a problem with my sql query. I need to insert a data that needs to be checked first if it is existing or not. If the data is existing the sql query must return it, if not insert and return it. I already google it but the result is not quite suitable to my problem. I already read this.
Check if a row exists, otherwise insert
How to 'insert if not exists' in MySQL?
Here is a query that' I'm thinking.
INSERT INTO #tablename(#field, #conditional_field, #field, #conditional_field)
VALUES(
"value of field"
(SQL QUERY THAT CHECK IF THERE IS AN EXISTING DATA, IF NOT INSERT THE DATA and RETURN IT, IF YES return it),
"value of feild",
(SQL QUERY THAT CHECK IF THERE IS AN EXISTING DATA, IF NOT INSERT THE DATA and RETURN IT, IF YES return it)
);
Please take note that the conditional field is a required field so it can't be NULL.
Your tag set is quite weird, I'm unsure you require all the technologies listed but as long as Firebird is concerned there's UPDATE OR INSERT (link) construction.
The code could be like
UPDATE OR INSERT INTO aTable
VALUES (...)
MATCHING (ID, SomeColumn)
RETURNING ID, SomeColumn
Note that this will only work for PK match, no complex logic available. If that's not an option, you could use EXECUTE BLOCK which has all the power of stored procedures but is executed as usual query. And you'll get into concurrent update error if two clients execute updates at one time.
You could split it out into 2 steps
1. run a select statement to retrieve the rows that match your valus. select count (*) will give you the number of rows
2. If zero rows found, then run the insert to add the new values.
Alternatively, you could create a unique index form all your columns. If you try to insert a row where all the values exist, an error will be returned. You could then run a select statement to get the ID for this existing row. Otherwise, the insert will work.
You can check with if exists(select count(*) from #tablename) to see if there is data, but with insert into you need to insert data for all columns, so if there is only #field missing, you cant insert values with insert into, you will need to update the table and go with a little different method. And im not sure, why do you check every row? You know for every row what is missing? Are you comparing with some other table?
You can achieve it using MySQL stored procedure
Sample MySQL stored procedure
CREATE TABLE MyTable
(`ID` int, `ConditionField` varchar(10))
;
INSERT INTO MyTable
(`ID`, `ConditionField`)
VALUES
(1, 'Condition1'),
(1, 'Condition2')
;
CREATE PROCEDURE simpleproc (IN identifier INT,ConditionData varchar(10))
BEGIN
IF (SELECT ID FROM MyTable WHERE `ConditionField`=ConditionData) THEN
BEGIN
SELECT * FROM MyTable WHERE `ConditionField`=ConditionData;
END;
ELSE
BEGIN
INSERT INTO MyTable VALUES (identifier,ConditionData);
SELECT * FROM MyTable WHERE `ConditionField`=ConditionData;
END;
END IF;
END//
To Call stored procedure
CALL simpleproc(3,'Condition3');
DEMO