This is a follow up question to this one:
Query examples in a many-to-many relationship
regarding updating the junction table. To do this, I would have to use both key values in the junction table, in the WHERE clause.
Users UserAddresses Addresses
======= ============= =========
FirstName UserId City
LastName AddressId State
Zip
In this example, for instance, say I wanted to update the AddressId field in the UserAddresses table, because a user changed his address. I would have to use both the existing UserId and the address AddressId in the update WHERE clause.
I'm using a stored procedure, and passing in UserId and the new AddressId as parameters.
I've tries this:
CREATE PROCEDURE dbo.test
(
#UserId int,
#AddressId int
)
AS
create table #temp
(
UserId int not null,
AddressId int not null
)
insert into #temp select UserId, AddressId from UserAddresses where UserId = #UserId
update UserAddresses
set AddressId = #AddressIdD
WHERE (UserId+AddressId in #temp table = UserId+AddressId passed in as parameters)??
I've tried all sorts of combinations, but I can't seem to get the syntax right.
The UserId passed in, would ofcourse be the same as the one in the UserAddresses table, but this is just me trying some things. The WHERE clause is where it seems to go wrong.
Any thoughts?
This actually looks like a many-to-one relationship. If it's not you'll need the old address id as well as the new address id and user id to make the change. If it's a many to one relationship then a simple update should work since only one user id/address id pair will exist for each user id:
update UserAddresses
set AddressId = #AddressId
where UserId = #UserId
If it truly is a many-to-many relationship you need to find the existing pair out of many possible ones and update that one -- that's where you'll need both the new and old address ids in addition to the user id.
update UserAddresses
set AddressId = #NewAddressId
where UserId = #UserId and #AddressId = #OldAddressId
Why use the temp table?
CREATE PROCEDURE dbo.test
(
#UserId int,
#AddressId int
)
AS
update UserAddresses
set AddressId = #AddressIdD
WHERE UserId = #UserId
tvanfossom pointed out the problem in your code correctly, I think.
With the tables above, your operation could be done in various ways:
INSERT the link to the new address and DELETE the link to the old address, either keeping or deleting the address record that's being linked to.
UPDATE the link record as tvanfossom described (LuckyLindys query will set all registered addresses of the user to the same one).
UPDATE the address record that's being linked to.
Which one you use depends on what you want in your application. I'd probably just update the linked address, or do you need to keep the old one?
Related
I am trying to create a function in MySQL for my 'friendships' table where I have 4 columns:
friendship_id, status, user1_id and user2_id (last two are also foreign keys which point to another table 'users').
Function should receive one parameter which is users id and return how many friends that user has.
I created a function like this:
CREATE FUNCTION num_of_friends(id int)
RETURNS int(11)
BEGIN
SET #friends_count = (SELECT COUNT(user2_id) FROM friendships WHERE user1_id = id);
RETURN #friends_count;
END
So this function returns number of friends for that specific user, if his id is in column user1_id.
But there are some users whose id is only in the column user2_id.
How could I check if the user's id which we passed as parameter exists in either of the columns and count friendships based on that?
You can compare the id value with both the columns with OR
CREATE FUNCTION num_of_friends(id int)
RETURNS int(11)
BEGIN
SET #friends_count = (SELECT COUNT(*) from (select * from friendship where user1_id=id
union
select user2_id,user1_id from friendship where user2_id=id)data);
RETURN #friends_count;
END
Check this SQL fiddle: http://sqlfiddle.com/#!9/c5928ca/8
I'm quite new to SQL and databases.
I'm trying to make a preference table of an user.
The fields will be user_id, pref_no, prg_code.
Now if I create the table making pref_no auto_increment then it will automatically increase irrespective of the user_id.
So, my question is - Is there a way to define the table in such a way that it will be auto_incremented taking user_id into account or I have to explicitly find the last pref_no that has occurred for an user and then increment it by 1 before insertion?
Any help is appreciated. Thanks in advance.
Following what Mjh and Fahmina suggested, we can create a procedure for the insertion.
DELIMITER //
CREATE PROCEDURE test(IN u_id INT(7), p_code INT(5))
BEGIN
SELECT #pno:= MAX(pref_no) FROM temp_choice WHERE user_id = u_id;
IF #pno IS NULL THEN
SET #pno = 1;
ELSE
SET #pno = #pno + 1;
END IF;
INSERT INTO temp_choice VALUES (u_id, #pno, p_code);
END //
DELIMITER ;
Now we can easily insert data by using
CALL test(1234567, 10101);
To manage user's preference, you don't need user_id to be auto_incremented in this table, but pref_no has to be.
user_id will just be a refence (or foreign key in sql) to your user table (where user_id should be auto_incremented).
And to request preference for a given user your request would be :
SELECT * FROM [user table] INNER JOIN [pref table] ON ([user table].user_id = [pref table].user_id) WHERE [user table].user_id = ?
(replace '?' by the user_id you want)
I have two table as follows:
active_employee, with the columns id, email_id, job, location and project_id
project_relation, with the columns id, email_id and project_id.
My problem is that I want to update the project_id column of project_relation table with the condition that if the value for project_id in both the tables are not same, then it has to fetch the value from "active_employee" table and update the project_relation table for corresponding email_id.
Help me how to do this!
I believe an UPDATE FROM with a JOIN will help:
UPDATE
project_relation
SET
project_relation.project_id = active_employee.project_id
FROM
project_relation PR
INNER JOIN
active_employee AE
ON
PR.columns_id = AE.columns_id
Just check underscore.. it may create problem.. you can remove it and make changes in db columns names also.
or Simply try this-
UPDATE project_relation SET project_relation.project_id = active_employee.project_id where project_relation.columns_id = active_employee.columns_id;
I think I get what you need. I created some temp tables to replace your actual tables for testing.
I used a subquery to rename some of the column names to remove ambiguous names because of the update table:
DECLARE #ACTIVE_EMPLOYEE TABLE (columnid UNIQUEIDENTIFIER, emailid UNIQUEIDENTIFIER, job VARCHAR(200), location VARCHAR(200), projectid UNIQUEIDENTIFIER)
DECLARE #PROJECT_RELATION TABLE (columnid UNIQUEIDENTIFIER, emailid UNIQUEIDENTIFIER, projectid UNIQUEIDENTIFIER)
UPDATE #PROJECT_RELATION
SET projectid = active.proid
FROM (SELECT columnid,
emailid [emid],
job,
location,
projectid [proid]
FROM #ACTIVE_EMPLOYEE) active
WHERE active.emid = emailid
AND active.proid <> projectid
Hello I'm working on a database assignment and I'm stuck on how to do this one stored procedure. Although It works, sort of...
DELIMITER //
CREATE PROCEDURE AddANewCustomer(IN firstName char(20), IN lastName char(20), IN companyName char(45), IN streetAddress char(60), IN city char(30), IN province char(45), IN postalCode char(6), IN phoneNumber int(10))
BEGIN
DECLARE PersonID INT;
SELECT idPerson FROM Persons WHERE Persons.firstName = firstName AND Persons.lastName = lastName INTO PersonID;
IF PersonID IS NULL THEN
INSERT INTO Persons(firstName, lastName, streetAddress, city, province, postalCode, phoneNumber) VALUES (firstName, lastName, streetAddress, City, Province, postalCode, phoneNumber);
SELECT idPerson FROM Persons WHERE firstName = firstName AND lastName = lastName INTO PersonID;
END IF;
INSERT INTO Customers(idCustomer, companyName) VALUES (Last_Insert_ID(), companyName);
END //
DELIMITER ;
Basically I'm working with Super/Sub types. I want to take the information from the user and then update my parent table (Persons) and pass on the remaining information to my child table (Customers). idPerson is the auto-incrementing PK for Persons table, and I want to use that as a PK/FK for the Customers table's id, idCustomer.
If I run the procedure once, it'll spit out an error 'Result consist of more than one row' and only the Parent table gets updated... But if I run it again, it'll update the Child table properly. Which makes me think that the Last_Insert_ID() parameter is null the first time around and the idPerson only gets updated after the procedure is done.
I've researched for a fix all night and now I'm absolutely stumped on how to solve this.
Ouch.
Basically I'm working with Super/Sub
types.
I don't think so, but I could be wrong. Customer usually describes a relationship between two parties, one a buyer and the other a seller.
If I run the procedure once, it'll
spit out an error 'Result consist of
more than one row'
What do you think that means? Does this query return any rows?
SELECT lastname, firstname, count(*)
FROM Persons
GROUP BY lastname, firstname
HAVING count(*) > 1;
You check for a NULL id number,
IF PersonID IS NULL THEN
but you ignore the possibility that your SELECT statement might return 2 or 3 or 42 different id numbers, all for people who have the same first and last name. Is that wise? Phrased another way, do you have a UNIQUE constraint on {firstname, lastname}?
If PersonID is null, you insert a row into Persons, which sets a value that LAST_INSERT_ID() can return. But your second INSERT tries to use LAST_INSERT_ID() without regard to whether a row was previously inserted into Persons.
Finally, you have two slightly different versions of
SELECT idPerson
FROM Persons
WHERE Persons.firstName = firstName
AND Persons.lastName = lastName
INTO PersonID;
I'm pretty sure you need one at most.
I am trying to create a conditional INSERT into my MySQL databate from a PHP script. The following SQL syntax works in phpMyAdmin, but not in my PHP Script:
INSERT INTO profiles (id, firstname)
SELECT "22","John" from profiles
WHERE NOT EXISTS (
SELECT * FROM li_profiles
WHERE li_p_firstname = "John"
)
(Note that "id" is the primary key, "firstname" is not a key or unique)
Something weird that might be part of the issue is that when I run that SQL in phpMyAdmin, while it does "work" (meaning that a new record is added with the id "22" and the firstname "John") I get the following warning: "#1062 - Duplicate entry '22' for key 1"
But the table didn't have a previous entry with id of 22. ??!!
What's going on?
Change SELECT to VALUES
INSERT INTO profiles (id, firstname) VALUES("22","John") FROM profiles WHERE NOT EXISTS ( SELECT * FROM li_profiles WHERE li_p_firstname = "John" )
Also, if you are using auto-increment values, you should specify the next value. Also, if its an integer, give an integer (22) not a string ("22")
You'll get a duplicate entry for the iD because you are inserting a new row for each row in the profiles table; for every row in the profiles table there is no John in the li_profiles table. You might try
INSERT INTO profiles (id, firstname)
SELECT "22","John" from profiles
WHERE NOT EXISTS (SELECT * FROM li_profiles
WHERE li_p_firstname = "John")
LIMIT 1;
which would eliminate the duplicate problem (if it works, sorry but I haven't checked this myself).
I figured it out in a different way. (I'm told that the HAVING statement is slow, so I'm not sure that it's the best way... but it the only method I've gotten to work.)
INSERT INTO profiles (id,firstname)
SELECT 22,'John'
FROM li_profiles
WHERE firstname = 'John'
HAVING COUNT(*) = 0;