I have a trigger running on my Asterisk "cel" table with a bunch of conditions. It appears that this condition prevents the record I am trying to catch from being inserted into the "cel" table.
Here is the trigger's condition:
IF (NEW.eventtype = 'CHAN_START' AND CHAR_LENGTH(NEW.cid_num) > 4 AND NEW.cid_ani = '' AND NEW.cid_rdnis = '' AND NEW.cid_dnid = '' AND CHAR_LENGTH(NEW.exten) > 4) THEN
INSERT INTO mem_callers VALUES (NEW.linkedid, NEW.eventtype, NEW.cid_num, NEW.exten, NEW.exten, NEW.eventtime);
END IF;
This is supposed to insert a record in my "mem_callers" table, but with this condition in my trigger, the "CHAN_START" record is never inserted into the "cel" table.
What am I doing wrong here?
Ok, it appears to be misbehaving because I'm doing something stupid.
I added another column to the "mem_callers" table earlier and my INSERT statement in that condition did not include a value for the new column.
Once I've added a value both tables inserted the correct records.
Related
I am writing a trigger to keep track of all the changes that happens in a table. Unfortunately the table has 150+ columns and I wanted to avoid writing each column in the code (Ex. new.col1, new.col2....) and thus I wrote a following query in "after update trigger"
INSERT INTO logs SELECT *, NOW() FROM abc WHERE abc.id = NEW.Id;
This idea is causing multiple issue due to duplication of data that is not changed in update query.
In a nutshell I want to dynamically find out which columns were part of the update query and if that is not possible is there a way to iterate through all the columns of "new" row so I can dynamically compare old.#colName == new.#colName?
I have already seen
Oracle PL/SQL: Loop Over Trigger Columns Dynamically, How to determine if anything changed in update trigger in t-sql and MySQL UPDATE trigger: INSERTing the values of the columns that actually changed.
The last link is the closes to what I need with only one difference, I don't want to hard code column names in following statment because I have way over 100+ columns in all the tables I am going to write similar trigger for!!
IF NEW.column1 <> OLD.column1 THEN INSERT INTO... END IF; IF NEW.column2 <> OLD.column2 THEN INSERT INTO... END IF
I've been doing a bit of research on this this morning and looks like I have come across much of the same search results as you. Ultimately it looks to me like there's no way to loop over all table columns and reference the corresponding old/new values. I'm settling on explicitly checking each column and then logging:
IF (NEW.fld1 <> OLD.fld1) OR (NEW.fld1 IS NOT NULL AND OLD.fld1 IS NULL) OR (NEW.fld1 IS NULL AND OLD.fld1 IS NOT NULL) THEN
INSERT INTO `fld_audit` (`table`, `fldname`, `oldval`, `newval`)
VALUES ("tblname", "fld1", OLD.fld1, NEW.fld1);
END IF;
IF (NEW.fld2 <> OLD.fld2) OR (NEW.fld2 IS NOT NULL AND OLD.fld2 IS NULL) OR (NEW.fld2 IS NULL AND OLD.fld2 IS NOT NULL) THEN
INSERT INTO `fld_audit` (`table`, `fldname`, `oldval`, `newval`)
VALUES ("tblname", "fld2", OLD.fld2, NEW.fld2);
END IF; ...
I found an inkling of another solution here. In theory you could have 3 delimited lists, one for column names, one for old vals and one for new vals. You would have to explicitly reference the old and new vals, but that would be one line (easier to maintain or copy/paste to implement on other tables) and you could then loop. So in pseudo code it would look something like this:
fields_array = concat_ws(",", "fld1", "fld2");
old_vals_array = concat_ws(",", OLD.fld1, OLD.fld2);
new_vals_array = concat_ws(",", NEW.fld1, NEW.fld2);
foreach fields_array as key => field_name
INSERT INTO `fld_audit` (`table`, `fldname`, `oldval`, `newval`)
VALUES ("tblname", field_name, old_vals_array[key], vew_vals_array[key]);
I haven't thought this through too much. You might need to call into a stored procedure rather than set variables. But it might be worth looking into. I've spent enough time on my triggers already. Not sure I could validate (to my boss) trial and error time on a more elegant solution.
As ingratiatednerd already suggested, you can use CONCAT_WS to make strings out of all required values and make a single compare statement.
Perhaps the following is useful to someone:
DECLARE old_concat, new_concat text;
SET old_concat = CONCAT_WS(',', OLD.fld1, OLD.fld2, ...);
SET new_concat = CONCAT_WS(',', NEW.fld1, NEW.fld2, ...);
IF old_concat <> new_concat
THEN
INSERT STATEMENT
END IF;
I have rails application and its using mysql.
I have a piles table with two columns that I care for.
The columns are name_he_il and name_en_us
I don't have a problem doing these
select name_he_il from piles;
select name_en_us from piles;
I need to insert data into the name_he_il column into the piles table where name_en_us = "a specific value"
I tried something like this
insert into piles (name_he_il) values 'לא מאפיין כלל' where name_en_us = "Extremely Uncharacteristic";
I am getting syntax error.
I was googling and I figured the sql should be
insert into table (column 1) values (blah) where conditions;
but its not working.
Basically that hebrew text means extremely uncharacteristic.
You want to use UPDATE ... WHERE
INSERT is for creating new records only.
Do UPDATE and not INSERT:
UPDATE piles SET name_he_il = 'לא מאפיין כלל' WHERE name_en_us = "Extremely Uncharacteristic";
Insert query is to insert new rom into table. If you already have row with value of "name_he_il" column then you need to use update.
UPDATE piles SET name_he_il='new value' WHERE name_he_es = 'something'
I just want to store records in two way.
If it exists, it will update information
If it dosn't exist, it will insert as new record
Here are the outline schemas for my tables:
product_purchase_item has product_purchase_item_id, product_id, quantity columns
product_stock has product_stock_id, product_id, product_total_quantity columns
I was creating a trigger
DELIMITER //
CREATE TRIGGER store_check AFTER INSERT ON product_purchase_item
FOR EACH ROW
BEGIN
DECLARE X INTEGER;
SET X =(SELECT product_id FROM product_stock where product_id = NEW.product_id);
IF NEW.product_id !=X THEN
INSERT INTO product_stock VALUES(NULL,NEW.product_id,NEW.quantity);
ELSE
UPDATE product_stock
SET product_total_quantity=product_total_quantity+NEW.quantity
WHERE product_id=NEW.product_id;
END IF;
END;//
DELIMITER;//
The problem is in product_stock table, INSERT query doesn't work when product record not exist, but update query work does properly when product record does exist.
Is it really the INSERT statement that "doesn't work"? Or, is the problem that the INSERT statement is not being executed at all?
What happens when the preceding SELECT query does not return a row? What value gets assigned to X?
When X has that value, does a conditional test "foo != X" return TRUE, or does it return something else (like FALSE, or NULL)?
Have you tried something like this?
IF NEW.product_ID = X THEN
UPDATE ...
ELSE
INSERT ...
END IF;
(I know it's bad practice to answer a question with a question; but it seemed apropros, since answering those will get you the answer to the question you really wanted to ask.)
You can do the desired operation through one of MySQL's standard commands:
INSERT INTO product_stock (product_id,product_total_quantity)
VALUES (NEW.product_id,NEW.quantity)
ON DUPLICATE KEY UPDATE product_total_quantity=product_total_quantity+NEW.quantity;
see the MySQL manual
I tried to insert from one table into another and im having with the redundancy..
I came up with a query but every time when i execute it, It cannot deals with duplicate.
here's my query...
INSERT INTO balik ( balik_date, balik_time, balik_cardID, balik_status,balik_type)
select current_date(), '00:00:00', L_CardID, 'BELUM BALIK', L_Type
FROM logdetail t1
LEFT JOIN balik t2 ON (t1.L_CardID = t2.balik_cardID)
WHERE t1.L_Type = 'IN'
any help will be greatly appreciated
Use INSERT IGNORE instant of INSERT.
Use INSERT IGNORE rather than INSERT. If a record doesn't duplicate an
existing record, MySQL inserts it as usual. If the record is a
duplicate, the IGNORE keyword tells MySQL to discard it silently
without generating an error.
OR
Check row count for unique field. If row exist don't insert or update.
OR
Use REPLACE rather than INSERT. If the record is new, it's inserted
just as with INSERT. If it's a duplicate, the new record replaces the
old one:
Source for definitions MySQL Handling Duplicates
I know I'm missing something obvious here. This trigger is updating all rows in the table (killing performance) when all I want it to do is perform the update on the new inserted row.
CREATE TRIGGER [dbo].[update_location_topo_name]
--fires at each row insert, queries topo map layer (must be present!) and inserts name of topo into new location record
on [dbo].[TBL_LOCATIONS]
after insert
AS
BEGIN
update TBL_LOCATIONS
set TOPO_NAME = dbo.QD24K_GRSM.NAME
FROM dbo.tbl_locations
inner join dbo.QD24K_GRSM
on TBL_LOCATIONS.Location_ID = TBL_LOCATIONS.Location_ID
WHERE (QD24K_GRSM.Shape.STContains(TBL_LOCATIONS.SHAPE) = 1)
END
You need to reference the INSERTED pseudo table to get only the rows that were inserted.
Additionally your join condition of TBL_LOCATIONS.Location_ID = TBL_LOCATIONS.Location_ID makes no sense at all.
Probably better to do this as an INSTEAD OF trigger to modify the rows before insert rather than after they are inserted.
CREATE TRIGGER [dbo].[update_location_topo_name]
ON [dbo].[TBL_LOCATIONS]
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO TBL_LOCATIONS
(foo,
bar,
TOPO_NAME)
SELECT foo,
bar,
dbo.QD24K_GRSM.NAME
FROM INSERTED I
LEFT JOIN dbo.QD24K_GRSM
ON QD24K_GRSM.Shape.STContains(I.SHAPE) = 1/* Will insert additional
rows if more than one match*/
END
I would suggest to create trigger "Instead of Insert" rather than "After Insert".
That way you can modify newly inserted rows as you need before actually inserting them in target table.
And there is absolutely no need to join "inserted" table with target table.
Something like this (syntax might be wrong as not actually run that code):
CREATE TRIGGER [dbo].[update_location_topo_name]
on [dbo].[TBL_LOCATIONS]
Instead Of insert
AS
BEGIN
Insert Into TBL_LOCATIONS (...., TOPO_NAME)
Select ..., CrTable.NAME as TOPO_NAME
From Inserted Cross Apply
(
Select top 1 QD24K_GRSM.NAME from QD24K_GRSM where
QD24K_GRSM.Shape.STContains(Inserted.SHAPE) = 1
) as CrTable
END