Update database php - php

mysql_query("UPDATE users SET `test` = '$unicornID' where id='$_SESSION[user_id]' ")
or die(mysql_error());
Now, when user clicks 'add to favorite'-button this line of code updates my database but also deletes all the old data from column test. What command should so that the old data is not deleted?

I think what you may be looking for is an "INSERT" sql query.
It would be something along the lines of;
"INSERT * INTO users WHERE test='$unicornID' and id='$_SESION['user_id']'";
Let me know how it goes. Cheers.

Another tip.
Use PDO with prepared statements:
$pdo = new PDO(sprintf('mysql:host=%s;dbname=%s', HOST, DATABASE), USER, PASSWORD);
And to insert something:
$params = array(':unicornID' => $unicornID, ':id' => $_SESSION['user_id']);
$stmt = $pdo->prepare("INSERT * INTO users WHERE test=:unicornID and id=:id");
$stmt->execute($params);
The old mysql(_query) commands are old and very vulnerable, PDO isn't as vulnerable.
The advantage of prepared statements are mainly that you can't inject via your variables some sql code.
Hope you understood my and my code

"Update" means that the old data row is changed; if you want to keep it, you have to insert a new one. In this case I think that you should copy the row (which may be done using "insert... select...") and then update the newly inserted line.

Related

How to use same query to insert data

I am new at programming.
I am trying to create a simple guestbok.
i have one index page where you can register a firstname, lastname and email.
And if you click on one name you redirect to a new page with id.
How can i now insert text to this ID with the same codeblock using the ID.
My code looks like this.
<?php
require('dbconfig.php');
try {
$conn = new PDO("mysql:host=$servername;dbname=projektone", $username, $password);
//Set PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Insert to database
$sql = "INSERT INTO user (firstname, lastname, email)
VALUE ('".$_POST["first_name"]."','".$_POST["last_name"]."','".$_POST["email"]."')";
$sql = "INSERT INTO user (guestbok)
VALUE ('".$_POST["guestbok"]."')";
$conn->query($sql);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
header('Location: /');
?>
Thanks in advance
/Daniel
Joining up raw bits of text and passing them on to your database to process is not a good idea. It opens up your system to SQL injection. While it's unlikely that someone could compromise your site when only INSERT statements are exposed in this way, it does mean that:
anyone with an apostrophe in their name will break the logic of the request
you are exposing a method by which someone can carry out a stored XSS attack by submitting javascript to your guestbook
Regarding the SQL Injection problem, there are 2 methods to protect your system - one is to transform the data in which a way that it cannot break the SQL string it is added to (e.g. using mysqli_real_escape_string()) but the recommended approach when using PDO to mediate your code's interaction with the DBMS is to use variable binding. Here you compose your SQL command with placeholders for the data and substitute them at run time.
If your ID is generated from a mysql auto insert id, then you can read the value from $conn->lastinsertid
$stmt=$conn->prepare("INSERT INTO user (firstname, lastname, email)
VALUES (:fnm,:lnm,:eml)");
$stmt->execute(array(
':fnm' => $_POST["first_name"],
':lnm' => $_POST["last_name"],
':eml' => $_POST["email"]));
$id=$conn->lastinsertid();
Your next problem is how to communicate this securely to the page where the user submits their guestbook comment (in your example code you try to do both operations in the same page).
Sending it in a round trip to the browser, as a cookie or as form variable means that it could be tampered with. There are esoteric stateless solutions where you can do this but with the data encrypted or cryptographically signed, however the simplest solution is to use sessions - add session_start() at the top of all your pages and any data you want available across requests can be stored in the $_SESSION superglobal.
(there are security issues relating to sessions as well)
When you receive the POST containing the guestbook data, then you should use an UPDATE user SET guestbook=:gstbk WHERE id=:id_from_session (or you could INSERT it into a seperate table with id as a foreign key)
Lastly, when you output the message the person left in your guestbook, make sure you protect the browser from any nasties in there:
print htmlentities($guestbook);
Ok, probably I managed to get what you need. Put the following two lines in your dbconfig.php:
$conn = new PDO("mysql:host=$servername;dbname=projektone", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
and then require it wherever you need a database connection:
file one:
require('dbconfig.php');
$sql = "sql 1";
$conn->query($sql);
then in another file
require('dbconfig.php');
$sql = "sql 2";
$conn->query($sql);

update two table in single query

i have two table in sql the 1st table is for account while the 2nd table is for testimonial . i am trying to update the two tables in single query. The update is successful if the account already have a testimonial but fails to update if the account has no testimonial yet .How can i fix this heres my code for the update ....
if(!$update=mysql_query(
"UPDATE
tblapplicant,
tbltestimonial
SET
tblapplicant.ImagePath='".$name."',
tbltestimonial.pic = '".$name."'
WHERE
tblapplicant.appid=tbltestimonial.appid"
)
)
1) You're working with a database, it defeats the purpose to use the same data being inserted into two different tables.
2) One gentleman also mentioned stop using MySQL... heres some reference code for you. Assuming you're using php.
3) If you want to use a single query to update 2 tables with the same info against recommendation. Use a stored procedure to update them both.
4) At which point are these account's interconnected in this query? I'm somehow intrigued if this system is in beta or testing?
With your "Where" conditions without matching a specific record, this will update every record that has a matching ID. This is highly not recommended until you add further conditions like username = .... or a condition that's specific to someone or a specific set of rows.
**I strongly advise you post the tables you're working with and what results you want achieve for the best advise. **
Can't really give a good consultation with you playing the whole overview close to the chest. Using this plain-Jane without further detail on what you're asking for is at your own risk my friend.
include/dbconnect.php optional recommended update
<?php
if (isset($mysqli)){
unset($mysqli);
}
define("HOST", "yo.ur.ip.addr"); // The host you want to connect to.
define("USER", "myfunctionalaccount"); // The database username.
define("PASSWORD", "superdoopersecurepassword!"); // The database password.
define("DATABASE", "thegoods");
$mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
if ( $mysqli->connect_error ) {
die('Connect Error: ' . $mysqli->connect_error);
}
?>
functions.php <-- shouldn't be called functions if its going to be your form response
<?php
// SHOULD BE SOME MASSIVE LOGIC UP HERE FOR FORM DATA DECISIONING
include_once "include/dbconnect.php";
$name = addslashes($_FILES['image']['name']);
$image = mysql_real_escape_string(addslashes(file_get_contents($_FILES['image']['tmp_name'])));
if ($stmt = $mysqli->prepare("CALL UpdateTestimonials(?,?,?)"){
$stmt->bind_param($name, $image, $userid);
$stmt->execute();
// optional to show affected rows
$stmt->affected_rows
//
// use if you want to return values from DB
// $stmt->bind_result($result);
// $stmt->fetch;
}
$stmt->close
?>
MySQL build a stored procedure - fyi; definer is optional. Definer will allow you to run a query that only elevated privileges can access due to the safety of such a query. You can use create procedure w/o the definer parameter. dT is just an abbreviation for datatype. You would put varchar or int... etc..
use 'database';
DROP procedure if exists 'UpdateTestimonials';
DELIMITER $$
use 'UpdateTestimonials' $$
CREATE DEFINER='user'#'HOSTNAME/LOCALHOST/%' PROCEDURE 'mynewprocedure' (IN varINPUT varchar, IN varIMG blob, IN varAppID int)
BEGIN
UPDATE tblapplicant
SET imagepath = varINPUT,
pic = LOAD_FILE(varIMG)
WHERE appid = varAppID
END $$
DELIMITER;
Use LEFT JOIN:
if (!$update = mysql_query(
"UPDATE
tblapplicant
LEFT JOIN tbltestimonial ON tblapplicant.appid = tbltestimonial.appid
SET
tblapplicant.ImagePath = '" . $name . "',
tbltestimonial.pic = '" . $name . "'"
)
)
Also, if you need some additional filters for tbltestimonial, add them into LEFT JOIN condition
You could try with a transaction. BTW also please use prepared statements to prevent SQL Injection attacks.
<?php
// prefer mysqli over mysql. It is the more modern library.
$db = new mysqli("example.com", "user", "password", "database");
$db->autocommit(false); // begin a new transaction
// prepare statements
$update_applicant =
$db->prepare("UPDATE tblapplicant
SET tblapplicant.ImagePath = ?"));
$update_applicant->bind_param("s", $name));
$update_applicant->execute();
$update_testimonial =
$db->prepare("UPDATE tbltestimonial
SET tbltestimonial.pic = ?"));
$update_testimonial->bind_param("s", $name))
$update_testimonial->execute();
$db->commit(); // finish the whole transaction as successful,
// when everything has succeeded.
?>
Of course that would not create any testimonials, that don't exist. It just updates those, that do. When you want to insert new entries in tbltestimonial, do so explicitly with an INSERT statement inside the transaction.
MySQL does not fully support transactions. The tables have to use a table type, that can handle them, e.g. innodb. When that is the case, the transaction will make sure, that everyone else either sees all changes from the transactions, or none.
In many cases transactions allow you to perform a group of simple steps, that otherwise would need complex single queries or would not be possible without transactions at all.
Alternative Solution
Another approach of course would be an update-trigger. Create a trigger in your database, that fires whenever e.g. tblapplicant is updated and updates tbltestimonial accordingly. Then you don't have to care about that in your application code.

MySQL Tables Not Updating (PDO)

I am trying to have the PHP code update an address in user table.
For starters, using mysqli, and tried both prepared statements as well as simpler queries. Never had much luck with prepared statements ever because I find them confusing, particularly bind_result().
I do use mysql testing at the command itself to make sure it works as it should. Updates as it should so it's not the mysql command itself. I even gave it a shot in phpMyAdmin locally on the server. However, once in PHP, it doesn't update data in the table.
Immediate thought that came to mind was to make sure the 'user' accessing the mysql tables had UPDATE rights, and it does. So it doesn't look like a permission issue. Even when I use the mysql root with all rights and privileges, the table will NOT update.
My original attempt was some thing quite simple:
$query = "UPDATE `UserTable` SET `Address`=\"". $address . "\" WHERE `id`=".$id;
$conn->query($query);
So, I tried prepared statement version of this and had the same effect. No error, but nothing changed in my table.
Today, I decided to go the PDO route.
try {
$dbh = new PDO("mysql:host=$hostname; dbname=DBDatabase", $db_user, $db_pass);
$query = "UPDATE UserTable SET 'Address'='".$address."' WHERE 'id'=".$id;
echo "Query: ". $query;
$count = $dbh->exec($query);
echo $count . " record changed.";
$dbh = null;
}
catch (PDOException $e) {
echo $e->getMessage();
}
I also tried changing other fields (maybe it was just happening to VARCHAR fields like address). So, I tried flipping the Registered flag and no changes register for that either.
You're not using PDO properly. This is how you will want to form your query.
try {
$dbh = new PDO('mysql:host=$hostname; dbname=DBDatabase', $db_user, $db_pass);
$stmt = $dbh->prepare('UPDATE UserTable SET `Address`=:address WHERE `id`=:id');
$stmt->bindParam(':address', $address, PDO::PARAM_STR);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
}
catch (PDOException $e) {
echo $e->getMessage();
}
This is not your direct question, but prepared statements are super easy, they just require a learning curve - which, honestly, from personal experience is no steeper than learning PDO.
Traditional Query Steps:
DB query.
DB result.
Prepared Query:
Send DB query without parameters, to prepare.
Insert parameters.
Connect to results (bind a variable for each return column, in order).
Cycle through results, using variables rather than a $result array.
It is a few extra steps, but take the twenty minutes you need to to conceptualize it and it will all snap together. The advantage to PDO is that it works across different databases and it is great at prepared statements.

mysql views get decreased

I own a image hosting website and I capture image views using php and mysql.
I use the following code to count the views.
include 'mysql.php';
$result = mysql_query("SELECT * FROM DB WHERE ID='$id'");
$row = mysql_fetch_array($result);
$views=$row['views'];
$query = "UPDATE DB SET views=$views+1 WHERE ID='$id'";
$result2 = mysql_query($query);
mysql_close($con);
views is mediumint(9) type field.
I noticed that the views get decreased day by day.can anyone say what is the problem and offer a solution.
Thanks.
You should use this to update instead:
$query = "UPDATE DB SET views=views+1 WHERE ID='$id'";
If a page takes a long time to execute, you can have one query overwrite another. Also using this, you might not need to even run the first query - unless you want other info from it.
The reason you are getting an error is that one script is reading the data and grabbing the value, then updating it - based on the value it is storing - but in the meantime other scripts could be updating the row. You could avoid it by using transactions, but that seems utter overkill for what you are doing.
You need to stop using mysql_* as those functions are deprecated
You don't need to make 2 queries just to increment a field by 1:
$query = "UPDATE DB SET views=views+1 WHERE ID='$id'";
and PDO example:
$db = new PDO('mysql:host=localhost;dbname=mydb;charset=UTF-8', 'username', 'password', array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
$stmt = $db->prepare("UPDATE DB SET views=views+1 WHERE ID=:id");
$stmt->execute(array(':id' => $id));
Read more about prepared statements and PDO

Postgresql: PREPARE TRANSACTION

I've two DB servers db1 and db2.
db1 has a table called tbl_album
db2 has a table called tbl_user_album
CREATE TABLE tbl_album
(
id PRIMARY KEY,
name varchar(128)
...
);
CREATE TABLE tbl_user_album
(
id PRIMARY KEY,
album_id bigint
...
);
Now if a user wants to create an album what my php code needs to do is:
Create a record in db1 and save its id(primary key)
Create a record in db2 using it saved in first statement
Is it possible to keep these two statements in a transaction? I'm ok with a php solution too. I mean I'm fine if there is a solution that needs php code to retain db handles and commit or rollback on those handles.
Any help is much appreciated.
Yes it is possible, but do you really need it?
Think twice before you decide this really must be two separate databases.
You could just keep both connections open and ROLLBACK the first command if the second one fails.
If you'd really need prepared transactions, continue reading.
Regarding your schema - I would use sequence generators and RETURNING clause on database side, just for convenience.
CREATE TABLE tbl_album (
id serial PRIMARY KEY,
name varchar(128) UNIQUE,
...
);
CREATE TABLE tbl_user_album (
id serial PRIMARY KEY,
album_id bigint NOT NULL,
...
);
Now you will need some external glue - distributed transaction coordinator (?) - to make this work properly.
The trick is to use PREPARE TRANSACTION instead of COMMIT. Then after both transactions succeed, use COMMIT PREPARED.
PHP proof-of-concept is below.
WARNING! this code is missing the critical part - that is error control. Any error in $db2 should be caught and ROLLBACK PREPARED should be executed on $db1
If you don't catch errors you will leave $db1 with frozen transactions which is really, really bad.
<?php
$db1 = pg_connect( "dbname=db1" );
$db2 = pg_connect( "dbname=db2" );
$transid = uniqid();
pg_query( $db1, 'BEGIN' );
$result = pg_query( $db1, "INSERT INTO tbl_album(name) VALUES('Absolutely Free') RETURNING id" );
$row = pg_fetch_row($result);
$albumid = $row[0];
pg_query( $db1, "PREPARE TRANSACTION '$transid'" );
if ( pg_query( $db2, "INSERT INTO tbl_user_album(album_id) VALUES($albumid)" ) ) {
pg_query( $db1, "COMMIT PREPARED '$transid'" );
}
else {
pg_query( $db1, "ROLLBACK PREPARED '$transid'" );
}
?>
And again - think before you will use it. What Erwin proposes might be more sensible.
Oh and just one more note... To use this PostgreSQL feature, you need to set max_prepared_transactions config variable to nonzero value.
If you can access db2 from within db1, then you could optimize the process and actually keep it all inside a transaction. Use dblink or SQL MED for that.
If you roll back a transaction on the local server, what has been done via dblink on a remote server will not be rolled back. (That is one way to make changes persistent even if a transaction is rolled back.)
But you can execute code on the remote server that rolls back if not successful, and only execute it, if the operation in the local db has been successful first. If the remote operation fails you can roll back locally, too.
Also, use the RETURNING clause of INSERT to return id from a serial column.
It will be easier with PDO...
The main advantage of PDO is to capture errors (by PHP error line or returning SQL error messages) of each single SQL statment in the transaction.
See pdo.begintransaction, pdo.commit, pdo.rollback and pdo.error-handling.
Example:
$dbh->beginTransaction();
/* Do SQL */
$sth1 = $dbh->exec("CREATE TABLE tbl_album (..)");
$sth2 = $dbh->exec("CREATE TABLE tbl_user_album(..)");
/* Commit the changes */
$dbh->commit();

Categories