INSERT if not exists, else return id - php

There are some limitations:
Cannot modify database
Columns are not unique
Needs to return last insert id (RETURNING id)
If exists, return existing id
It will be called through our custom db library (the values in select will be as parameters from PHP (?, ?, ?, !))
INSERT INTO tags (name, color, groupid)
SELECT 'test', '000000', 56
WHERE NOT EXISTS (
SELECT text FROM tags WHERE name = 'test' AND groupid = 56
)
RETURNING id
This works - until to the point where i need to get existing id aswell. With this i only get the inserted id.
Is it possible to return the value of SELECT statement if it doesn't insert?
UPDATE:
DO $$
BEGIN
IF NOT EXISTS (
SELECT text FROM tags WHERE name = 'test' AND groupid = 56
)
THEN
INSERT INTO tags (name, color, groupid)
VALUES ('test', '000000', 56) RETURNING id;
ELSE
RETURN SELECT text FROM tags WHERE name = 'test' AND groupid = 56;
END IF;
END
$$
Was testing with this kind of format - however this ends with a few errors:
RETURN cannot have a parameter in function returning void

You can do this using a CTE.
The info cte has the source data, so replace the values there with your placeholders for PHP.
The CTE will return the results from the first half of the union if an existing record exists (so will show old id), and the second half if an insert was performed (so will show the new id).
WITH info (name, color, groupid) AS
(values('test','000000',56)),
trial AS (
INSERT INTO tags(name, color, groupid)
SELECT info.name, info.color, info.groupid
FROM info
WHERE NOT EXISTS (
SELECT * FROM tags t2
WHERE t2.name = info.name AND t2.groupid= info.groupid)
RETURNING id)
SELECT tags.id
FROM tags
INNER JOIN info ON tags.name = info.name AND tags.groupid= info.groupid
UNION ALL
SELECT trial.id
FROM trial;
SQL Fiddle example: http://sqlfiddle.com/#!15/a7b0f/2
Postgres manual page for using CTEs
http://www.postgresql.org/docs/9.1/static/queries-with.html

You can use an IF statement to do this.
IF NOT EXISTS(SELECT text FROM tags WHERE name = 'test')
BEGIN
INSERT INTO tags (name, color, groupid)
VALUES ('test', '000000', 56)
SET #textId = SCOPE_IDENTITY()
END
ELSE
BEGIN
SELECT #textId = ID FROM tags WHERE name = 'test'
END
You have to make necessary changes in above query as per your requirements.

if name is unique:
INSERT INTO `tags` (name, color, groupid) VALUES ('test', '000000', 56)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), `name`='test';
SELECT LAST_INSERT_ID();

Related

MYSQL - append or insert value into a column depending on whether it's empty or not

As title says, im trying to append a string to a VARCHAR column in my table.
The string is something like " //string ", forward slashes will be used later to explode the string to an array in PHP.
I was wondering if there's a way in MYSQL to perform a CONCAT(columnname, "//string") if the column is empty, otherwise perform a normal UPDATE ... SET ... WHERE . In this way, i will avoid the first value of my future exploded string to be a "//string" with forward slahes.
also, above I 've used bold characters for "in MYSQL" because I know i could first query the DB (to check if the column is empty) with something like:
$q = $conn->dbh->prepare('SELECT columnname FROM tablename WHERE username=:user');
$q->bindParam(':user', $username);
$q->execute();
$check = $q->fetchColumn();
and then leave PHP decide which operation perform:
if ($check != '') { // PERFORM A CONCAT }
else { // PERFORM AN UPDATE }
but this would mean a waste of time/resources due to 2x database calls and more PHP code.
thanks.
https://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
That means in your case:
INSERT INTO tablename (id,columnname) VALUES (1,'//string')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//string');
http://sqlfiddle.com/#!9/bd0f4/1
UPDATE Just to show you your options:
http://sqlfiddle.com/#!9/8e61c/1
INSERT INTO tablename (id, columnname) VALUES (1, '//string')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//string');
INSERT INTO tablename (id, columnname) VALUES (1, '//string')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//string');
INSERT INTO tablename (id, columnname) VALUES ((SELECT id FROM tablename t WHERE columnname='blahblah'), '//string')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//string');
INSERT INTO tablename (id, columnname) VALUES ((SELECT id FROM tablename t WHERE id=2), '//string')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//string');
INSERT INTO tablename (id, columnname) VALUES ((SELECT id FROM tablename t WHERE columnname='newone'), '//newone')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//newone');
If what you want is this:
first string: column will contain 'firststring'
second string: column will contain 'firststring//secondstring'
then do the update like this:
UPDATE tablename SET columnname = CONCAT( IF(IFNULL(columnname,'')='','',CONCAT(columnname,'//')), :string) WHERE username=:user

mysql: store a DEFAULT value as a variable

I am wondering how to store the value of a primary key, auto-incremented by "DEFAULT" so that I can insert it as a value in another table row.
So far I have:
$sql = "INSERT INTO sales (
sale_id,
sale_amt,
sale_date)
VALUES (
DEFAULT, # <--- how to store the resulting value of this?
'$amt',
'$date'
)";
I need the specific value created by "DEFAULT" to be stored, so that I can insert it into another table's row. How do I do this with either PHP or MySQL?
You don't. You use last_insert_id() to retrieve it AFTER you've performed the first insert.
INSERT INTO foo (bar) VALUES (baz)
SELECT #id := last_insert_id();
INSERT INTO other (id, parent) VALUES (null, #id)
INSERT INTO yetanother (id, parent) VALUES (null, #id)
Note that last_insert_id() is not smart and will return the id of the LAST insert you did. If you do two inserts, and then try to get the ids, you'll get the id of the second (last) insert.
MySQL:
You can find this in MySQL by using the LAST_INSERT_ID() function, as the last insert ID will be returned that you inserted for an AUTO_INCREMENT value.
$sql = "INSERT INTO sales (
sale_id,
sale_amt,
sale_date)
VALUES (
DEFAULT, # <--- how to store the resulting value of this?
'$amt',
'$date'
)";
sql2 = "INSERT INTO records (
sale_id,
customer_name,
other_info)
VALUES (
LAST_INSERT_ID(), <-------- correct sales_id
'$name',
'$info');

INSERT with two SELECT statements

Here is what I am currently trying but I am receiving an mySQL error:
mysql_query ("INSERT INTO profile_tag (profile_id, tag_id)
(SELECT profile_id FROM profile WHERE username = '$username'),
(SELECT tag_id FROM tag WHERE tag = '$music' OR tag = '$sports' OR tag = '$tech')");
I am able to complete an INSERT using a single SELECT statement however, not two.
The error I receive:
Query is invalid: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(SELECT tag_id FROM tag WHERE tag = '' OR tag = 'sports' OR tag = '')' at line 1
Much like the error says, the syntax is incorrect. The values of the insert has to match the number of values in the column definition.
INSERT INTO profile_tag (profile_id, tag_id)
SELECT
profile_id, tag_id
FROM
profile
CROSS JOIN tag
WHERE
username = ?
AND tag IN (?, ?, ?)
Note that this will insert multiple rows if a tag value is found for each of the inputs, but I believe that is what you want.
You can use VALUES clause
insert into profile_tag(user_id, tag_id) values
((select id from users where username = 'alice'),
(select id from tags where tag = 'music'));
http://sqlfiddle.com/#!2/76439/1/0
mysql_query ("INSERT INTO profile_tag (profile_id, tag_id)
(SELECT profile.profile_id, tag.tag_id FROM profile LEFT JOIN tag ON 1 WHERE profile.username = '$username' AND tag.tag IN ('$music', '$sports', '$tech'))");

Insert data from another table and also from form in MYSQL and PHP

i have a form where i post the data to mysql. the query should insert the data from the form into table1, but also include data from another table2 where the ID that is send from the form is equal to the ID in table2?
i use the old mysql connection, i know, not the best :-) and php!
hope someone can help, thanks :-)
Martin
think maybe I should give some more info :-)
table1 is called: books
from the form, i have the following value: itemCode, itemQty, ownerID
i have 2 static value: status, type
the values from table2 that must be inserted into table1 is:
title, description, price, frontcover
from table2 the field isbn should be equal to itemCode from form.
here is what i have tried so far:
$bookid=$_POST['itemCode'];
$itemQty=$_POST['itemQty'];
$status='2';
$ownerID = $user->id;
$query="INSERT INTO books (name, description, price, picture, status, ownerID, itemqty, type, studie, isbn) SELECT (title, description, price, frontcover FROM isbnbooks WHERE isbn=$itemCode), $status, $ownerID, $itemQty, '1', '1', $bookid)";
UPDATE:
I have also tried this one here:
$bookid=$_POST['itemCode'];
$itemQty=$_POST['itemQty'];
$status='2';
$ownerID = $user->id;
$data2 = mysql_fetch_array (mysql_query("SELECT * FROM isbnbooks WHERE isbn = $bookid"));
$title = $data2[title];
$description = $data2[description];
$price = $data2[price];
$picture = $data2[frontcover];
$query="INSERT INTO books (name, description, price, picture, status, ownerID, itemqty, type, studie, isbn)
VALUES ($title, $description, $price, $picture, $status, $ownerID, $itemQty, '1', '1', $bookid)";
mysql_query($query) or die("Opps some thing went wrong");
If you have values 'a' and 'b' to go into columns f1 and f2 of table1; and in f3 you want the value of table2.field where table2.id is 123, you can prepare and execute a SQL statement along these lines:
INSERT INTO table1 (f1, f2, f3)
SELECT 'a', 'b', field FROM table2 WHERE id = 123;
Further to seeing the code in your updated question, the problem with your first attempt is that you're trying to mix INSERT ... SELECT with INSERT ... VALUES; sadly they are mutually exclusive. However, you could write instead:
INSERT INTO books (
name,
description,
price,
picture,
status,
ownerID,
itemqty,
type,
studie,
isbn
)
SELECT
title,
description,
price,
frontcover,
:status, -- use prepared statements to prevent SQL injection
:ownerID, -- see http://bobby-tables.com/ for more info
:itemQty,
'1', -- do you really want a string containing a number?
'1',
:bookid
FROM isbnbooks
WHERE isbn=:itemCode;
Your second attempt looks as though it ought to work (although you really should use prepared statements, see above!); what problems are you having with it?
in the absence of code, here's the workflow id recommend:
Form is submitted -> check and sanitize values - > execute lookup query against "table 2" and get your related values -> commit the update query with both form and "table2" data -> on successful update, notify user that their information was processed -> thank them.
Something like this ? :
$data2 = mysql_fetch_array (mysql_query("SELECT * FROM table2 WHERE id2 = '1'"));
$data1 = data2['column2'];
mysql_query("INSERT INTO table1 VALUES('value1','$data2') WHERE id1 = id2);

Problems with MySQL Complex Insert (Mutli Row Insert with Sub Select)

I'm having an issue with the following query. With the query I'm attempting to insert a row into the notification table for each user who matches the sub select for the recipient id field.
The query I have is as follows, but is not working:
INSERT INTO
notification (type,
target_id,
sender_id,
recipient_id,
data,
timestamp,
is_unread)
('post',
'$id',
'$senderId',
(SELECT user_id FROM group_member WHERE group_id = '$id'),
'1',
'$timestamp',
'1')
I also tried using VALUES prefixed to the information I am attempting to insert, but I read somewhere that for multi row inserts you're supposed to exclude it and just use the values in parenthesis as I have above?
Assuming your variables are properly escaped, you can do
INSERT INTO
notification (type,target_id,sender_id,recipient_id,
data,`timestamp`,is_unread)
SELECT 'post', '$id','$senderId',user_id, '1','$timestamp', '1'
FROM group_member WHERE group_id = '$id'

Categories