MySQL insert new value when no other like that - mysql

I am trying to solve the problem with insert new value into table. Primary key is ID not email... Before insert i need check other records for email value. If no one match inserted email, data is inserted. But i canot write correct code for that...
IF EXIST (SELECT email FROM users WHERE email = "email")
THEN
BEGIN
'We Have Records of this Customer'
END
ELSE
BEGIN
INSERT INTO users
VALUES (null,'email9','password9','forename9','lastname9')
END
END IF
Or:
IF SELECT COUNT(*) FROM users WHERE email = 'email' > 0
THEN
BEGIN
//email exist
END
ELSE
BEGIN
//inserting
END
END IF

This looks like a good use case for MySQL INSERT ... ON DUPLICATE KEY UPDATE syntax.
First of all, you want to create a UNIQUE constraint on column email. This is the proper way to represent your business rule:
ALTER TABLE users ADD CONSTRAINT users_unique_email UNIQUE (email);
Now, if the record that is about to be inserted would generate a duplicate on the primary key or on that UNIQUE constraint, then MySQL lets you turn the operation to an UPDATE instead.
In your case, since you want not to update anything in that case, you can simply re-assign the email column (which we know is the same here).
Consider:
INSERT INTO users
VALUES (null,'email9','password9','forename9','lastname9')
ON DUPLICATE KEY UPDATE SET email = 'mail9';

I cant comment, but I post this. I recommend making an external script like in python or java to do this for you by selecting * and parsing through the output because SQL itself does not have the power to do this.

Related

MySQL Query: UPDATE and/or APPEND

I have a temporary table that I use to insert into the master db.
The temp table is named "temp_table"
The master table is "master"
I currently use the following command to update "master"
SELECT COUNT(*) FROM master;
SHOW COLUMNS FROM master;
INSERT INTO master
SELECT * FROM temp_table
ON DUPLICATE KEY UPDATE email = VALUES(email), phone = VALUES(phone)
Now, I want to be able to append field (counter) from the "temp table" into "master." The field already exists in both tables and I just want to be able to update or append it.
"counter" field in master may be empty or it may contain a number value already.
In cases where the value exists, it should append separated by a comma. Format (88,89,90)
In cases where the it's empty, it should update (88)
Thank you in advance.
I think you want:
on duplicate key update
email = values(email),
phone = values(phone),
counter = case when counter is null
then values(counter)
else concat(counter, ',', values(counter))
end
You can also phrase this with coalesce(), although the expression might be a bit more complicated to understand:
on duplicate key update
email = values(email),
phone = values(phone),
counter = concat(
coalesce(concat(counter, ','), ''),
values(counter)
)

How do I update if exist, else insert in MySQL

I have table with AUTO_INCREMENT field defined as PRIMARY_KEY.
I have columns like:
vote_id,vote_user_id,vote_ask_id,vote_comment_id,vote_post_id,vote_type,vote_status
I want to INSERT new records but before I do that I want to check if there is a row with columns(vote_user_id,vote_ask_id,vote_type) as same as the new data I want INSERT.
CONDITIONS:
IF ROW EXISTS
THEN UPDATE tableName SET vote_status=new_value, vote_time=new_time
ELSE
INSERT NEW RECORDS
I have searched the internet and learnt about MySQL ..ON DUPLICATE KEY UPDATE.
I have realize this statement will not be helpful to my task since it only checks for DUPLICATE KEY(...PRIMARY_KEY or UNIQUE FIELD).
I have learnt also on MySQL REPLACE INTO ...and likewise this will not be helpful to my problem since that is also bind to PRIMARY_KEY or UNIQUE index.
I learnt I could use MERGE....USING...statements
but this was giving me errors so i read more about it and I relised it only work in SQL server (Microsoft)
Please how best can someone help me solve this?
I tried this on MERGE staments:
MERGE {$votes_table} WITH (HOLDLOCK) AS VT
USING ({$Qid},{$vote_type},{$CUid},{$vote_status}) AS VTS (vote_ask_id,vote_type,vote_user_id,vote_status)
ON( VT.vote_ask_id = VTS.vote_ask_id AND VT.vote_user_id=VTS.vote_user_id AND VT.vote_type=VTS.vote_type)
WHEN MATCHED THEN
UPDATE SET VT.status=VST.vote_status , VT.vote_time='{$current_time}' WHERE VT.vote_user_id=VTS.vote_user_id AND VT.vote_ask_id=VTS.vote_ask_id AND VT.vote_type=VTS.vote_type
WHEN NOT MATCHED THEN INSERT (vote_ask_id,vote_type,vote_status,vote_user_id,vote_time) VALUES('{$Qid}','{$vote_type}','{$vote_up_status}','{$CUid}','{$current_time}')
In MySQL, use ON DUPLICATE KEY:
INSERT INTO tablename (vote_user_id, vote_ask_id, vote_type, . . . )
VALUES (new_vote_user_id, new_vote_ask_id, new_vote_type . . . )
ON DUPLICATE KEY UPDATE vote_status = VALUES(vote_status), vote_time = VALUES(vote_time);
For this to work, you need a unique index/constraint on the columns that define a unique row:
CREATE UNIQUE INDEX unq_tablename_3 ON tablename(vote_user_id, vote_ask_id, vote_type);
You do want insert ... on duplicate key update: in MySQL, this is the right way to do what you want.
To start with, you need to create a unique constraint on the tuple of concerned columns:
create unique index votes_table_unique_idx
on votes_table(vote_user_id, vote_ask_id, vote_type);
Then, you can do something like:
insert into votes_table(vote_user_id, vote_ask_id, vote_type, vote_comment_id, vote_post_id, vote_status)
values(...)
on duplicate key update
vote_comment_id = values(vote_comment_id),
vote_post_id = values(vote_post_id)
vote_status = values(vote_status)

Insert a record only if it is not present

I need to create a query to insert some records, the record must be unique. If it exists I need the recorded ID else if it doesnt exist I want insert it and get the new ID. I wrote that query but it doesnt work.
SELECT id FROM tags WHERE slug = 'category_x'
WHERE NO EXISTS (INSERT INTO tags('name', 'slug') VALUES('Category X','category_x'));
It's called UPSERT (i.e. UPdate or inSERT).
INSERT INTO tags
('name', 'slug')
VALUES('Category X','category_x')
ON DUPLICATE KEY UPDATE
'slug' = 'category_x'
MySql Reference: 13.2.5.3. INSERT ... ON DUPLICATE KEY UPDATE Syntax
Try something like...
IF (NOT EXISTS (SELECT id FROM tags WHERE slug = 'category_x'))
BEGIN
INSERT INTO tags('name', 'slug') VALUES('Category X','category_x');
END
ELSE
BEGIN
SELECT id FROM tags WHERE slug = 'category_x'
END
But you can leave the ELSE part and SELECT the id, this way the query will always return the id, irrespective of the insert...
MySQL has nice REPLACE. It is easy to use and remember it's syntax as same as INSERT.
in you case, just run following query.
REPLACE INTO tags('name', 'slug') VALUES('Category X','category_x')
It acts like INSERT when no unique constraint violation. If duplicated value found on PK or UNIQUE key, then other columns will be UPDATED with given values. It is done by DELETE duplicated record and INSERT new record.

inserting new rows to table without updating old ones

Alright, i have revised the question to also include what i have so far, and what i want to do. So here goes it:
CREATE ORDER (
product_nat_id int(3) NOT NULL,
name VARCHAR(20),
PRIMARY KEY (product_nate_id)
)
INSERT INTO ORDER(product_nat_id, name) VALUES(1, 'Product 1');
INSERT INTO ORDER(product_nat_id, name) VALUES(2, 'Product 2');
INSERT INTO ORDER(product_nat_id, name) VALUES(3, 'Product 3');
CREATE TABLE INT_PRODUCT (
product_id INTEGER NOT NULL AUTO_INCREMENT,
product_nat_id INTEGER NOT NULL,
title TINYTEXT,
dateCreate TIMESTAMP CURRENT_TIMESTAMP,
CONSTRAINT INT_PRODUCT_PK PRIMARY KEY (product_id),
UNIQUE INT_PRODUCT_NK (product_nat_id));
But what i want is, whenever a record arrives with an updated value but duplicate key, i need to insert it (and not updated), but avoid duplicate constraint based on the difference in time inserted. Hope this makes sense now.
I would suggest the following:
Look up the previous record. I assume you should know what that would be
SELECT Count(*) FROM dim WHERE recordId = '$recordid'
If in step 1 the records returned are larger than 0 then invalidate the 'previous' record:
UPDATE dim SET datevalid = '$datevalue' where recordId = '$recordid' and status = 2
Continuing with step 1 where the ecords return in the check are larger than 0 now do the insert:
INSERT INTO dim (recordId,field1,field2,date,status) VALUES (1,'sad','123123','2013-03-26',1)
If step 1 was false then just do the insert:
INSERT INTO dim (recordId,field1,field2,date,status) VALUES (1,'sad','123123','2013-03-26',1)
I would add a status field just as an extra measure when you need to find records and distinguish between valid or invalid then you do not need to filter between dates. You can then use the status field. Also have a unique auto-increment key for every record even though the data might be the same for a set of valid and invalid records. recordId and unique key will not be the same in this case. You assign the recordId and the system will assign the unique key on the table. status = 1 is valid and status = 2 is invalid.
Hope this helps!
sample code of your post like as:
Insert query syntax looks like this:
INSERT INTO table (primarykeycol,col1,col2)
VALUES (1,2,3) ON DUPLICATE KEY UPDATE col1=0, col2=col2+1
If there is already a row with primarykeycol set to 1 this query is equal to:
UPDATE table SET col1=0, col2=col2+1 WHERE primarykeycol = 1
explanation as:
Ordinarily to achieve the same result you would have to issue an
UPDATE query, then check if there were affected rows and if not
issue an INSERT query.
This way, you can do everything in one step – first try insert and
then update if insert fails.
One situation for which this type of syntax is perfect is when you
work with daily counters. For example, you might have a table with
PostID, Date and Count columns.
Each day you’d have to check if you already created an entry for
that day and if so increase the count column – and this can be
easily substituted with one INSERT … ON DUPLICATE KEY UPDATE query.
Unfortunately there are some caveats. One being that when you have
multiple unique indexes it will act as if you had an OR condition in
WHERE clause of UPDATE query.
This means that multiple rows should be update, but INSERT … ON
DUPLICATE KEY UPDATE will update only one row.
MySQL manual: INSERT ON DUPLICATE KEY UPDATE Syntax

INSERT INTO query only if record doesn't already exist

In my table I have two fields: v_id and ip_address. I want to insert some data into this table only if the IP address doesn't already exist.
After Google'ing I came across the INSERT IGNORE INTO statement, and this is my code:
public function update_visits($ip_address)
{
$sql = 'INSERT IGNORE INTO `24h_visits` (ip_address) VALUES (?)';
if($this->db->query($sql, array($ip_address)))
{
return TRUE;
}
return FALSE;
}
It runs fine and without errors, but duplicate rows are still being made, even if the same IP is passed in as a parameter.
Anyone got a clue? Thanks.
You have to create a UNIQUE index on ip_address for INSERT IGNORE to work:
ALTER TABLE 24h_visits
ADD UNIQUE INDEX(ip_address)
However, I haven't seen the entirety of your schema, but I would assume that there's a column that stores a timestamp of the last visit. It's the only way this would make sense (so you can purge visits older than 24 hours every now and then).
In this case, you actually don't want INSERT IGNORE, but INSERT ... ON DUPLICATE KEY UPDATE instead. Assuming you have a column called last_visit:
INSERT INTO 24h_visits (ip_address, last_visit)
VALUES ('$ip_address', NOW())
ON DUPLICATE KEY UPDATE last_visit = NOW();
With INSERT IGNORE, the new row is never inserted, and thus you would always have the first value ever inserted on last_visit, which (the way I see it) is not entirely correct.
Add the UNIQUE constraint to your ip_address column.
Then your query would fail if it attempts to add a duplicate ip_address row (unless you use INSERT IGNORE).
The other answers don't actually answer the question: Creating a unique index prevents the duplicate from being inserted, which is a good idea, but it doesn't answer "how to insert if not already there".
This is how you do it:
INSERT IGNORE INTO 24h_visits (ip_address)
select ?
where not exists (select * from 24h_visits where ip_address = ?)
Additionally, this approach does not require any changes to schema.