Insert if not exist and Update if exist - mysql

I have three columns on my database table
user_id, post_id, and vote
I want to insert a new data if user_id and post_id don't exist. But if both columns user_id and post_id exist i will be able to update 'vote' column value. I set user_id to be unique but it proves to be not working since i want user to insert votes on different post.
The query below only updated the value of vote since user_id already exist. I want to have it updated if and only if user_id and post_id existed
I used this sql query
INSERT INTO polls (user_id,post_id,vote) VALUES (1,2,5)
ON DUPLICATE KEY UPDATE vote= ?;
Here's my problem

You must create unique key combination
Create unique index your_index_name on yourtable (field_one,field_two),
then do the insert into , on duplicate key logic
It is absolutely logical that your code does not work as intended, because your only key is user_id, thus if you want to check the uniqueness of user_id AND post_id, then you should set it as so.

Don't think you can do it purely in MySQL :*( post_id would have to be unique and you said that does not fit your business logic. Furthermore, if multiple keys are detected, they are joined by an OR in the resulting query, which will further complicate things for you. Here's an excerpt from the manual, where a and b are keys involved in the ON DUPLICATE KEY query:
If a=1 OR b=2 matches several rows, only one row is updated. In general, you should try to avoid using an ON DUPLICATE KEY UPDATE clause on tables with multiple unique indexes.

Related

Number of rows that are using the foreign key

I have a problem with counting the number of items/rows that are using the foreign key.
For example.
Table "A" has a foreign key of "group_id" and there is a row with "group_id" of "5" and a couple of items/posts/rows in table "B" are using the foreign key (in this case the ID of "5"). How would I know how to cont the rows that are using that "group_id"?
Here's what I mean.
Thanks very much.
UPDATE
Here is a sketch that explains my problem
PK = Primary Key
FK = Foreign key
You can query the number of rows like this:
SELECT group_id, COUNT(*) FROM table_B GROUP BY group_id;
Your image seems to show that you want table_A to keep the count persistently as an attribute column.
Some people design triggers for this. For example, in an INSERT trigger on table_B, increment the count attribute column of table_A by 1. In a DELETE trigger on table_B, decrement the count column of table_A by 1.
This sort of works, but it causes more overhead for inserts and deletes, and it causes more exclusive locking on table_A.
It's easier to do the SELECT query that I showed above.

insert into 2column table, avoiding duplicate records

I have a table with 2 columns, userid and messageid. I am updating it automatically through a php script, but I can't get a working insert statement. I don't mind if there are duplicates of userid, or duplicates of messageid (in fact there should be duplicates of both), I just don't want any duplicate of the same combination of userid and messageid. Is there any way to write a query that will do this for me, or do I have to handle it at the php level?
I've probably tried 20 different queries that I found on here and google, but have not gotten it right. This was the last thing I tried:
INSERT INTO interests_join (userid, interestid)
VALUES (1, 4)
WHERE NOT EXISTS
(SELECT userid, interestid FROM interests_join WHERE userid = 1 AND interestid = 4)
You can add a UNIQUE KEY, sql will refuse to insert a new row that is a duplicate of an existing one.
ALTER TABLE `interests_join` ADD UNIQUE `row` (`userid`, `interestid`);
Then you'll have to check from PHP if the query was successful or not (error #1062). You can't apply the key if there are duplicate rows, you have to remove them first .

Strategies for preventing the insertion of duplicate table rows

Scenario:
User A and B executes at the same time select id from Product where id = ?, if the there are no results, both create a new product with given ID.
Problem:
This could lead to the creation of duplicate rows.
Question:
What are the possibles strategies to prevent that? I know that I can use compound/unique keys, to guarantee this, but are there any other strategies? Is there any SQL statement to lock query with same parameters?
You can use unique constraints
ALTER TABLE Persons ADD UNIQUE (P_Id)
or
ALTER TABLE Persons
ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)
That way it would be impossible for a duplicate to be inserted.
Put a UNIQUE key on the field in question:
https://dev.mysql.com/doc/refman/5.0/en/constraint-primary-key.html

Database design: auto-increment key & update inconsistencies

Two tables share a unique identifier 'id'. Both tables are meant to be joined by using 'id'.
Defining 'id' as an auto incrementing primary key in both tables may risk update inconsistencies.
Is there some general pattern to avoid such a situation or do I have to deal with updating table1 first and table2 by utilizing the last inserted id after (therefore not declaring id as auto inc in table2)?
First, if you use InnoDB table engine in MySQL you could use both transactions and foreign keys for data consistency.
Second, after the insert in the first table, you could get the last insert id (depending on the way you access the db) and use it as foreign key.
Eg
Table 1: Users: user_id, username
Table 2: User_Profiles: user_id, name, phone
In User_Profiles you don't need to define user_id as auto increment, but first insert a record in Users table and use the user_id for the User_Profiles record. If you do this in transaction, the Users record won't be seen outside of the transaction connection until it's completed, this way you guarantee that even if something bad happens after you insert the user, but before you have inserted the profile - there won't be messed up data.
You could also define that the user_id column in User_Profiles table is foreign key of Users table thus if someone deletes a record from the Users table, the database would automatically delete the one in User_Profiles. There are many other options - read more about that.
There is no problem with same column name 'id' in any number of tables.
Several persistence layer frameworks do it same way.
Just use aliases in your SQL to distinct your tables accordingly.
do I have to deal with updating table1 first and table2 by utilizing the last inserted id after (therefore not declaring id as auto inc in table2)?
Yes. And make id a foreign key so it can only exist in table2 if it already exists in table1.
Yes you do, and remember to wrap the operation in a transaction.

data model and app logic question?

basically i have this problem i have a table of posts(in my mysql database)
Post{user_id, post, vote_up(int), vote_down(int)}
because users log in, then they get to vote, but i wanted to check if the user has already voted, so then i can not allow them to vote again, and obviously im going to be using user session to control this oppose to tracking ips etc.
so i was thinking do i have to create another table or is thier a better approach.
You will need another table e.g. called "votes":
Vote{user_id, post_id}
I assume, that your "Post" table has a primary key (e.g. "id") that you have not shown in your question above? Then "post_id" should be a foreign key to Post#id.
/Carsten
You'll definately need another table, and some primary and foreign keys would help too:
Post{post_id(int), user_id(varchar), post(clob)}
Votes{vote_id(int), post_id, user_id, up_down(char)}
Your vote_up and vote_down column values are removed and are now calculated with queries:
-- vote_up
select count(*) from votes where post_id = n and up_down = '+';
-- vote_down
select count(*) from votes where post_id = n and up_down = '-';
There should be a unique index on votes(post_id, user_id) to prevent multiple votes by the same user on the same post.
The primary key vote_id does not have to be defined, but each table should have a primary key and if you don't want to use a surrogate key, then you can define the PK using the same columns as above and this will serve as the unique index too, so ot does not have to be defined.