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.
Related
I'm trying to insert data into my database. I'm able to insert it using INSERT INTO. However I want to check, if the database already has the ID and if it has I want it to just update the records.
$check = $db->query("SELECT Fuid FROM users WHERE Fuid='$fuid_db'");
//IF the user is new
if(empty($check))
{
$insert = $db->query("INSERT INTO users (Fuid, Ffname, Femail) VALUES ('$fuid_db', '$ffname_db', '$femail_db'");
}
else
{
//ELSE update the information
$update = $db->query("UPDATE users SET Ffname='$ffname_db', Femail='$femail_db' WHERE Fuid='$fuid_db'");
}
How come this is not working? I'm using ERROR_REPORTING(E_ALL),
but I'm not getting any errors. It seems like the issue is the "checking" before inserting. Without the checking part it works fine but now it's not inserting anything.
The Problem
$db->query() returns an (maybe empty) mysqli_result object. So empty($check) evaluates to false (since empty($var) returns true only if $var is zero, false, an empty string, an empty array or null) and thus an UPDATE is performed, no matter if there is a corresponding id or not.
To check if there is a record you have to use $check->num_rows to get the number of records containing the id.
Better
The ON DUPLICATE KEY UPDATE command should work for you.
INSERT INTO users (Fuid, Ffname, Femail)
VALUES ('$fuid_db', '$ffname_db', '$femail_db')
ON DUPLICATE KEY UPDATE users
SET Ffname = '$ffname_db', Femail = '$femail_db'
This way you don't have to make a SELECT first, so you reduce the number of database calls.
Notice: This only works, if Fuid is set as a unique key (or primary key).
Security
The way you use the SQL commands is vulnerable to SQL injection. You should use prepared statements.
Using prepared statements, your code would look like this:
$stmt = $db->prepare("INSERT INTO users (Fuid, Ffname, Femail)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE users
SET Ffname = ?, Femail = ?");
$stmt->bind_param('issss',$fuid_db,$ffname_db, $femail_db,$ffname_db, $femail_db)
$stmt->execute();
First and foremost, for security reasons you should not insert value that way.
But if we ignore it for now, you can instead use ON DUPLICATE KEY UPDATE as below provided that Fuid is a primary key
INSERT INTO users (Fuid, Ffname, Femail) VALUES ('$fuid_db', '$ffname_db', '$femail_db')
ON DUPLICATE KEY UPDATE users SET Ffname = '$ffname_db', Femail = '$femail_db'
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
I am inserting multiple rows using one query and, obviously, the ID column auto increments each row. I want to create another ID column and have the ID remain the same for all rows inserted during the query. So if I insert 10 rows during one query, I want all 10 rows to have the id "1". How can this be done? Thanks for any help
If I understood your question correctly, you want to supply an ID for the specific group of INSERT statements.
Assumming you have this schema
CREATE TABLE TableName
(
RecordID INT AUTO_INCREMENT PRIMARY KEY,
OtherColumn VARCHAR(25) NOT NULL,
GroupID INT NOT NULL
)
You can have two statements for this:
1.) Getting the last GroupID and increment it by 1.
SELECT COALESCE(MAX(GroupID), 0) + 1 AS newGroupID FROM TableName
2.) once you have executed it, store the value in a variable. Use this variable for all the insert statement,
$groupID = row['newGroupID'];
$insert1 = "INSERT INTO TableName(OtherColumn, GroupID) VALUES ('a', $groupID)";
$insert2 = "INSERT INTO TableName(OtherColumn, GroupID) VALUES ('b', $groupID)";
$insert3 = "INSERT INTO TableName(OtherColumn, GroupID) VALUES ('c', $groupID)";
UPDATE 1
SQLFiddle Demo
I'm performing a transaction (using PDO), however I need to grab the insert id of the first element in the transaction, for example:
BEGIN
INSERT INTO user (field1,field2) values (value1,value2)
INSERT INTO user_option (user_id,field2) values (LAST_INSERT_ID(),value2);
COMMIT;
Then do the pdo stuff:
[...]
$pdo->execute();
$foo = $pdo->lastInsertId(); // This needs to be the id from the FIRST insert
Is there a way to get the last insert id from the first element in a transaction? Perhaps using something like the following:
BEGIN
INSERT INTO user (field1,field2) values (value1,value2)
SELECT id AS user_id FROM user WHERE id=LAST_INSERT_ID()
INSERT INTO user_option (user_id,field2) values (LAST_INSERT_ID(),value2);
COMMIT;
$pdo->execute();
$fooArray = $pdo->fetchAll();
$lastId = $fooArray[0]['user_id'];
Am I completely out to lunch with ^ ? Is there a better way to do this?
EDIT 1
Based on suggestion, i've updated the query to use variables... however, i don't know how to retrieve the variable values using PDO. Using $stmt->fetchAll() just returns an empty array;
BEGIN
DECLARE User_ID int
DECLARE Option_ID int
INSERT INTO user (field1,field2) values (value1,value2);
set User_ID = select LAST_INSERT_ID();
INSERT INTO user_option (user_id,field2) values (LAST_INSERT_ID(),value2);
set Option_ID = select LAST_INSERT_ID();
select User_ID, Option_ID
COMMIT;
You can do it this way, put the value into variable then just select it
BEGIN
DECLARE User_ID int
DECLARE Option_ID int
INSERT INTO user (field1,field2) values (value1,value2);
set User_ID = select LAST_INSERT_ID();
INSERT INTO user_option (user_id,field2) values (LAST_INSERT_ID(),value2);
set Option_ID = select LAST_INSERT_ID();
select User_ID, Option_ID
COMMIT;
Hey guys quick question, I currently have an insert statement
$query= "INSERT into new_mail VALUES ('$to1', '0')"; where fields are username, and message_number
Currently what I would do to check if the entry exists, is do a select query then check the number of rows with mysql_num_rows (php). If rows==1 then I get the current message_number and set it equal to
$row['message_number']+1.
Then I update that entry with another query.
Is there an easier way to do all this in just mysql with just one query (check if exists, if not insert, if so update message_number, increase by 1)?
Depending on how your table is structured, you may be able to use the ON DUPLICATE KEY UPDATE (link to the MySQL manual) feature of INSERT:
INSERT into new_mail VALUES ('$to1', '0') ON DUPLICATE KEY UPDATE message_number=message_number+1
Use INSERT...ON DUPLICATE KEY UPDATE. The MySQL manual has an example which does almost exactly what you need:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
To make this work you need to add a UNIQUE index on the column that you use to check for duplicates. There is one important warning though:
In general, you should try to avoid using an ON DUPLICATE KEY clause on tables with multiple unique indexes.
Got a little confused by your question and your table structures but I think you want something like this.
INSERT INTO new_mail (username, message_number)
VALUES ($username, $message_number)
ON DUPLICATE KEY UPDATE message_number=message_number + 1;
This is presuming username is your primary key (more likely something like userid). Hope this helps.
EDIT: The ON DUPLICATE KEY UPDATE answers are better, but you could do this (eludes the select query):
Assuming you're using the mysqli extenson:
$db = //Some construction of mysqli object;
$sql = 'UPDATE tablename SET RowValue = RowValue + 1 WHERE message_number = ?';
$updateStatement = $db->prepare($sql);
$updateStatement->bind_param('i', $message_number);
$message_number = //Set message number;
$updateStatement->execute();
if ($updateStatement->affectedRows == 0) {
$sql = 'INSERT INTO tablename (RowValue, message_number) VALUES (?, ?)';
$insertStatement = $db->prepare($sql);
$insertStatement->bind_param('ii', $rowValue, $messageNumber);
$rowValue = something;
$messageNumber = something;
$insertStatement->execute();
}