MySQL - "insert if not exists" query? - mysql

I'm trying to write a MySQL query which will update a blog post view counter if the user has not visited the post in the last 24 hours. I'm trying to write something like this (but this does not work):
IF EXISTS (
SELECT 1
FROM `posts-views`
WHERE
`ip` = '".$_SERVER['REMOTE_ADDR']."'
AND
`time` > ".($time-60*60*24)."
AND
`post` = $id
) THEN
NULL
ELSE
INSERT INTO `posts-views`
(`post`, `time`, `ip`, `user`)
VALUES
($id, $time, '".$_SERVER['REMOTE_ADDR']."', $me)
What's the correct way to fix the query?

From what I see you cannot use INSERT IGNORE in that case, but something like following should do the job :
INSERT INTO `posts-views`
(`post`, `time`, `ip`, `user`)
SELECT $id, $time, '".$_SERVER['REMOTE_ADDR']."', $me
FROM dual
WHERE NOT EXISTS (
SELECT 1
FROM `posts-views`
WHERE
`ip` = '".$_SERVER['REMOTE_ADDR']."'
AND
`time` > ".$time-60*60*24."
AND
`post` = $id
)
I completely omit escaping variables which definitely should be done in real code.
UPDATED - added from dual to avoid syntax error

Related

MySQL IF THEN ELSE

I'm trying to make a IF EXISTS UPDATE ELSE INSERT statement but I get errors around the UPDATE line. I could do this in two separate queries but I'm not sure what would be better.
I've tried to follow this guide but didn't manage to make my query work. https://blog.udemy.com/sql-if-then/
IF EXISTS
(
SELECT 1
FROM `table`
WHERE
`column` = 'value'
)
THEN
(
UPDATE `table` SET
`date` = NOW()
WHERE
`column` = 'value'
)
ELSE
(
INSERT INTO `table` SET
`date` = NOW(),
`column` = 'value'
)
END IF
END
Would this help?
INSERT ... ON DUPLICATE KEY UPDATE
https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
In your case "column" would be a unique key

MySQL insert into values (select)

I am trying to insert value into mysql 5.1 table using the following statement
INSERT INTO `bp_measurements`
(`id_patient`, `time`, `location`, `systolic`, `diastolic`)
VALUES (
'2',
'2015-12-26 13:19:35',
(SELECT `id` FROM `gps_locations` WHERE `lon` = 20.40930 AND `lat` = 48.94990`),
'110',
'70'
)
But I am getting syntax error MySQL server version for the right syntax to use near '`),'110','70')' at line 2 (sorry for not putting this into code but it is not working because of apostrophes used). What am I doing wrong? I have tried some other solution from stackoverflow but I cant get them working
Thanks in forward
EDIT:
this is the correct version of my statement
INSERT INTO `bp_measurements`
(`id_patient`, `time`, `location`, `systolic`, `diastolic`)
VALUES (
'2',
'2015-12-26 13:19:35',
(SELECT `id` FROM `gps_locations` WHERE `lon` = 20.40930 AND `lat` = 48.94990),
'110',
'70'
)
both these and accepted answer works so feel free to use any of them
Try this syntax
Add the constant values to the select column list in order of insert column list
INSERT INTO `bp_measurements`
(`id_patient`,
`time`,
`location`,
`systolic`,
`diastolic`)
SELECT '2',
'2015-12-26 13:19:35',
`id`,
'110',
'70'
FROM `gps_locations`
WHERE `lon` = 20.40930
AND `lat` = 48.94990
Modified Insert statement as:
INSERT INTO bp_measurements(id_patient, time, location, systolic, diastolic) (SELECT '2' AS id_patient,'2015-12-26 13:19:35' AS time,id AS location,'110' AS systolic,'70' AS diastolic FROM gps_locations WHERE lon = 20.40930 AND lat = 48.94990)

#1064 MySql error in nested query statements

Here is the nested query i am using:
insert into ( select dbtable from profiles where ( email = 'blah#test.com' ) ) values ( null, null, 'blah#test.com', 'testing' )
the tablename will be fetched by the SELECT query for the INSERT query to run but i am getting this #1064 error.
I get another error of "#1103 - Incorrect table name" if i use back-ticks like this:
insert into `( select dbtable from profiles where ( email = 'blah#test.com' ) )` values ( null, null, 'blah#test.com', 'testing' )
I tried and searched for this but still i am stuck here. Can anybody help?
Sorry if this is an easy question as i am a newbie in this.
select dbtable from profiles where ( email = 'blah#test.com' ) into #tableName;
set #queryy = CONCAT(CONCAT('INSERT INTO ', #tableName), ' values ( null, null, \'blah#test.com\', \'testing\' )');
prepare myQuery from #queryy;
execute myQuery;
deallocate prepare myQuery;
I think it should help you solve your problem.

how to use if not exists while inserting a row mysql

The thing that i want to do is to check if there is a same row and if not to insert a new row to the table.
In that case, how can i use if not exists ?
INSERT INTO `facebook` (`ID`,`fb_id`,`label_id`,`page_ids`,`token`) VALUES (NULL,'". $session['id'] ."','$id','','". $access_token ."')
For example, in that query, i want to check if there is a row with the same label_id record and if not, execute that query.
any help ?
thanks
You can use the INSERT IGNORE INTO ... syntax. When using this, duplicate key errors are treated as warnings and the statement will return without having inserted the affected row.
INSERT INTO `facebook` (`ID`,`fb_id`,`label_id`,`page_ids`,`token`)
SELECT NULL, '". $session['id'] ."', '$id', '', '". $access_token ."'
FROM DUAL
WHERE NOT EXISTS (SELECT 'x' FROM facebook WHERE label_id = '$id')
I think FROM DUAL is optional, but I'm an Oracle guy. :)
User Insert Into to ignore duplicates:
INSERT IGNORE INTO `facebook`
SET `ID` = null,
`fb_id` = '". $session['id'] ."',
`label_id` = '$id',
`page_ids`='',
`token`='". $access_token ."';

If not exist insert into table mysql problem

I am trying to insert into my table, but only if the information doesn't exist already.
This works:
$sql = //"if not exists (select `id` from friends where `id` = :id) " . //ERROR!
"insert into `friends` (`id`, `fb_id`, `name`, `id2`, `fb_id2`, `name2`) " .
"values (:id, :fb_id, :name, :id2, :fb_id2, :name2)";
try
{
$stmt = $this->db->prepare($sql);
if (!$stmt)
{
$errorcode = (string)
$stmt->errorCode();
trigger_error("mysql errorcode : " . $errorcode, E_USER_ERROR);
$data = array( "note" => "mysql error code: " . $errorcode );
return json_encode( $data );
}
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindParam(':fb_id', $fb_id, PDO::PARAM_INT);
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
$stmt->bindParam(':id2', $id2, PDO::PARAM_INT);
$stmt->bindParam(':fb_id2', $fb_id2, PDO::PARAM_INT);
$stmt->bindParam(':name2', $name2, PDO::PARAM_STR);
$result = $stmt->execute();
$stmt->closeCursor();
}
catch (Exception $e)
{
die ($e->getMessage() );
}
I tried if not exists ( select id ... etc as commeted out in the first line, but that didn't work. It returned error code 00000 with (string) $stmt->errorCode();, I googled it and it means: to many mysql connections, this can't be the problem as other queries work fine.
How do I insert into the table when not exist and how do I get mysql error information?
I've never seen your syntax before, putting an exists clause before the insert clause, but the following should work.
INSERT INTO `friends`
SELECT :id, :fp_id, :name, :id2, :fb_id2, :name2
FROM `friends`
WHERE NOT EXISTS ( select `id` from friends where `id` = :id )
LIMIT 1;
Just realized that you'll need at least one record in your friends table before this'll go.
insert IGNORE into `friends` (`id`, `fb_id`, `name`, `id2`, `fb_id2`, `name2`)
values (:id, :fb_id, :name, :id2, :fb_id2, :name2)
Or you want to prevent duplicate id's you can add a trigger
DELIMITER $$
CREATE TRIGGER bi_friends_each BEFORE INSERT ON friends FOR EACH ROW
BEGIN
DECLARE TestId integer;
SELECT id INTO TestId FROM friends WHERE id = new.id LIMIT 1;
IF (id IS NOT NULL) THEN BEGIN
/*force an error to prevent insert*/
SELECT * FROM force_an_error_table_unwilling_to_insert_dup_key;
END; END IF;
END $$
DELIMITER ;
Note that if id is a UNIQUE or PRIMARY KEY field inserting a duplicate key will create an error and rollback any pending transaction.
If you are using a non-transactional engine, MySQL will stop inserting rows at the error point leaving only part of your rows inserted.
Your question is vague as to why you want to do the IGNORE test. So I'll recap the options and the implications:
If you want a transaction to fail, set id as primary key and just insert as normal, the resulting conflict will generate an error and rollback the transaction.
If you want to just insert stuff with no worries about duplicate id's set field is to AUTOINCREMENT and replace the value for id with null. INSERT INTO table (id, fb_id,name,id,fb_id2,name2) VALUES (null,:fb_id,:name,:id2,:fb_id2,:name2)
If you just want the one insert not to succeed, do the INSERT IGNORE ... as stated above.
If you do not have transactions (MyISAM et al), you may have to do a test SELECT first and only INSERT a bunch of values after the test shows it is save to proceed.
You could use INSERT IGNORE assuming you have a unique index on id. See this post for discussion about the pros/cons: "INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE"
This solution works even if you do not have any rows in your table.
INSERT INTO t (
x,
y,
z) (
SELECT
'00000',
'11111',
'22222'
FROM
DUAL
WHERE
NOT EXISTS (
SELECT
1
FROM
t
WHERE
c = '00000'
AND x = '11111'
AND y = '22222'
)
LIMIT 1
);