MySQL Stored Procedure update using a Join and CASE..ELSE syntax - mysql

This is my first time creating a MySQL stored procedure and am stuck on getting the UPDATE piece to work correctly. The proc is performing an inner join, looking for matches on a domain name field. If there is a match, a column named inbound is getting updated with a value of 0. If there is not a match on the join, then I need inbound set to a value of 1.
When I run this, I am able to get the matches tagged with a 0, but the non-matches are not getting updated with a 1. I thought how I have the 'ELSE' part set up would take care of this- can anyone tell if I am missing something with the syntax?
CREATE PROCEDURE `sp_InboungTagging`()
BEGIN
update `tableA` a
inner join `TableD` d
on a.senderDomain = d.domainName
set inbound = CASE
when a.senderDomain = d.domainName then 0
ELSE 1
END
WHERE inbound is null;
END;|
DELIMITER ;
Thanks,
Ron
EDIT-
Thanks for your reply. I am looking for exact matches on a varchar field that has domain names in it- the master list of domains is in table D. If the record in TableA has a match in TableD, I want to tag that recored with a 0. If there is no match in TableD, then I would like to tag it with a 1. Let me know if that clears things up- thanks

Your JOIN condition is the same as your CASE condition. If you JOIN your two tables on:
a.senderDomain = d.domainName
Then there will be no values in the result set for which
a.senderDomain != d.domainName
so the ELSE clause of your CASE statement never fires.
Without knowing more about what you mean by "matches" and "non-matches," I can't really suggest a correction.

Related

SQL Server 2008 trigger update when specific column changes

Other solutions got me this far, but ultimately things are not working for me.
I have a column in tbl_activity named abstract. When tbl_activity.abstract changes, I want to set tbl_activity.flag = 0.
My 2 versions of the trigger will set flag = 0, but then I cannot set flag back to 1, because changing that flag causes it to trigger, and it keeps setting the flag = 0. I've tried comparing old to new values, deleted to inserted values, and tried INSTEAD OF INSERT.
Can someone please examine this code and tell me what I'm missing?
ALTER TRIGGER [dbo].[AbstractChange] --trigger name
ON [dbo].[cpy_activity] --table using the trigger
INSTEAD OF UPDATE, DELETE
AS
UPDATE a
SET a.flag = 0
FROM tbl_activity a
INNER JOIN INSERTED i ON a.activityid = i.activityid
INNER JOIN DELETED d ON d.activityid = i.activityid
WHERE d.abstract NOT LIKE i.abstract
This results in "Command[s] completed successfully" - but when a column other than abstract changes, the trigger always sets flag = 0. Ideas?
Not sure what the datatype of abstract is - but I'm kinda guessing that the cause of your troubles is using the NOT LIKE operator in your trigger - try this instead:
ALTER TRIGGER [dbo].[AbstractChange] --trigger name
ON [dbo].[cpy_activity] --table using the trigger
INSTEAD OF UPDATE, DELETE
AS
UPDATE a
SET a.flag = 0
FROM tbl_activity a
INNER JOIN INSERTED i ON a.activityid = i.activityid
INNER JOIN DELETED d ON d.activityid = i.activityid
WHERE d.abstract <> i.abstract -- use the usual *not equal* operator <> here
Does that change anything?
Also: why is the trigger on cpy_activity, but inside the trigger, you're using tbl_activity - seems a bit odd, really .....
since the code i posted to ask my question, contained the erroneous use of INSTEAD OF - my "answer" at this point is that i changed my tbl_activity.abstract field from type Text to type Varchar(MAX) not null. One of the original problems was that the SQL trigger would not allow use of a text field. I will post that question properly on another post. Meanwhile, this code works, in the context where the "abstract" field is type varchar:
ALTER TRIGGER [dbo].[AbstractChange] --trigger name
ON [dbo].[tbl_activity] --table using the trigger
AFTER INSERT, UPDATE
AS UPDATE a
set a.flag = 0 --target action when above table is changed
FROM tbl_activity a
INNER JOIN INSERTED i ON a.activityid = i.activityid
INNER JOIN DELETED d ON d.activityid = i.activityid
WHERE d.abstract <> i.abstract

Updating table using JOIN not working correctly

I'm doing something like this:
UPDATE `widget_list` a
JOIN `geography` b
ON b.`zip_code` = a.`zip_code`
SET b.`msa` = a.`msa`;
This executes just fine, but affects no rows. msa is set to NULL for all rows as if it wasn't changed at all. zip_code and msa are the same data types and length and definitely have overlapping zip_code. Any idea why this won't update?
EDIT: Update...I tried with a different column name and it ran as well, said that a set of my rows were affected, but none actually changed.
EDIT2: If I do this, then my msa column shows NULL for every row. Why wouldn't this value be here for a simple join?
SELECT * FROM `widget_list` a
JOIN `geography` b
ON b.`zip_code` = a.`zip_code`
Something like the below should work.
UPDATE `widget_list`
SET `msa` = (SELECT `msa` FROM `geography` b
JOIN `widget_list` a
ON `a`.`zip_code` = `b`.`zip_code`
);
Able to reproduce using this fiddle
However by changing the order on the set function it works... as in this fiddle
UPDATE `widget_list` a
JOIN `geography` b
ON b.`zip_code` = a.`zip_code`
SET a.`msa`=b.`msa` ;
and again that it should work.. implying it's a setup issue in your enviroment, or we're missing something (trigger perhaps?)
Working Fiddle Note however when mopre than one msa exists per zipcode A, X in my example for zip 123... the system simply picks one and uses it to update. X is lost in my example... are you sure that's not what's happening to you? (it's why I want to see sample data to see if it's a data issue vs syntax vs logic)
updated:
fiddle So if your source table has null values in the zipcodes you'll get null values in the destination table...
so what happens if we add....
UPDATE `widget_list` a
JOIN `geography` b
ON b.`zip_code` = a.`zip_code`
and b.msa is not null
SET a.`msa`=b.`msa` ;
and fiddle showing excluded nulls
Use from to do join.
UPDATE widget_list
SET b.msa = a.msa
FROM widget_list a JOIN geography b ON b.zip_code = a.zip_code

Copying One column from table to another table that has matching variables in another column

I hope I can explain this to make sense lol.
I am trying to copy variables from one hats_old.red to hats_new.red that match hats_new.name in both tables, if they do not match then i need it to do nothing so it does not null the value or set it to 0.
This is as far as ive gotten. This changes unmatched to 0 which i am trying to avoid and cannot figure the rest out.
This is for Mysql
Thank you
UPDATE hats_new
SET hats_new.red = (
SELECT hats_old.red
FROM hats_old
WHERE hats_old.name = hats_new.name LIMIT 1
);
An update with a join should do the trick:
UPDATE hats_new hn
JOIN hats_old ho ON hn.name = oh.name
SET hn.red = ho.red

How to set a column value equal to the value in another table?

I am trying to figure out how to update a row in one table, setting a column value equal to a value in a different table. Here's an example:
movies:
movie_id | movie_price
movies_attended:
attended_id | attended_movie_id | attended_movie_price
Now, this is kind of a stupid example, but supposed that for some reason there is a row in movies_attended that does not have the correct attended_movies_price in it and so it needs to be updated.
How should a query be written to update the movies_attended table, setting movies_attended.attended_movie_price = movies.movie_price?
I tried something similar to the following, but it did not work:
update movies_attended, movies
set movies_attended.attended_movie_price = movies.movie_price
where movies_attended.attended_movie_id = movies.movie_id
AND attended_id = [the id of the row we want to update]
When you say "it did not work", do you mean that it reported 0 rows updated, or did the statement cause the database raise an exception?
Your example statement appears to be of the form:
UPDATE movies_attended a
JOIN movies m
ON a.attended_movie_id = m.movie_id
SET a.attended_movie_price = m.movie_price
WHERE a.attended_id = ?
(We typically prefer the JOIN ... ON ... style syntax to the comma join operator and the join predicates in the WHERE clause.)
I have no explanation as to why this statement would "not work".
It's possible this would report 0 rows affected, if no rows satisfy the predicates. It would also report 0 rows affected if the rows that would be changed do not require any changes... that is, the existing value in attended_movie_price already matches the value being assigned to it.
Normally, before running an update statement like that, I write it as a SELECT first, and see what values are returned...
By replacing the UPDATE keyword with SELECT ... FROM, and removing the SET clause:
SELECT m.movie_price AS new_val
, a.attended_movie_price AS old_val
, a.attended_id
FROM UPDATE movies_attended a
JOIN movies m
ON a.attended_movie_id = m.movie_id
WHERE a.attended_id = ?
This is actually a bad database design. You don't need movie price in two tables.
But, if you just need this, it goes something along this:
UPDATE movies_attended
INNER JOIN
movies
ON movies_attended.attended_movie_id = movies.movie_id
SET movies_attended.attended_movie_price = movie.movie_price

Help with MySQL Coalesce and Stored Procedures

I'm (attempting) to write a MySQL stored procedure that parses a large text file. Part of what this procedure does is check to see if the entities (in this case, government contractors) named in each record are already contained in the db. (This is a follow up to this question.) This is my first stored procedure and so I'm sure I've wondered off the rails here, and I would appreciated any help.
Here's what I have right now (after declaring the variables):
-- try and fetch first organization (a government agency)
SET agency = COALESCE(SELECT org_agency_o_id FROM orgs_agencies WHERE org_agency_code = maj_agency_cat,SELECT min(org_id) FROM orgs WHERE org_name LIKE CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5)))
-- check to see if that worked
IF agency = NULL THEN
INSERT INTO orgs (org_name,org_name_length,org_type,org_sub_types) VALUES (CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5)),LENGTH(CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5))),'org','Org,GovernmentEntity,Federal,Agency');
SET agency = LAST_INSERT_ID();
END IF;
-- try and fetch second organization
SET org = COALESCE(SELECT MIN(org_id) FROM orgs WHERE org_name IN (vendorname, vendoralternatename, vendorlegalorganizationname, vendordoingasbusinessname), SELECT MIN(org_alias_org_id) FROM orgs_aliases WHERE org_alias in (endorname, vendoralternatename, vendorlegalorganizationname, vendordoingasbusinessname))
IF org = NULL THEN
INSERT INTO orgs(org_name,org_name_length,org_type,org_sub_types,org_created) VALUES (vendorname,LENGTH(vendorname),'org','org',DATE());
SET org = LAST_INSERT_ID();
END IF
Right now MySQL is throwing an error on the line:
SET agency = COALESCE(SELECT org_agency_o_id FROM orgs_agencies WHERE org_agency_code = maj_agency_cat,SELECT min(org_id) FROM orgs WHERE org_name LIKE CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5)))
'maj_agency_cat' is a variable that I declare at the beginning of the procedure and then is assigned dynamically using a cursor that goes through my staging data. The full stored procedure can be viewed here.
I'm sure I'm missing something basic and would appreciate any help.
Try wrapping another () around the inner SELECT statements in your COALESCE arguments. Otherwise, they are not treated as subqueries to be executed first and the value returned, but as query objects passed into COALESCE, which is not a valid argument type for COALESCE:
SET agency = COALESCE((SELECT ..), (SELECT ..))