I have a PHP-script in which I can register news users.
Of course I want to insert things like username, password etc. (these values come from the user) but on the other side I want to insert his user_id (new user!) into another table.
My SQL
$sql = "
BEGIN;
INSERT INTO users (username, password, auth_lvl, realname, usercolor) VALUES ('$username', '$password', '$auth_lvl', '$realname', '$usercolor');
INSERT INTO users_startmodules (user_id, startmodule, enabled) VALUES ('(SELECT MAX(user_id)+1 FROM users)', 'newsmodule', '1');
COMMIT;
";
How can I solve this problem and is BEGIN; ... COMIT; the right choice when I want to get the query canceled if just one thing didn't work, because I don't want to have just a few entries in the worst case.
I suggest to change the type of user_id in users table to auto_increment with something like this:
alter table users alter column user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
Now, Assuming that you have escaped the user input data:
$query="INSERT INTO users (username, password, auth_lvl, realname, usercolor) VALUES ('$username', '$password', '$auth_lvl', '$realname', '$usercolor');"
and run that:
$mysqli->query($query);
then get the userid with mysql_insert_id() function of MySQL or alternatively in PHP:
$userid=$mysqli->insert_id;
and:
$query="INSERT INTO users_startmodules (user_id, startmodule, enabled) VALUES ('$userid', 'newsmodule', '1');";
$mysqli->query($query);
This is too long for a comment.
To get the id that was just inserted, use last_insert_id(). This function is documented here.
Next, the answer to your question is to start a transaction. I would give you the syntax, but it is better for you to read the documentation on transactions before you start using them.
The key idea is that a transaction groups data modifications together. Either all take place or none do. Along the way, you can use commit or rollback, depending on whether or not you want to keep the changes or keep none of the changes.
Related
I have a MySQL table set out as the following
UID | Thing1 | Thing2 | Date
The UID column has been set as unique and is made from the users ID + the date as an integer. I.E 7620150715
What I'd like to do is check to see if the UID exists, if it does, then update columns thing1 and thing2 with the latest information.
If the UID doesn't exist, then create a new row for all the information.
Currently, what works to enter is
$sql = "INSERT INTO things2 (uid, thing1, thing2, date) VALUES (:uid, :thing1,:thing2,:date)";
But this doesn't work after making UID unique.
I've found that the ON DUPLICATE KEY UPDATE statement seems to be what I'm looking for, but all answers appear to be adding +1 to the input, which is not what I want to do.
Some pseudo syntax for what I'm looking for would go like this
$sql = "INSERT INTO things2 (uid, thing1, thing2, date) VALUES (:uid, :thing1,:thing2,:date ON DUPLICATE KEY UPDATE (thing1, thing2) VALUES (:thing1, :thing2)";
What would be the correct syntax?
Your syntax is a little wrong. If the INSERT fails then you code an UPDATE with the standard UPDATE syntax like so.
$sql = "INSERT INTO things2
(uid, thing1, thing2, `date`)
VALUES (:uid, :thing1,:thing2,:date )
ON DUPLICATE KEY
UPDATE things2 SET thing1 = :thing1, thing2 = :thing2, `date` = :date";
Also date is a reserved word so its best to wrap it in backticks.
The easiest/most clear way needs two steps:
First do an INSERT OR IGNORE of just the (new) UID. Don't bother with the values yet, because you will update anyway. Just make sure that table allows this with proper defaults and not too many constraints:
INSERT OR IGNORE INTO things2 (uid) VALUES (:uid)
Then do an UPDATE ... SET a=b WHERE UID=.. to actually update the records:
UPDATE thing1=:thing1, thing2=:thing2 WHERE UID = :uid
(Not tested, and please check because I am more into C++/sqlite than in MySql/php)
Problem Description
I have two tables in a MySql database which is intended to store form submission info. The first table contains contact info from the form, the second, user source info (i.e. IP address).
I am creating a datetime in PHP like so:
$timestamp = date('Y-m-d H:i:s');
Then, I am inserting into the first table (successfully) the contact form info, along with this datetime.
Now, what I want to do is get the primary key (auto-incrementing integer) from the first table which is associated with this datetime. So, I query the first table with this string: $db_query = "SELECT `unique_id` FROM `leads_contact_info` WHERE `timestamp` = '$timestamp'";
Herein lies my problem: when I query the table from PHP, it always returns '0'. But, if I go into the first table in PHPMyAdmin, copy and paste the datetime value from a given row into the query, then run the query from the PHPMyAdmin interface, it does indeed return the correct value.
Any help would be greatly appreciated as I'm getting to the, "I'm about to throw my computer out the window and me with it," stage of frustration.
Best
NOTE: In the below scripts, I have control structures for error handling/reporting, which I have omitted for the sake of clarity. Suffice it to say, they work and are not the source of the problem.
Original Script
// Create timestamp
$timestamp = date('Y-m-d H:i:s');
// Create query to insert contact info into first table
$db_query = "INSERT INTO `leads_contact_info` (`unique_id`, `timestamp`, `first_name`, `last_name`, `company_name`, `business_type`, `website`, `phone`, `phone_ext`, `email`, `time_of_week`, `time_of_day`, `notes`) VALUES (NULL, '$timestamp', '$first_name', '$last_name', '$company_name', '$business_type', '$website', '$phone', '$phone_ext', '$email', '$time_of_week', '$time_of_day', '$notes')";
// Execute query
$db_query_result = $db_connection->query($db_query);
// Create query to get primary key from last insertion
$db_query = "SELECT `unique_id` FROM `leads_contact_info` WHERE `timestamp` = '$timestamp'";
// Execute query
$db_query_result = $db_connection->query($db_query);
// Create query to insert source info into second table
$db_query = "INSERT INTO `leads_source_info` (`unique_id`, `from_page`, `referrer`, `user_agent`, `ip_address`) VALUES ('$unique_id', '$this_page', '$referrer', '$user_agent', '$ip_address')";
// Execute query
$db_query_result = $db_connection->query($db_query);
Edited Script (following suggestion from #SetSailMedia)
// Create timestamp
$timestamp = date('Y-m-d H:i:s');
// Create query to insert contact info into first table
$db_query = "INSERT INTO `leads_contact_info` (`unique_id`, `timestamp`, `first_name`, `last_name`, `company_name`, `business_type`, `website`, `phone`, `phone_ext`, `email`, `time_of_week`, `time_of_day`, `notes`) VALUES (NULL, '$timestamp', '$first_name', '$last_name', '$company_name', '$business_type', '$website', '$phone', '$phone_ext', '$email', '$time_of_week', '$time_of_day', '$notes')";
// Execute query
$db_query_result = $db_connection->query($db_query);
// Get primary key from last query
$unique_id = mysqli_insert_id();
// Create query to insert source info into second table
$db_query = "INSERT INTO `leads_source_info` (`unique_id`, `from_page`, `referrer`, `user_agent`, `ip_address`) VALUES ('$unique_id', '$this_page', '$referrer', '$user_agent', '$ip_address')";
// Execute query
$db_query_result = $db_connection->query($db_query);
Debugging Attempts
Unquoting '$timestamp' in both insertion and selection queries.
Various date format conversions on the PHP end of things (again, the insertion query is successful).
Added while loop with sleep(1) on selection query (while result from query == 0).
Tried using both $mysqli->insert_id and mysqli_insert_id($db_connection) to retrieve value of unique ID in first table. Both return 1 on first and follow up executions of the script (in other words, data is inserted into the second table with the unique ID of 1, which doesn't match the actual auto-incremented value of the most recent record in the first table).
Workaround (Not A Solution To The Original Problem)
After many attempts, I finally decided to opt for a workaround for this particular problem. That said, I'd like to leave the question open in case someone comes up with an answer or otherwise has the solution. Thanks to all who tried to help, especially #SetSailMedia.
As a workaround, I changed the DATETIME field in the first table to a TIMESTAMP, and set it to default to the current timestamp. Then, I increased the size of the primary key field to, and in PHP, created a custom integer unique ID via $unique_id = time() + rand(1, 999999999). I checked (via a while loop) to make sure that this unique ID did not already exist in the first table, then fired off the insertion query. Finally, I inserted into the second table with the same value as a unique ID.
Again, this is not a solution to the original problem, and I for one am curious to see what the issue is here, but I simply must move on with this project. I do hope someone else finds the information and efforts herein to be useful.
Why aren't you using mysql_insert_id() (or equivalent function in your database abstraction layer)? This returns the primary key after a successful insert.
Looking at your answers in the comments and the code you posted i see where is the problem:
-In the first table you insert the record with a null value in the unique_id field and then you tried to retrieve this unique id but you dont get a result.
-Then you posted this:
At this point, I'm ready to just pop an auto-incrementing unique ID on both tables, but I really would hate to do that. I feel like there is a solution to this problem.
There lies your problem, if you can pass a null in unique_id an the insert is a success but that field isn't autonumeric then that field is not_null and if thats the case it is also not the primary key.
Of course the SELECT fails because theres nothing to return and also the mysqli_insert_id because there are not autonumerics in the first table.
If you dont want or cant use a autonumeric then look at the uniqid function. The second table does not need any modification.
I am totally new to PHP and I'm trying to create a registration page. To register, a user has to create a username, password, email, which are put into a table called users.
They also enter address details which is put into a table called customer_info.
In both tables I have created an auto increment, primary key called 'user_id'.
When the form is completed it fills out and enters the data, but the data is not banded and so there are two user_id, one in users and one in customer_info.
First I create values (from the post) that have been entered and assign them to variables. Then I put the variables into my table using the following query:
$result = mysql_query(
"INSERT INTO `users`(username, password, email) VALUES ('$value1', '$value2','$value3')"
);
and
$result = mysql_query(
"INSERT INTO `customer_info`(firstname, lastname, b_add_num, b_add_road, b_add_town, b_add_pc, p_add_num, p_add_road, p_add_town, p_add_pc) VALUES ('$value4','$value5','$value6','$value7','$value8','$value9','$value10','$value11','$value12','$value13')"
);
How would I set it so that it creates only one user id for both tables (making a connection between the sets of data)?
Is there something missing in my query, that should connect the tables?
Before anything, you should not use mysql_* extension anymore. Go towards PDO or mysqli
Your technique generates two different unique ids. The point is to have only one, so that it can be unique, and link information on that unique id.
The users table is the one with that unique id, user_id, which is your auto_increment column. The customer_info table can also have a info_id unique column, but must contain a user_id column, which will contain the user's user_id, linking the rows together.
It would also be a great moment to add a foreign key to your tables so that integrity of the data won't be compromised.
so after this query:
$result = mysql_query(
"INSERT INTO `users`(username, password, email) VALUES ('$value1', '$value2','$value3')"
);
get the insert id:
$id = mysql_insert_id();
then run your other query with it:
$result = mysql_query(
"INSERT INTO `customer_info`(user_id,firstname, lastname, b_add_num, b_add_road, b_add_town, b_add_pc, p_add_num, p_add_road, p_add_town, p_add_pc) VALUES ('$id','$value4','$value5','$value6','$value7','$value8','$value9','$value10','$value11','$value12','$value13')"
);
I would configure USER_ID as an AUTO_INCREMENT column only in Users table, insert the data into Users table first, then get the ID of the user inserted, using the mysql_insert_id ($connection_id); and use that while inserting data into Customer_Info table. This way, you can leverage the ID generation (sequence) feature of MySQL as well.
I have a MySQL table with an auto-incrementing primary key (UID). The user can bring up a record in this table via a PHP form, where the UID is a $_GET variable. I would like the database to update the chosen record if it exists, but every time the user hits submit, a new record is created. This is what I've tried so far:
//Present the form
$form = $con->prepare("SELECT Name, Date, Time FROM forms WHERE UID = :uid");
$data = array('uid'=>$_GET['uid']);
$form->execute($data);
$row = $form->fetch(PDO::FETCH_ASSOC);
//Write new record to database. If the UID exists, update the record.
INSERT INTO forms (Name, Date, Time) VALUES (:name, :date, :time)
ON DUPLICATE KEY UPDATE Name=VALUES(Name),Date=VALUES(Date),Time=VALUES(Time);
This doesn't work. Do I need another unique key in the table, or am I missing something obvious?
INSERT INTO forms (`Name`, `Date`, `Time`) VALUES (:name, :date, :time)
ON DUPLICATE KEY UPDATE `Name`=:name, `Date`=:date, `Time`=:time;
This should be the query; I removed VALUES() from your code and added backticks and corrected your parameters.
And I recommend you to use backticks around column names so it doesn't get confused with other similar SQL keywords as example.
I have a simple question about MySQL and PHP here. Let's say I have this PHP syntax :
mysql_query("INSERT INTO Persons (FirstName, LastName, Age)
VALUES ('Peter', 'Griffin',35)");
on that Person table, there's a column named ID (Auto Increment). how to get Peter Griffin's ID after INSERT process is done without making another SELECT query?
or is it possible to do INSERT for 2 tables using single query? for example I want to INSERT Peter's address as well on Address table :
mysql_query("INSERT INTO Address (City, State, Zip)
VALUES ('Cupertino', 'California', 35212)");
that's all..
$new_id = mysql_insert_id();
Put that right after your INSERT query and it will give you the id.
I would't recommend trying to do two INSERTs in one, and the mysql_insert_id() method will make it simplest for you and your code.