PHP - MYSQL - insert on duplicate key AND(?) - php

Is it possible to connect the duplicate key to another statement.
I just picked some integers (4=4) for the example. In the actuall code I am trying to compare two dates and only if the date in the database row is bigger than the php generated date AND duplicated key it should update unj to 7.
from this:
$sql="INSERT INTO mutable (hid, xsn, unj, for, datetime)
VALUES ('$hid', '$xsn', '$unj', '$for', now()) ON DUPLICATE KEY UPDATE unj=7";
to this:
$sql="INSERT INTO mutable (hid, xsn, unj, for, datetime)
VALUES ('$hid', '$xsn', '$unj', '$for', now()) ON 4=4 AND DUPLICATE KEY UPDATE unj=7";
( ON 4=4 AND ) added.
But this is not working. Is there any way to archive this?
Thank you.
edit: I know I could archive this with using SELECT and then INPUT or UPDATE but I need more efficient code.

INSERT INTO mutable (hid, xsn, unj, `for`, datetime)
VALUES ('$hid', '$xsn', '$unj', '$for', now())
ON DUPLICATE KEY UPDATE unj = IF(datetime > VALUES(datetime), 7, unj)
I tested this and it works.
The VALUES(datetime) refers to the value you tried to insert into the datetime column. It's a convenient way to repeat the value in your ON DUPLICATE KEY UPDATE clause without having to write it twice in the query.
If the condition in IF() returns false, then the default is to set unj = unj which means a no-op.
PS: for is a MySQL reserved word, so it needs to be delimited. It would be simpler to avoid that column name.

Related

MySQL - How to check if a value exists before appending to a TEXT Field?

On duplicated record, I want to update the record by appending a string to the TEXT column in table, on the condition that the appending value does not already exist in that TEXT column.
I have come so far with my query
INSERT INTO events (event_id, event_types)
VALUES ("1", "partyEvent")
ON DUPLICATE KEY UPDATE event_types = CONCAT(event_types, ",testEvent")
Is there a such check with MySQL, or is necessary that I fetch the record and do the comparison myself with PHP?
It looks like event_types is a denormalized field, containing a comma-separated sequence of text strings. With respect, this is a notorious database design antipattern. The next programmer to work on your code will be very unhappy indeed.
I'll answer your question even though it pains me.
First of all, how can you tell whether a particular string occurs within a comma-separated set of text strings? FIND_IN_SET() can do this.
FIND_IN_SET('testEvent', event_types)
returns a value greater than zero if 'testEvent' shows up in the column.
So we can use it in your event_types = clause. If FIND_IN_SET comes up with a positive number, you want event_types = event_types, that is, an unchanged value. If not, you want what you have in your question. How to do this? Use IF(condition,trueval,falseval). Try this:
...UPDATE event_types = IF(FIND_IN_SET('testEvent',event_types) > 0,
CONCAT(event_types, ',', 'testEvent'),
event_types)
There's a much better way however. Make a new table called event_types defined like this.
CREATE TABLE event_types (
event_id INT(11) NOT NULL,
event_type VARCHAR(50) NOT NULL,
PRIMARY KEY (event_id, event_type)
)
This has a compound primary key, meaning it cannot have duplicate event_type values for any particular event_id.
Then you will add a type to an event using this query:
INSERT IGNORE INTO event_types (event_id, event_type)
VALUES (1, 'testEvent');
The IGNORE tells MySQL to be quiet if there's already a duplicate.
If you must have your event types comma-separated for processing by some program, this aggregate query with GROUP_CONCAT() will produce them..
SELECT e.event_id, GROUP_CONCAT(t.event_type ORDER BY t.event_type) event_types
FROM events e
LEFT JOIN event_types t ON e.event_id = t.event_it
GROUP BY e.event_id
You can find all the events with a particular type like this.
SELECT event_id FROM event_types WHERE event_type='testEvent')
Pro tip: Comma separated: bad. Normalized: good.
Don't worry, we've all made this design mistake once or twice.

Mysql, How to read auto increment value in other fields of the same inserting row?

Hello I need to have the transaction id in the comment field of my transaction
mysql_query("INSERT INTO `transactiontb` (`tid`, `amount`, `comment`) VALUES (NULL,'$amount', CONCAT('Transaction # ',`tid`)')");
How can i do this?
Get off of mysql_* functions. Look at MySQLi or PDO.
Don't store the tid twice. Why not concat when you select it instead of storing it that way? This is not the best way.
For reference though, try LAST_INSERT_ID()+1):
INSERT INTO `transactiontb` (`tid`, `amount`, `comment`)
VALUES (NULL, '$amount', CONCAT_WS('Transaction # ', LAST_INSERT_ID()+1))
LAST_INSERT_ID() will give the ID of the previous INSERT not the one from the current INSERT so you must add 1.
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id
The ID that was generated is maintained in the server on a
per-connection basis. This means that the value returned by the
function to a given client is the first AUTO_INCREMENT value generated
for most recent statement affecting an AUTO_INCREMENT column by that
client. This value cannot be affected by other clients, even if they
generate AUTO_INCREMENT values of their own. This behavior ensures
that each client can retrieve its own ID without concern for the
activity of other clients, and without the need for locks or
transactions.
Use the LAST_INSERT_ID() function.
LAST_INSERT_ID() (with no argument) returns a BIGINT (64-bit) value
representing the first automatically generated value that was set for
an AUTO_INCREMENT column by the most recently executed INSERT
statement to affect such a column.
Source: MySQL Documentation
Example:
"INSERT INTO transactiontb(tid, amount, comment) VALUES (NULL,'" . $amount . "', CONCAT_WS('#','Transaction',LAST_INSERT_ID(id+1)))"
Just saw you were also forgetting to put the separator for you CONCAT_WS function, so i fixed it in the example query.

Avoid entering duplicate entries based on date, without using select statement

I am running a insert statement to insert data, but I want to check for any duplicate entries based on date and then do an entry.
All I want is if today a user enters product_name='x', 'x' is unique so that no one can enter product name x again today. But of course the next day they can.
I do not want to run a select before the insert to do the checking. Is there an alternative?
You can either use
1. Insert into... on duplicate update
2. insert.. ignore
This post will answer your question
"INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE"
You can use the mysql insert into... on duplicate update syntax which will basically enter in a new row if one isn't there, or if the new row would have caused a key constraint to kick in, then it can be used to update instead.
Lets say you have the following table:
MyTable
ID | Name
1 | Fluffeh
2 | Bobby
3 | Tables
And ID is set as the primary key in the database (meaning it CANNOT have two rows with the same value in it) you would normally try to insert like this:
insert into myTable
values (1, 'Fluffster');
But this would generate an error as there is already a row with ID of 1 in it.
By using the insert on duplicate update the query now looks like this:
insert into myTable
values (1, 'Fluffster')
on duplicate key update Name='Fluffster';
Now, rather than returning an error, it updates the row with the new name instead.
Edit: You can add a unique index across two columns with the following syntax:
ALTER TABLE myTable
ADD UNIQUE INDEX (ID, `name`);
This will now let you use the syntax above to insert rows while having the same ID as other rows, but only if the name is different - or in your case, add the constraint on the varchar and date fields.
Lastly, please do add this sort of information into your question to start with, would have saved everyone a bit of time :)

How to Update if the data exist else insert the new data (multiple rows)

I need to create a insert and update statement, when today date is not in the database it will insert else it will update the QTY (from excel [this part I have done]) get from today.
But, there have a lots of row need to be insert and update.
1) it will check for the last 4 days in database, if there doesn't include today, it will just insert the data for today and update the last 3 days data. in the other hand, if there contain today it will just update.
P.S: I had try to use INSERT... ON DUPLICATE KEY UPDATE but it only 1 row affected.
If else statement , when i used this it only insert one row of data then the rest it just doing update.
Can give me some advise or example.
suppose you bulk copy your data from excel to a temporary table tbl and your actual table is tbl1 then do something like this
begin transaction;
if not exists(select * from tbl(updlock holdlock) where...)
begin
insert into tbl1...
else
begin
update tbl1...
end
commit;
What language are you using to do this? I have done something similar in Ruby before. I would make the column (Date in your case) unique at the database level then simply try inserting each record. When I get an exception thrown because the Date is not unique I would then proceed to update the QTY.
I found this article on mysql which says it supports multiple insert.
http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
That statement is identical to the following two statements:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=3;
INSERT INTO table (a,b,c) VALUES (4,5,6)
ON DUPLICATE KEY UPDATE c=9;
So if we want to edit straight, we could do something like this.
INSERT INTO table (uniquekey,data) VALUES (1,2),(4,5)
ON DUPLICATE KEY UPDATE data=VALUES(data);

Update if record already exists for todays date

Is there is an easy way to change the following query to check to see if a record already exists for todays date if it does to update it with the newest count value.
mysql_query("INSERT INTO daily_record (PageID, count)
VALUES (".$array['page_id'].",".$array['count'].")");
The column I want to check is a CURRENT_TIMESTAMP field (record_date - part of daily_record table) if a todays date exists for a pageID then an update needs to happen rather than a new insert.
If someone can help that would be amazing!!!
Well if you build the daily_record table like this:
CREATE TABLE daily_record (
pageID INT,
record_date DATE,
count INT,
PRIMARY KEY (pageID,record_date),
INDEX idxPageID (pageID)
)
You could then use the command:
INSERT INTO daily_record (
pageID,record_date,`count`
) VALUES (
1,'2011-03-31',32
) ON DUPLICATE KEY UPDATE `count`=32;
Obviously pageID/record_date/count would be supplied by the calling code. This effectively creates a record for the pageID/day with the given count, or if a record for the pageID/day already exists, then it sets the count to the supplied value.
Using the DATE column type prevents you getting free timestamping BUT that's not particularly useful for this table - the way you describe it - since you don't care about the hours/minutes/seconds.
The key here is the unique index created by the PRIMARY KEY... line. If it's uniqueness would be violated by an insert then an update on it can occur instead.
Best I can come up with is either use a select with if ... then to check for the existance ahead of time, or run the update statement first, check ##rowcount (records affected) and do an insert if it comes back with 0)
i.e. No.
[Edit - this is a little more complex than it seemed at first, because of the DATE thing.]
To UPDATE the record you MUST get the count that you want to update, so that requires you to use a SELECT first. But you need to select the records that are only for the current date.
Let's assume that you have done the code to get the current date into $today.
Then as Kendrick said,
$result=mysql_query("SELECT * from daily_record where PageID=\'$array['page_id']\' and date_field BETWEEN '$today'.' 00:00:00' AND '$today'.' 23:59:59'");
if (!$result)
{ mysql_query("INSERT into daliy_record (PageID,count} VALUES (\'$array['page_id']\',\'$array['count']\')"); }
else
{mysql_query("UPDATE daily_record (count) VALUES (\'$array['count']\') where PageID=\'$array['page_id']\' and date_field=\'$result['date_field']\'");}

Categories