Related
I have searched that there is already a way in inserting avoiding the duplicate error
ref: MySQL: Insert record if not exists in table
INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Unknown' AS name, 'Unknown' AS address, '022' AS tele) AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name = 'Unknown'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `table_listnames`;
+----+---------+-----------+------+
| id | name | address | tele |
+----+---------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
| 2 | John | Doe | 022 |
| 3 | Unknown | Unknown | 022 |
+----+---------+-----------+------+
is there a way for this to do in batch?
or how is the format in adding data as a batch
ref: insert multiple rows via a php array into mysql
Planning to integrate this one
$sql = array();
foreach( $data as $row ) {
$sql[] = '("'.mysql_real_escape_string($row['text']).'", '.$row['category_id'].')';
}
mysql_query('INSERT INTO table (text, category) VALUES '.implode(',', $sql));
is there a way?
I would suggest using the ON DUPLICATE KEY syntax for this. This will simplify the query, and allow the use of the VALUES() statement, which is handy to pass parameters from your application.
For this to work, you need a unique (or primary key) constraint on colum name. Create it if it does not exist:
create unique index idx_table_listnames on table_listnames(name);
Then, you can do:
insert into table_listnames(name, address, tele)
values('Unknown', 'Unknown', '022')
on duplicate key update name = values(name)
The conflict clause traps violations on the unique index, and performs a no-op update.
Side note: use parameterized queries to pass data from your application to the query; escaping input is not enough to make your query safe.
It's a php mysqli query where there is a table named result(uid,matchid,playerid,score)
I want to generate a unique id based on number of rows returned by the select statement with matchid
That would look something like this
if matchid is 0 then on first the rows returned would be zero then uid must be
matchid+rows returned
and then saving data with that uid and match id with other details
I hoped it must return something like this...
i.e. if id1(ID) is 0
then the unique id(UID) would be
ID+UID
that is 00,01,02...and so on where the UID would increment based on number of rows returned with the specific id1(ID).
another example, taking a different ID
i.e. if id1(ID) is 1
then according to the above explanation
it would be
ID+UID
i.e. 10,11,12...and so on based on the number of rows returned by that id1(ID)
I have tried to get the number of rows returned by the match id and found that the result given was 0(must indicates null),and scound time it also returns 0 and after the third time it starts incrementing values.
i.e 00,00,01,02 and so on
<?php
$ri=0;
$res=mysqli_query($c,"select rsid from result where mid='$m' ");
$rows=mysqli_num_rows($res);
$ri=$rows++;
echo ("<script> alert( '$ri' ); </script>");
//Unique Match Id for Player Result
$rsid = $m.$ri;
//Saving the data in the table
mysqli_query($c,"insert into result values('$rsid','$m','$u','$k','$w')");
?>
I expected the output to be 00,01,02...
but the output is 00,00,01,02...
To produce your desired results, you can use the INSERT ... SELECT syntax with a COUNT subquery on the result table, in order to retrieve your row count or 0, along with a CONCAT() of the mid to produce the desired rsid value.
To help prevent SQL injection attacks, it is strongly encouraged to use prepared statements,
Assuming rsid is your primary key you can use the following.
Example db-fiddle
//enable mysqli exception handling
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$c = mysqli_connect($host, $user, $pass, $dbname);
$query = <<<'EOL'
INSERT INTO `result`
SELECT
CONCAT(?, COALESCE((SELECT COUNT(r.rsid)
FROM `result` AS r
WHERE r.mid = ?
GROUP BY r.mid), 0)),
?, ?, ?, ?
EOL;
try {
/* example data
* $m = 0;
* $u = 1;
* $w = 1;
* $k = 1;
*/
$stmt = mysqli_prepare($c, $query)
mysqli_stmt_bind_param($stmt, 'ssssss', $m, $m, $m, $u, $k, $w);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
/*
* retrieve the theoretical last record inserted
*/
$stmt = mysqli_prepare($c, 'SELECT MAX(rsid) FROM result WHERE mid = ?');
mysqli_stmt_bind_param($stmt, 's', $m);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $rsid);
if (mysqli_stmt_fetch($stmt)) {
echo $rsid;
}
mysqli_stmt_close($stmt);
} catch(mysqli_sql_exception $e) {
//handle the exception
//echo $e->getMessage();
}
Results per execution
| execution | $rsid |
| 1 | 00 |
| 2 | 01 |
| 3 | 02 |
...
Disclaimer, your current approach of using the total number of rows to generate the rsid is subject to serious data integrity complications. When a
record is deleted from the result table, the retrieved COUNT or mysqli_num_rows will result in a conflicting rsid. Additionally if the mid value is ever changed (a typo is corrected), the rsid value will become invalid.
There are also additional complications to consider with race conditions/hazards. See sql - Do database transactions prevent race conditions for details on preventative measures
For example, if you have a record of 00 in the database already, SELECT CONCAT(mid, COUNT(rsid)) WHERE mid = 0; will return 01. After inserting 01 and then removing 00, your next insert will be a duplicate rsid of 01;
INSERT INTO results(rsid)
VALUES(01);
DELETE FROM results WHERE rsid = '00';
INSERT INTO results(rsid)
VALUES(01); /* error duplicate key */
I recommend using SELECT MAX(rsid) + 1 instead of COUNT(). This will ensure your rsid is not repeated after deletion, but does not resolve the UPDATE mid issue. However you will need to have a minimum mid of 1 for MAX() + 1 to work.
Example db-fiddle
INSERT INTO `result`
SELECT
COALESCE((SELECT MAX(r.rsid) + 1
FROM `result` AS r
WHERE r.mid = ?
GROUP BY r.mid), CONCAT(?, 0)),
?, ?, ?, ?
If you absolutely need to use row count, to avoid the complications, you would need to ensure to only DELETE the highest rsid record within the mid grouping, and never UPDATE the mid column values. Otherwise you will need to rebuild all rsid values, on any change to the table. If you decide to rebuild the rsid values, I suggest using before update and after delete triggers to handle both of these instances and use a DATETIME NULL DEFAULT CURRENT_TIMESTAMP column to determine the ordering of the records.
Alternatively you could generate an rsid only when viewed, by using an AUTO_INCREMENT primary key and an incremental user variable. Then you no longer need to worry about the application controlled rsid, and only be required to insert the mid.
Example db-fiddle
SET #rsid: = NULL;
SET #mid = NULL;
SELECT
result.*,
CONCAT(mid, CASE WHEN #mid != result.mid OR #rsid IS NULL THEN #rsid := 0 ELSE #rsid := #rsid + 1 END) AS rsid,
#mid:=result.mid
FROM result
ORDER BY mid ASC, id ASC;
Result
| id | mid | ... | rsid |
| 1 | 0 | ... | 00 |
| 29 | 0 | ... | 01 |
| 311 | 0 | ... | 02 |
| 20 | 1 | ... | 10 |
| 40 | 1 | ... | 11 |
...
As a last alternative, you can use a segmented AUTO_INCREMENT by specifying a composite primary key of mid, id with the MyISAM engine, which is not capable of transactions or foreign key references. However, there are additional complications with this approach. [sic]
AUTO_INCREMENT values are reused if you delete the row with the biggest AUTO_INCREMENT value in any group.
Example db-fiddle
CREATE TABLE `result` (
`mid` INT(11) UNSIGNED NOT NULL,
`id` INT(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`mid`, `id`)
)
ENGINE=MyISAM
;
INSERT INTO result(mid)
VALUES(0),(1),(0),(2),(0),(1);
SELECT
result.*,
CONCAT(mid, id) AS rsid
FROM result;
Results:
| mid | id | rsid |
| --- | --- | ---- |
| 0 | 1 | 01 |
| 0 | 2 | 02 |
| 0 | 3 | 03 |
| 1 | 1 | 11 |
| 1 | 2 | 12 |
| 2 | 1 | 21 |
To update your current result table you can use
/* remove default value */
ALTER TABLE `result` ALTER `mid` DROP DEFAULT;
/* change engine, add id column, add composite primary key */
ALTER TABLE `result`
ENGINE=MyISAM,
CHANGE COLUMN `mid` `mid` INT(11) NOT NULL FIRST,
ADD COLUMN `id` INT(11) NOT NULL AUTO_INCREMENT AFTER `mid`,
ADD PRIMARY KEY (`mid`, `id`);
I have this table called classes:
+------------+----------+------+-----+----------------+
| Field | Type | Null | Key | Extra |
+------------+----------+------+-----+----------------+
| class_id | int(3) | NO | PRI | auto_increment |
| class_level| int(1) | YES | | |
| class_name | char(1) | YES | | |
+------------+----------+------+-----+----------------+
With data inside like this:
+----------+-------------+------------+
| class_id | class_level | class_name |
+----------+-------------+------------+
| 1 | 0 | N |
| 2 | 1 | A |
| 3 | 1 | B |
| 4 | 2 | C |
| 5 | 2 | D |
| 6 | 3 | E |
| 7 | 3 | F |
+----------+-------------+------------+
With PHP I want to increment all values inside class_level except 0.
So I made this PHP/MySQL function:
mysql_query("UPDATE classes SET class_level = (class_level + 1) WHERE class_level != 0") or die(mysql_error());
This (what is weird) does not add 1 to each class_level except theese equal to 0, but adds 2 or 3 or 4! I haven't found a rule, that this script would add either 2 or 3 or 4. This is RANDOMLY picked. And there is no error outputted too.
All it does it adds randomly 2 or 3 or 4 to each row.
So, to debug it, I have done this PHP code to add to each one by one:
$query = mysql_query("SELECT * FROM `classes` WHERE `class_level` != 0");
while ($row = mysql_fetch_assoc($query)) {
$class_id = $row['class_id'];
$class_level = $row['class_level'];
$class_level = $class_level + 1;
var_dump($class_level);
mysql_query("UPDATE `classes` SET `class_level` = '$class_level' WHERE `class_id` = '$class_id'") or die(mysql_error());
}
The output from var_dump is:
int(2) int(2) int(3) int(3) int(4) int(4)
But in database in table I get following result:
+----------+-------------+------------+
| class_id | class_level | class_name |
+----------+-------------+------------+
| 1 | 0 | N |
| 2 | 4 | A |
| 3 | 4 | B |
| 3 | 5 | C |
| 4 | 5 | D |
| 5 | 6 | E |
| 6 | 6 | F |
+----------+-------------+------------+
This is an empty file with just MySQL connection and the code above, so there is no loop above it.
Here is my version information: PHP version: 5.2.12, MySQL Client API version 5.1.44. Note that I cannot install mysqli nor PDO.
EDIT:
Just after executing the MySQL query I have outputted data from table, and the result was, as it should be. But in table itself (or on refresh with code just for output) there was 3 added, not 1!
EDIT 2:
I tried executing this MySQL query from command line (aka Webmin tool for SQL commands) and the result was, as it should be: 1 was added.
EDIT
Added SQL Fiddle demonstration: http://sqlfiddle.com/#!9/efa05b/1
create table classes
( class_id int(3) not null auto_increment primary key comment 'pk'
, class_level int(1)
, class_name char(1)
)
;
insert into classes (class_id,class_level,class_name) values
('1','0','N')
,('2','1','A')
,('3','1','B')
,('4','2','C')
,('5','2','D')
,('6','3','E')
,('7','3','F')
;
update classes set class_level = (class_level + 1) where class_level != 0
;
A query verifies that expected result is returned. Each row (other than row with class_level=0) has been updated, with class_level incremented by exactly 1.
select * from classes order by class_id
class_id class_level class_name
-------- ----------- ----------
1 0 N
2 2 A
3 2 B
4 3 C
5 3 D
6 4 E
7 4 F
original answer
Assuming that there isn't a BEFORE/AFTER UPDATE trigger on the table, given the SQL statement being executed:
UPDATE classes SET class_level = (class_level + 1) WHERE class_level != 0
The most logical explanation for the behavior is that the SQL statement is being executed multiple times within the function, or, the function is being called multiple times.
To verify this, you could temporarily turn on the MySQL general log, run the test, disable the general log, and review... and you're going to find multiple executions of the statement. If you don't have access to the MySQL server, then the next best would be to echo out a line immediately before the statement is executed; you're going to see that line echoed out multiple times.
Highly unlikely that this is a bug in the MySQL database. (Verify there isn't a TRIGGER defined on the table.)
Also, test that statement using a different client, like mysql command like client, or phpmyadmin. And verify the statement is working correctly.
FOLLOWUP
Given that your test of the SQL statement from a different client gives the expected results, I think this demonstrates this isn't a problem with the MySQL database or the SQL statement.
For some reason, that SQL statement is being executed multiple times. As a next step in debugging, I would add some more code. I'd temporarily create a "log" table, using MyISAM engine, containing an auto_increment id, a datetime column, and an informational string:
CREATE TABLE debug_log
( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
, dt DATETIME
, info VARCHAR(40)
) Engine=MyISAM
Then add another SQL statement in your function to insert a row to that table, immediately before and/or after the execution of the UPDATE statement
INSERT INTO debug_log (dt, info) VALUES (SYSDATE(), 'my function before update')
Then, run the test, and see how many rows get inserted into the debug_log table.
To get an error thrown if this statement is executed more than one time, supply a fixed value for the id column, e.g.
INSERT INTO debug_log (id, dt, info)
VALUES (123, SYSDATE(), 'my function before update')
With the fixed value for id, if that statement gets called a second time, then MySQL will throw a duplicate key exception.
As I mentioned previously, based on the information provided, I suspect that your function is being called multiple times. (I don't have sufficient information to actually make that determination; that's just a hunch.)
Here is the simple solution below
<?php
print("<h1>BEFORE</h1>");
$q =mysql_query("select *from classes ");
while($row=mysql_fetch_array($q)){
print("$row['class_id'] - $row['class_level'] - row[$class_name] <br/>");
}
mysql_query("UPDATE classes SET class_level = class_level+1 WHERE class_level>0") or die(mysql_error());
print("<h1>AFTER</h1>");
$q =mysql_query("select *from classes ");
while($row=mysql_fetch_array($q)){
print("$row['class_id'] - $row['class_level'] - row[$class_name] <br/>");
}
?>
You dnt need to write any single php line to do what you are actually want to do.
Ok i have updated the code try this way. First it will get data & show . Secondly ,it will update the data .finally,display the data. Try this way hope you can find your problem.
I solved this by simply doing something like this:
mysql_query("UPDATE classes SET class_level = 2 WHERE class_level = 1");
mysql_query("UPDATE classes SET class_level = 3 WHERE class_level = 2");
mysql_query("UPDATE classes SET class_level = 4 WHERE class_level = 3");
I have just those three classes so it gets the job done.
It isn't the way I wanted to go with, but it works. The bug was really odd and I'd rather not go back to it. I hope this helps someone though.
P.S. How could I possibly not think about that in the first place XD
I'm trying to set the Auto Increment of my tables st_id to = 201406001
query:
ALTER TABLE
support_ticket AUTO_INCREMENT=201406001
When doing this it worked and now my "st_id" (AI, Primary key) is set to 201406001 just as I wanted.
When I ran that query it said it affected 4 rows which is right, because there were 4 rows in the table when I ran that query.
But now when I try and update the status of a specific column in one of those 4 rows, it will not update.
Is my ALTER TABLE query wrong?
I tried running the following query to only target the st_id like this, but gave me an error.
ALTER TABLE
support_ticket.st_id AUTO_INCREMENT=201406001
FROM
support_ticket
ERROR
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 'FROM
support_ticket' at line 3
So my question is, should I stick with my original query, as it did work, or should I try to get the 2nd query working?
Also, could running that 1st query be that be the reason I cannot update my column now?
This is my first time using ALTER TABLE so any help would be of use.
Here is my update code:
Form
<form method="POST" action="close.php" enctype="multipart/form-data">
<input type="hidden" name="st_id" value="<?php echo escape ($t->st_id); ?>">
<h3>Close this ticket...</h3>
<select name="status">
<option value="<?php echo escape($t->status); ?>">Current Status: OPEN</option>
<option value="0">CLOSE</option>
</select>
<input type="submit" value="CLOSE"><input type="button" value="Cancel" onclick="window.location = '/admin/maintenance/'">
</form>
Action script:
include($_SERVER['DOCUMENT_ROOT'] . "/core/init.php");
$st_id = $_POST['st_id'];
$status = $_POST['status'];
$updatestatus = DB::getInstance()->UPDATE('support_ticket', $st_id, array(
'status' => $status,
));
echo "The ticket was successfully closed.<br />
Solution to my UPDATE problem:
Finally got it to update by this:
$st_id = $_POST['st_id'];
$status = $_POST['status'];
$updatestatus = DB::getInstance()->query("UPDATE `support_ticket` SET `status` = $status WHERE `st_id` = $st_id");
It seems to trial to auto-increment according to year or month. You can use MySQL Custom AUTO_INCREMENT values as follows:
(read the article first)
I changed the function getNextCustomSeq the line:
SET #ret = (SELECT concat(sSeqGroup,'-',lpad(nLast_val,6,'0')));
to
SET #ret = (SELECT concat(sSeqGroup,lpad(nLast_val,3,'0')));
Then I create table and triggeras follows:
CREATE TABLE ticket(
id int not null primary key auto_increment,
autonum int not null
);
DELIMITER $$
CREATE TRIGGER ticket_autonums_bi BEFORE INSERT ON ticket
FOR each ROW
BEGIN
SET NEW.autonum = getNextCustomSeq(date_format(now(),'%Y%m'),date_format(now(),'%Y%m'));
END$$
delimiter ;
Note: The function date_format(now(),'%Y%m') will return current year and mont like "201406"
Now insert some values:
insert into ticket(id)
values (null),(null),(null),(null),(null),
(null),(null),(null),(null),(null);
Select the inserted data:
mysql> select * from ticket;
+----+-----------+
| id | autonum |
+----+-----------+
| 1 | 201406001 |
| 2 | 201406002 |
| 3 | 201406003 |
| 4 | 201406004 |
| 5 | 201406005 |
| 6 | 201406006 |
| 7 | 201406007 |
| 8 | 201406008 |
| 9 | 201406009 |
| 10 | 201406010 |
+----+-----------+
10 rows in set (0.00 sec)
ALTER TABLE ... AUTO_INCREMENT=201406001 only means that the next AI value generated will be that value. It doesn't change the id value in any of the current rows of data in the table.
The "affected rows" message meant that it performed a table copy as part of the ALTER TABLE. Some older versions of MySQL would naively copy all the rows in the table, even though you wouldn't think it had to to perform the metadata change.
So if you try to UPDATE ... WHERE id=201406001 it will not apply to your existing rows.
With ALTER you update your tabledescription (ie columnnames, values for autoincrement).
If you want to update the values of a table you have to use UPDATE. ie:
UPDATE support_ticket SET status = 'closed' WHERE id = 1234;
If you're new to SQL have a look at w3schools.com. they have some tutorials (http://www.w3schools.com/sql/sql_update.asp)
Clarification of what I'm trying to accomplish:
Update "user name", if there is a record with the same e-mail but no name. if user already has a name, then don't make any changes
I have a website where all users can be "subscribers, entrepreneurs or investors". If a subscriber (of whom I have previously only asked for email) chooses to upload a business idea then that person will probably use the same e-mail address as before only this time adding a name. So I'd like to INSERT INTO, and if e-mail already exists - add the name, but only if there is not a name there already (so that a person cannot simply over write somebody else's details).
I've gotten this far:
mysql_query("
INSERT INTO users
(email, name)
VALUES
('" .$epost. "', '" .$namn. "')
ON DUPLICATE KEY UPDATE
name=VALUES(name) -->[if name == '', else do nothing...]
");
Now it replaces the current name with a new one if different.
I searched "on duplicate update if field empty"
and found:
http://forums.aspfree.com/sql-development-6/on-duplicate-key-update-but-only-if-value-isn-t-482012.html (merging?)
conditional on duplicate key update (closer, but I don't want to update it if it differs, only if the field is empty.)
http://bytes.com/topic/php/answers/914328-duplicate-key-update-only-null-values (if the input is blank.. well it's not)
http://boardreader.com/thread/Insert_on_duplicate_key_update_only_if_c_can8Xachr.html (the layout of this page got me lost)
http://www.digimantra.com/tutorials/insert-update-single-mysql-query-duplicate-key/ (it simply updates)
I believe this might be kind of what I'm after (?) http://thewebfellas.com/blog/2010/1/18/conditional-duplicate-key-updates-with-mysql but I haven't managed to make it work
This code:
mysql_query("UPDATE users SET name='".$namn."'
WHERE email='".$epost."' AND name =''");
updates the name, only if it's previously null, and that's what I'm after however it does not insert a new record if email doesn't already exist.
My table
So I tried this:
mysql_query("
INSERT INTO users
SELECT email, 'victoria' FROM users
WHERE email='victoria#hejsan.se' ON DUPLICATE KEY UPDATE name = 'victoria'
");
and I tried this:
mysql_query("
INSERT INTO users
SELECT email, 'yay' from users
WHERE email='victoria#hejsan.se'
ON DUPLICATE KEY
UPDATE name = values(name)
");
from #Fluffeh 's answer
but nothing happens. Did i misinterpret the answer?
It just hit me that if someone already has an account then they should also have a password already, and so I'll just ask them to verify their password, and make sure I do an AJAX call while they insert their e-mail to see if the e-mail is already registered :) And so then this is no longer an issue, and I think that is the solution I'll go with. !)
The only way that you could use the insert .... on duplicate key... syntax to solve your issue would be if name and email made a composite key - and I think you would be better off using an auto_increment as a primary key.
You might have to put a little logic into the PHP to do a check first, then insert or update - or write a function to do that same test for you - but neither will be a simply query that you can just fire off.
Edit: Not sure if this is what you want to do, but I think that the best solution for your requirements is to actually use two tables in a one to many relationship.
Table-Users
id | email | name
create table users(
id int(10) not null auto_increment,
email varchar(100),
name varchar(100),
primary key(email, name)
);
Table-Ideas
id | userID | idea
create table users(
id int(10) not null auto_increment primary key,
userID int(10) not null,
idea text
);
With the primary key on the table, you can safetly do an insert... duplicate... without worrying about over-writing folks. The second table will however allow you to have the ideas stored safetly locked to the user, and let you have a number of ideas per user. As the relationship is the users.id to ideas.userID you won't lose who owns it even if their details are updated.
Edit: (aka, ZOMG facepalm)
$query="
update users
set name='".$userName."'
where
email='".$userEmail."'
and name is null";
Edit 2: (aka, wipes brow)
insert into users
select email, '".$namn."' from users where email='".$epost."'
on duplicate key
update name = values (name);
and here it is working:
mysql> create table test1 (myName varchar(10) unique, myEmail varchar(10));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into test1 values ('Tom','something');
Query OK, 1 row affected (0.01 sec)
mysql> insert into test1 values('Nick',null);
Query OK, 1 row affected (0.00 sec)
mysql> select * from test1;
+--------+-----------+
| myName | myEmail |
+--------+-----------+
| Tom | something |
| Nick | NULL |
+--------+-----------+
2 rows in set (0.00 sec)
mysql> insert into test1 select myName, myEmail from test1
where myName='Tom' on duplicate key update myEmail = values (myEmail);
Query OK, 0 rows affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from test1;
+--------+-----------+
| myName | myEmail |
+--------+-----------+
| Tom | something |
| Nick | NULL |
+--------+-----------+
2 rows in set (0.00 sec)
mysql> insert into test1 select 'Tom', myEmail from test1
where myName='Tom' on duplicate key update myEmail = values (myEmail);
Query OK, 0 rows affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from test1;
+--------+-----------+
| myName | myEmail |
+--------+-----------+
| Tom | something |
| Nick | NULL |
+--------+-----------+
2 rows in set (0.00 sec)
mysql> insert into test1 select myName, 'Something Else' from test1
where myName='Tom' on duplicate key update myEmail = values (myEmail);
Query OK, 2 rows affected, 1 warning (0.01 sec)
Records: 1 Duplicates: 1 Warnings: 1
mysql> select * from test1;
+--------+------------+
| myName | myEmail |
+--------+------------+
| Tom | Something |
| Nick | NULL |
+--------+------------+
2 rows in set (0.00 sec)
mysql> insert into test1 select myName, null from test1
where myName='Nick' on duplicate key update myEmail = values (myEmail);
Query OK, 0 rows affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from test1;
+--------+------------+
| myName | myEmail |
+--------+------------+
| Tom | Something |
| Nick | NULL |
+--------+------------+
2 rows in set (0.00 sec)
mysql> insert into test1 select myName, 'yay' from test1
where myName='Nick' on duplicate key update myEmail = values (myEmail);
Query OK, 2 rows affected (0.01 sec)
Records: 1 Duplicates: 1 Warnings: 0
mysql> select * from test1;
+--------+------------+
| myName | myEmail |
+--------+------------+
| Tom | Something |
| Nick | yay |
+--------+------------+
2 rows in set (0.00 sec)
Edit 3: Try this for your $query
insert into table1 select coalesce(email,'".$epost."') as email, coalesce(name,'".$namn."') as name from table1
where email='".$epost."' on duplicate key update name = values (name);
If you want to update a field that is already exist, you can do this as;
-- MySQL Reference
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
-- so your code
INSERT INTO users
(email, name)
VALUES
('" .$epost. "', '" .$namn. "')
ON DUPLICATE KEY UPDATE email=VALUES(email), name=VALUES(name)
http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
UPDATE
At this point, you need "MySQL conditional insert". Let's try it;
CREATE TABLE IF NOT EXISTS `users` (
`name` varchar(50) NOT NULL,
`email` varchar(255) NOT NULL,
UNIQUE KEY `email` (`email`)
)
INSERT INTO users (name, email) VALUES('kerem', 'qeremy[atta]gmail[dotta]com');
INSERT INTO users (name, email) VALUES('test', 'test#example.com');
>> 2 rows inserted. ( Query took 0.0005 sec )
-- this is your part (regarding email field is UNIQUE, so WHERE email='search email')
INSERT INTO users (name, email)
SELECT 'test', 'test#example.com' FROM DUAL WHERE NOT EXISTS (
SELECT * FROM users WHERE email = 'test#example.com' LIMIT 1
);
>> 0 rows inserted. ( Query took 0.0003 sec )
https://www.google.com/search?q=conditional+insert+mysql
http://allurcode.com/2011/04/15/mysql-conditional-insert/ (which is useful search result)
UPDATE 2
If this does not work for you, then you can do your work like (just an input);
mysql_query("INSERT IGNORE INTO users (name, email) VALUES('$name', '$email')");
if (!mysql_insert_id()) {
mysql_query("UPDATE users SET name='$name' WHERE name='' AND email='$email'");
}
Or;
mysql_query("UPDATE users SET name='$name' WHERE name='' AND email='$email'");
if (mysql_affected_rows() < 1) {
mysql_query("INSERT INTO users (name, email) VALUES('$name', '$email')");
}
I'd like to suggest this solution using the control function IFNULL(exp1,exp2), defined as "if exp1 is not null, returns exp1; if exp1 is null, returns exp2".
http://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html
INSERT INTO users (name, email) VALUES ('$name','$email')
ON DUPLICATE KEY UPDATE name = IFNULL(name, VALUES(name))
Of course you must be beyond this somehow, but it helped me.