if id exist use on duplicate key, else insert - php

I have a database with following table test_users:
| id | Username | Password |
| 1 | pat | ***** |
| 2 | roger | ***** |
| 3 | luke93 | ***** |
And to insert a new row I use following code, and it works fine:
$sql = $conn->prepare("INSERT INTO `test_users` (`Username`, `Password`) VALUES (?,?)");
$sql->bind_param('ss',$name, $email);
But now i am trying to make a "update profile"-page and I wanted to use ON DUPLICATE KEY. That means I need to check if idexists and if so update the row. Neither Username or Password is Unique, but id is. I have a $_SESSION["id"] which is available if the user is logged in. Can I use that in some way?
So how do I write a SQL-sentence that finds out if id exist, and if so, overwrite it with ON DUPLICATE KEY (or a better way)?

first write selct query and count num rows if its 0 then insert query fire else update query

UPDATE works the same as an insert. You just need to pass the WHERE condition.
You can do this with the following code, Try it
$id = $_SESSION['id'];
$sql = "UPDATE test_users SET Username=?, Password=? WHERE id=?";
$stmt = $conn->prepare($sql);
$stmt->bind_param($Username, $Password, $id);
$stmt->execute();

Assign unique key of your unique field and try below query
Insert into a MySQL table or update if exists
INSERT INTO test_user(id, username, password) VALUES(1, "test", "test") ON DUPLICATE KEY UPDATE
username="test", password="test"

Use INSERT ... ON DUPLICATE KEY UPDATE
QUERY:
INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE
name="A", age=19
credits to Donnie

Related

How to check how many rows were updated and inserted in a ON DUPLICATE statement?

I have a statement that looks like this:
$count=0;
while($row = pg_fetch_assoc($result)){
$sql=("INSERT INTO joblist (job_no, billed, completed, paid, paid_amount, inv_no, invoice, type, o_submitted, approval_date, gals, jobtype, name, state, region, territory)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE
job_no=VALUES(job_no), billed=VALUES(billed),completed=VALUES(completed), paid=VALUES(paid), paid_amount=VALUES(paid_amount), inv_no=VALUES(inv_no), invoice=VALUES(invoice), type=VALUES(type), o_submitted=VALUES(o_submitted), approval_date=VALUES(approval_date), gals=VALUES(gals), jobtype=VALUES(jobtype), name=VALUES(name), state=VALUES(state), region=VALUES(region), territory=VALUES(territory)");
$stmt = $conn->prepare($sql);
$stmt->bind_param("ssssssssssssssss",$job_no, $billed, $completed, $paid, $paid_amount, $inv_no, $invoice, $type, $o_submitted, $approval_date, $gals, $jobtype, $name, $state, $region, $territory);
$stmt->execute();
$count++;
}
The problem is, I cannot decipher between updated rows and inserted rows. Is there a way I can do this?
I know i can use the effected rows function, but it reads the same if updated/inserted. Any ideas? thanks!
You're looking for an UPSERT with a RETURNING clause.
Taking into account the following table a records ..
CREATE TEMPORARY TABLE t
(id INT PRIMARY KEY, name TEXT);
INSERT INTO t VALUES (1,'elgar'),(2,'bach'),(3,'brahms');
.. you can use an UPSERT to catch a primary key conflict and ask the query to return the affected records. You can put this insert inside a CTE and count it with a new query. The following query will insert two already existing primary keys (1 and 2) and a new one (4):
WITH j (affected_rows) AS (
INSERT INTO t VALUES (1,'edward'),(2,'johann sebastian'),(4,'schubert')
ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name
RETURNING *
) SELECT count(affected_rows) FROM j;
count
-------
3
See the results yourself :-)
SELECT * FROM t ORDER BY id;
id | name
----+------------------
1 | edward
2 | johann sebastian
3 | brahms
4 | telemann

Get last inserted id of any table in mysql

I'm importing a .sql file via php. My .sql file contains multiple tables and I want the last inserted id of a particular table.
So, how to get last inserted id of any table by table name?
Any idea how to get the id?
Please don't suggest, get id by select query to get MAX id.
As long as auto_increment is defined, that last inserted auto increment id can be retrieved from information_schema.tables:
select IF(auto_increment = 1,
'No row has been inserted',
auto_increment - ##auto_increment_increment) As LastInsertedId
from information_schema.tables
where table_schema = 'DBName' and table_name = 'TableName';
This can be done in both mysql and mysqli.
$conn = mysqli_connect($servername, $username, $password, $dbname);
$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('abc', 'xyz', 'abc#example.com')";
if (mysqli_query($conn, $sql)) {
$last_id = mysqli_insert_id($conn);}
in mysql
mysql_connect($servername, $username, $password);
mysql_select_db($dbname);
$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('abc', 'xyz', 'abc#example.com')";
if (mysql_query($sql)) {
$last_id = mysql_insert_id();}
We had.
id | value
1 | 10
3 | 20
Then we inserted 2 | 15, so it had become
id | value
1 | 10
2 | 15
3 | 20
(Remind, we have a .sql file, not a live connection)
And now you want to know, that the last one was 2? If so — it's impossible. .sql file doesn't keep that kind of information, only bare data and some meta.
Try these functions
If you're using PDO, use PDO::lastInsertId
If you're using Mysqli, use mysqli::$insert_id
But if you have to, use mysql_insert_id.

Inserting data to two tables at once in mysql

I have two mysql tables:
table1_id (PK) | table1_data
and
table2_id (PK) | table1_id (FK) | table2_data
and they both together have to be created at once to represent single object. Primary keys are auto incremented, so after inserting table1_data when I move on to creating table2, how can I get the correct, freshly created table1_id value to insert there?
I'm doing it in php:
$stmt = $conn->prepare("INSERT INTO table1 (`table1_data`) VALUES (:data)");
$stmt->bindParam(':data', $data);
$stmt->execute();
$stmt2 = $conn->prepare("INSERT INTO table2 (`table1_id`,`table2_data`) VALUES (:id,:data)");
$stmt2->bindParam(':id', $table1_id); //how can I get the id of row just created above by stmt?
$stmt2->bindParam(':data', $data2);
$stmt2->execute();
You can use the PDO::lastInsertId method for that. Call it after executing your first insert, so you get:
$stmt = $conn->prepare("INSERT INTO table1 (`table1_data`) VALUES (:data)");
$stmt->bindParam(':data', $data);
$stmt->execute();
$table1_id = $conn->lastInsertId();
You can then use $table1_id in your second query.

Does an SQL query like this exist?

I found something on google which said MySql allows me to do something like this:
$sql = "IF(EXISTS(SELECT api_key, username FROM credentials WHERE id = 0))
THEN UPDATE credentials SET api_key = ?, username = ? WHERE id = 0 ELSE
INSERT INTO credentials (api_key, username) VALUES (?, ?) END IF";
This is the function the query makes part of:
protected function store_credentials($config_file_path = 'envato_credentials_config.json') {
$credentials_config = $this->get_envato_config($config_file_path);
$sql = "INSERT INTO credentials (api_key, username, last_update) VALUES (?, ?, NOW()) ON DUPLICATE KEY UPDATE api_key = values(api_key), username = values(username), last_update = values(last_update)";
if ($stmt = $this->connect->prepare($sql)) {
$stmt->bind_param('ss', $credentials_config['API'], $credentials_config['User']);
$stmt->execute();
$stmt->close();
} else {
return false;
}
}
Can I do something like that ? And am I understanding the statement clearly, if no values are found inside those two columns then new values will be inserted, else it will only update ?
You could use MySQL's on duplicate key syntax:
INSERT INTO credentials (api_key, username) VALUES (?, ?)
ON DUPLICATE KEY UPDATE api_key = values(api_key), username = values(username);
mysql has REPLACE syntax which does this. If record exists it updates it (actually deletes old row and inserts new row) otherwise inserts.
http://dev.mysql.com/doc/refman/5.0/en/replace.html
13.2.7. REPLACE Syntax
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name [(col_name,...)]
{VALUES | VALUE} ({expr | DEFAULT},...),(...),...
Or:
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
SET col_name={expr | DEFAULT}, ...
Or:
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name [(col_name,...)]
SELECT ...
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted. See Section 13.2.5, “INSERT Syntax”.
REPLACE is a MySQL extension to the SQL standard. It either inserts, or deletes and inserts. For another MySQL extension to standard SQL—that either inserts or updates—see Section 13.2.5.3, “INSERT ... ON DUPLICATE KEY UPDATE Syntax”.
Note that unless the table has a PRIMARY KEY or UNIQUE index, using a REPLACE statement makes no sense. It becomes equivalent to INSERT, because there is no index to be used to determine whether a new row duplicates another.
Values for all columns are taken from the values specified in the REPLACE statement. Any missing columns are set to their default values, just as happens for INSERT. You cannot refer to values from the current row and use them in the new row. If you use an assignment such as SET col_name = col_name + 1, the reference to the column name on the right hand side is treated as DEFAULT(col_name), so the assignment is equivalent to SET col_name = DEFAULT(col_name) + 1.
To use REPLACE, you must have both the INSERT and DELETE privileges for the table.

What is the correct syntax for INSERT INTO ... ON DUPLICATE KEY UPDATE in MySQL?

my table(s) structure (MySQL / each one is same as below)
+-------+--------------+------+------+-------------------+
| Field | Type | Null | Key | Default |
+-------+--------------+------+------+-------------------+
| id | int(11) | NO | PRI | AUTO INCREMENT |
| lesson| varchar(255) | NO | | LESSON_NAME |
| exam | char(50) | NO |UNIQUE| NO DEFAULT |
| quest | text | NO | | NO DEFAULT |
| answer| text | NO | | NO DEFAULT |
| note | text | NO | | NO DEFAULT |
+-------+--------------+------+------+-------------------+
and i'am posting some values to add this table via ajax ($post) - PHP 5.0
in database.php there is a function to get posted data and add to table
function update_table ($proper_table, $name, $question, $answer, $note) {
$sql = "INSERT INTO $proper_table (id, lesson, exam, quest, answer, note) VALUES ('', '', $name, $question,$answer,$note) ON DUPLICATE KEY UPDATE exam = $name, quest = $question, answer = $answer, note = $note";
$result= mysql_query($sql)or die(mysql_error());
}
$proper_table variable is taken by another variable to add this record to correct table.
(NOTE: Original table fields and variables are different (Turkish), to be more understandable i traslated to english but the syntax is the same as you see.)
Question : I want to check that if there is a record that exam field is same then all these variables will be used for updating this record, otherwise let function put this record to proper table as a new record.
But i'am getting error like below
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
is there any faulty coding? and what can be the solution?
Thanks right now...
function update_table ($proper_table, $name, $question, $answer, $note) {
$sql = "INSERT INTO $proper_table (lesson, exam, quest, answer, note) VALUES ('', '$name', '$question','$answer','$note') ON DUPLICATE KEY UPDATE quest = VALUES(quest), answer = VALUES(answer), note = VALUES(note)";
$result= mysql_query($sql)or die(mysql_error());
}
Just breaking this out I'll detail the changes
$sql = "INSERT INTO $proper_table
// Removed the PK (primary key) AI (auto increment) field - don't need to specify this
(lesson, exam, quest, answer, note)
// Likewise removed PK field, and added quotes around the text fields
VALUES ('', '$name', '$question','$answer','$note')
ON DUPLICATE KEY UPDATE
// If you specify VALUES(fieldName) it will update with the value you specified for the field in the conflicting row
// Also removed the exam update, as exam is the UNIQUE key which could cause conflicts so updating that would have no effect
quest = VALUES(quest), answer = VALUES(answer), note = VALUES(note)";
You need to wrap you string variables in single quotes in your SQL '$name' for example. Otherwise mysql thinks you are referencing column names.
With that query, when you add ON DUPLICATE KEY UPDATE... it will update when the id es the same than the id that you are sending, in this case you are not sending an id as parameter so it will never update because you have the id with auto-increment.
A solution could be that you read the table where exam equals the parameter you are sending, something like this:
SELECT id FROM $proper_table;
If it is null the you execute an insert, if it is not null the you update taking as parameter the id that you are getting from the select
id auto-increments, so presumably you don't want to set an empty string as id.
Try:
$sql = "INSERT INTO $proper_table (lesson, exam, quest, answer, note) VALUES ('', $name, $question,$answer,$note) ON DUPLICATE KEY UPDATE exam = $name, quest = $question, answer = $answer, note = $note";
You have to make it like this
<?php
function update_table($proper_table, $name, $question, $answer, $note, $id) {
$sqlQuery = "INSERT INTO '".$proper_table."' SET
name = '".$name."',
question = '".$question."',
answer = '".$answer."',
note = '".$note."' WHERE id = '".$id."'";
$result= mysql_query($sqlQuery)or die(mysql_error());
}
?>

Categories