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

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'

Related

INSERT if not exists, else return id

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();

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

PHP Assosiative array Insert into if data doesnt exist in table

I have an assosiative array in PHP which is inserting data into a table
foreach($array as $key => $value){
$query = "INSERT INTO live_list (file_id, date) SELECT ('$key', '$value') FROM dual WHERE NOT EXISTS (SELECT * FROM live_list WHERE file_id = '$key')";
mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
}
However as I have moved from an indexed array to an assosiative array, I can't figure out how to insert this data ONLY if the data in my array does not exist in my table.
Query failed: Operand should contain 1 column(s)
Now I am recieving this error
Any help will be great!
Why the use of a sub-query?
Assuming file_id is a unique field (i.e. no duplicates in the whole table), make it a unique index on the table if it isn't already:
ALTER TABLE live_list
ADD UNIQUE (file_id)
and change your query to
INSERT INTO live_list (file_id, date)
VALUES ('$key', '$value')
ON DUPLICATE KEY UPDATE date = date;
This means that it will simple "update" the value of date to what it already is if it encounters a duplicate key.
Although you should look to bind your parameters to protect against sql injection.
You could do this:
INSERT INTO live_list (file_id, date)
SELECT '$key', '$value'
FROM dual
WHERE NOT EXISTS (SELECT * FROM live_list WHERE file_id = '$key')
DUAL is a dummy table. The logic is that if the sub query does not exist, the dummy table returns one row with the desiered input.

insert multiple records with one ID in single query

Hello i want insert data into 2 different tables.
First table 'Events:'
id,
name,
desc,
date
Second table 'Events_sub_cat:'
id,
event_id,
name,
desc,
date
I want to insert 2 different data in one query like:
INSERT INTO Events (name, desc, date) VALUES ('name', 'desc', 'date')
INSERT INTO Events_sub_cat (event_id, name, desc, date) VALUES (event_id, 'name', 'desc', 'date')
And i want get in the same query the ID of the even what i just inserted in table 'Events'
to let know to another INSERT what is the 'event_id'
There you go a suggestion:
Insert records into two table at once
As said in the post, there's no way to insert without using mysql_insert_id()
functions such as lmysql_insert_id() return the last inserted id.
you can select the last id from Events and put it in the second insert

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);

Categories