very strange duplicate entry error [duplicate] - php

This question already has answers here:
When to use single quotes, double quotes, and backticks in MySQL
(13 answers)
Closed 7 years ago.
I am saving data repeatedly with code. The first time I run it it doesn't complain. The second time it says Duplicate entry '$id' for key 'PRIMARY'. I am echoing $id value and they are different everytime. The table is 5min old and I guess it can't be corrupted. Is my approach wrong?
function insertData($conn,$data){
$id=$data['id'];
$name=$data['name'];
$fp=$data['first_price'];
$sp=$data['second_price'];
echo "$id<br>";
echo "$name<br>";
echo "$fp<br>";
echo "$sp<br>";
$query = 'INSERT INTO names VALUES("$id", "$name", "$fp", "$fp")';
$result = $conn->query($query);
if (!$result){
echo "nothing saved, sorry $conn->error";
}
}
table structure:
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | varchar(15) | NO | PRI | NULL | |
| name | varchar(150) | YES | | NULL | |
| first_price | varchar(10) | YES | MUL | NULL | |
| second_price | varchar(10) | YES | MUL | NULL | |
+--------------+--------------+------+-----+---------+-------+

You're trying to insert the string literals $id etc into the table because you're using single quotes.
Here's an example that would work:
$query = "INSERT INTO names VALUES('$id', '$name', '$fp', '$fp')";
Now generally speaking you shouldn't need to insert a primary key value, just use null and it will auto increment if your table is set up that way. In your case it's not (auto_increment is not listed under "extra" for the primary key). Consider adding it.
I'll assume that the ->query() is from the PDO library, so to avoid SQL injection you should use parameter binding and your adjusted code would look like this:
$query = 'INSERT INTO names VALUES(?, ?, ?, ?)';
$stmt = $conn->prepare($query);
$stmt->execute(array($id, $name, $fp, $fp));
... or if you're using mysqli rather than PDO:
$query = 'INSERT INTO names VALUES(?, ?, ?, ?)';
$stmt = $conn->prepare($query);
$stmt->bind_param('isdd', $id, $name, $fp, $fp);
$stmt->execute();

Your query is literally inserting the string $id as you're using single quotes for your query string. Do this instead:
$query = "INSERT INTO names VALUES('$id', '$name', '$fp', '$fp')";
Just so you know the reasoning behind it, using single quotes for a string makes it so that variables are ignored.

Related

How to insert entirely json object to table

Suppose I have a table like the following:
id| name | family
---+------+---------
1 | iman | marashi
2 | mike | ...
3 | john | ...
4 | |
and I also have an Json object to insert to the table like the following:
{"name ":"will","family":"smith"}
How can I insert together an Json object to a table given that the fields of the table and the keys of the Json object are the same?
Without having to parsing the Json object.
I don't want to use this method:
$name = $data["name"];
$family = $data["family"];
If you're using PDO, you can provide an associative array to fill in the parameters of a query.
$query = $conn->prepare("INSERT INTO yourTable (name, family) VALUES (:name, :family)");
$data = json_decode($json_object, true);
$query->execute($data);
I think that Barmar provided the correct answer if you are running PDO.
For the sake a completeness, you could also do this purely with MySQL, using json_extract() to read directly from the json string given as parameter:
insert into mytable (name, family) values(
json_unquote(json_extract(:js, '$.name')),
json_unquote(json_extract(:js, '$.family'))
);
Demo on DB Fiddle:
create table mytable (
id int auto_increment primary key,
name varchar(50),
family varchar(50)
):
insert into mytable (name, family) values(
json_unquote(json_extract('{"name":"will","family":"smith"}', '$.name')),
json_unquote(json_extract('{"name":"will","family":"smith"}', '$.family'))
);
select * from mytable;
id | name | family
-: | :--- | :-----
1 | will | smith

PDO statement, quotes are stored as?

So, I'm really new to PDO, and I was trying some stuff and practicing it, and happens that I became really confuse about what is happening to my database once I'm trying to insert some special characters with this code below:
<?php
$post_cat = 4;
$post_title = "TESTING";
$post_author = "Test";
$post_image = "test_image.png";
$post_content = "“Luo Changan, I grant you five breaths’ time. Show me whether you’re actually such a ‘person’ as you say, or a dog that would ‘beg to surrender!’”";
$post_tags = "novel, mga, chinese novel";
$ID_post_stat = 2;
$pdo = new PDO("mysql:charset=utf8mb4;hostname=localhost;dbname=cms;", "root", "");
$stmt = $pdo->prepare('INSERT INTO posts (ID_post_category, post_title, post_author, post_image, post_content, post_tags, ID_post_status) VALUES (?, ?, ?, ?, ?, ?, ?)');
$stmt->bindParam(1, $post_cat);
$stmt->bindParam(2, $post_title);
$stmt->bindParam(3, $post_author);
$stmt->bindParam(4, $post_image);
$stmt->bindParam(5, $post_content);
$stmt->bindParam(6, $post_tags);
$stmt->bindParam(7, $ID_post_stat);
$stmt->execute();
/* data stored:
+------------------+------------+-------------+----------------+-----------------------------------------+---------------------------+----------------+
| ID_post_category | post_title | post_author | post_image | post_content | post_tags | ID_post_status |
+------------------+------------+-------------+----------------+-----------------------------------------+---------------------------+----------------+
| 4 | TESTING | Test | test_image.png | ?Luo Changan, I grant you five breaths? | novel, mga, chinese novel | 2 |
| | | | | time. Show me whether you?re actually | | |
| | | | | such a ?person? as you say, or a dog | | |
| | | | | that would ?beg to surrender!?? | | |
+------------------+------------+-------------+----------------+-----------------------------------------+---------------------------+----------------+
*/
?>
I was looking for answers for why this characters (“ ‘ ’ ”) are not being stored on database and are replaced with (?) instead, I had tried to change the table and column to UTF8 as I had read some answers from the community, but it don't seems to make difference, its working fine with (áéíóú) though. Thanks in advance!
as suggested by Madhur Bhaiya, I had tried again to check on it charset, even aplied charset=utf8mb4 to my PDO DSN what helped me alot instead of using utf8_decode or utf8_encode to each string, and it is indeed all set to UTF8 already, so I guess that this kind of characters like curly quotes aren't supported for this charset, then how can I solve this?

using one key to multiple values in php

I'm developing a webaplicattion in php where there will be an area called 'My Products'. This area you can see the products that you listed. Lets say you placed a car to sell. You will have something like:
Model: R8
Color: Yellow
Brand: Audi
Type: Diesel
Price: 90000
CarID: 1
My problem: How can I select the carid so that I have the cardid as the key and the other values (eg. model, color, etc...) as values?
I'm using mysql to store the listings. SQL TABLE:
+---------+------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------------------------------+------+-----+---------+----------------+
| carid | int(11) | NO | MUL | NULL | auto_increment |
| brand | enum('Alfa Romeo','Aston Martin','Audi') | NO | | NULL | |
| color | varchar(20) | NO | | NULL | |
| type | enum('gasoline','diesel','eletric') | YES | | NULL | |
| price | mediumint(8) unsigned | YES | | NULL | |
| mileage | mediumint(8) unsigned | YES | | NULL | |
| model | text | YES | | NULL | |
| year | year(4) | YES | | NULL | |
| user | varchar(30) | YES | | NULL | |
+---------+------------------------------------------+------+-----+---------+----------------+
My pseudo code is something like this:
Fetch ID of the cars that was listed by certain user;
Use that ID as a key;
Get every other options to be the values (diesel, yellow, etc...)
I have tried some codes since array_combine to foreach inside foreach.
This is the code I have ended up so far:
$qry_id = "select carid from cars where user='$login'";
if ($car_id = mysqli_query($link, $qry_id)){
while ($row = mysqli_fetch_assoc($car_id)){
//It will fetch the iD of the user in the DB
$user_id = $row["carid"];
$qry_model = "select model from cars where carid='$user_id'";
if($model_obj = mysqli_query($link, $qry_model)){
while ($row_2 = mysqli_fetch_assoc($model_obj)){
$model = $row_2['model'];
$final_array = array($user_id => $model);
}
}
}
}
I don't know if this is the right approach since it's my first webapp I'm building.
I'm just using the model value in this code for the simplicity sakes.
$q = "SELECT * FROM cars where user=?";
if ($stmt = $pdo->preapre($q)){
$result=[];
$stmt->execute([$login]);
while ($row = $stmt->fetchObject()){
$carId = $row->carid;
unset($row->carid);
$result[$carId]=$row;
}
}
now note that $pdo is object of pdo connecttion to the database not mysqli, you can do the same thing with mysqli but i am not uses to it
also i don't recommend that you use the user name on every column you should instead store the userId as foreign key to the primary key id in the table user
that will save alot more storage make the query faster ( it's easier to look for numbers than string ) and user can change it's name without having to change his name in all other tables ( userid won't be changing of course )
also carid should be unsigned int(10) not int(11) if wondering why 10 see that post MySQL datatype INT(11) whereas UNSIGNED INT(10)?
To avoid SQL injection, use prepared statements. You can use one query to fetch all attributes for the cars:
$qry_id = "select carid, model, price, color from cars where user=?";
$stmt = mysqli_prepare($link , $qry_d) or die("SQL statement error");
// Bind the login parameter to the statement
mysqli_stmt_bind_param($stmt, "s", $login);
mysqli_stmt_execute($stmt);
// bind every column in the SELECT
mysqli_stmt_bind_result($stmt, $user_id, $carid, $model, $price, $color);
while (mysqli_stmt_fetch($stmt)){
$final_array[] = array(
"model" => $model,
"price" => $price,
"color" => $color
);
}
You may do the following
Note this query is not safe and pron to SQL Injection, I would recommend to use prepared statements or PDO
The $carArray variable will finally have the array with carid as key in it
$query = "select * from cars where user='$login'";
$result = mysqli_query($query);
$carArray = array();
while ($row = mysqli_fetch_assoc($result)){
$carArray[$row['carid']] = $row;
}

Php MySQL How to Updated/Insert into a database row

Table_A
+--------+-----------+---------+
| id | name | views |
+--------+-----------++--------+
| num | text | int |
+--------+-----------+---------+
| 1 | Video 1 | 10 |
| NULL | NULL | 0 |
| NULL | NULL | 0 |
| NULL | NULL | 0 |
| NULL | NULL | 0 |
+--------+-----------+---------+
<a href="video.php?id=video1&idtitle=Hello%20Video1">
<a href="video.php?id=video2&idtitle=Hello%20Video2">
<a href="video.php?id=video3&idtitle=Hello%20Video3">
I'm trying to make the script do something like this.
1.User click on link
2.User is on video.php?id=video1
3.Mysql then add a +1 to my id column #1
4.then take the video title from $videoName
5.Mysql take the title inside of $videoname and store it on name column #2
6.Mysql then add +1 to Views everytime ID 1 is view
7.Mysql is now finish with Row 1
8.Now Mysql will repeat that same step if video.php?id=video2 and so on,
How can i make this happen?
$id = $_GET['id'];
$videoName = $_GET['idtitle'];
$pdo = new PDO('mysql:localhost;dbname=videocount', 'root', '');
$userip = $_SERVER["REMOTE_ADDR"];
if($userip){
$pdo->query("UPDATE Table_A SET (`id`, `name`, `views`)
VALUES (NULL,$videoName, views+1)");
}
I also try the code below but still no luck.
if($userip){
$pdo->query("INSERT INTO `videocount`.`Table_A` (`id`, `name`, `views`)
VALUES (NULL, '$videoname', 'views'+1)");
}
UPDATE instead of UPDATED, VALUES instead of VALUE. In addition you have to add a WHERE condition to your query to select record to update.
This is another correct syntax:
$pdo->query( "UPDATE `Table_A` SET `views`=`views`+1 WHERE `id`='$id'" );
Edit:
To update also the video name you can perform this query:
$pdo->query( "UPDATE `Table_A` SET `name`='{$videoName}', `views`=`views`+1 WHERE `id`='$id'" );
On the border, you should bind the variable values to avoid errors with titles special characters.
See more about binding and MySQL UPDATE syntax
I think there is a little confusion about data view logic.
First of all, you need to save all data into database, then list them for user.
When the use click the link to view this video, the column of views need to be updated.

Error in mysqli->prepare with insert statement

I'm trying to figure out why my first prepare statement works just fine but my second one doesn't. The actual INSERT INTO syntax looks correct and works when I substitute numbers and place it in a mysql console, but the prepare statement returns false.
Just to clear away the simple questions; $db_table_prefix == "uc_" and all variables are initialized. Also, the first statement sets $results == 0 (EDIT: this was my mistake, it's really 0, not 1).
global $mysqli,$db_table_prefix;
$stmt = $mysqli->prepare("SELECT COUNT(id) FROM ".$db_table_prefix."attempts WHERE ((exp_m = ?) AND (exp_n = ?) AND (max_base <= ?))");
$stmt->bind_param("iii", $m, $n, $this->max_base);
$stmt->execute();
$stmt->bind_result($results);
$stmt->fetch();
if ($results < 1)
{
$stmt = $mysqli->prepare("INSERT INTO ".$db_table_prefix."attempts (exp_m, exp_n, base_x, max_base) VALUES (?,?,?,?)");
$stmt->bind_param("iiii", $m, $n, $x, $this->max_base);
.....
}
I've included the table structure, just in case that's the issue.
mysql> describe uc_attempts;
+----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------------+------+-----+---------+----------------+
| exp_m | bigint(20) unsigned | NO | | NULL | |
| exp_n | bigint(20) unsigned | NO | | NULL | |
| base_x | bigint(20) unsigned | YES | | NULL | |
| max_base | bigint(20) unsigned | NO | | NULL | |
| id | int(11) | NO | PRI | NULL | auto_increment |
+----------+---------------------+------+-----+---------+----------------+
I'm sure I'm just missing something simple, but after a few days of staring at the code, I needed to ask. Thanks in advance for the help. Please let me know if there is any other information I should include.
You forgot to close the first resource. I believe it can't open a second prepared statement if the first one isn't closed. I think $mysqli->prepare( ... ); will then return false and obviously false->bind_param( ... ); does not exist ;-) causing your Fatal error: Call to a member function bind_param() on a non-object-error.
global $mysqli,$db_table_prefix;
$stmt = $mysqli->prepare("SELECT COUNT(id) FROM ".$db_table_prefix."attempts WHERE ((exp_m = ?) AND (exp_n = ?) AND (max_base <= ?))");
$stmt->bind_param("iii", $m, $n, $this->max_base);
$stmt->execute();
$stmt->bind_result($results);
$stmt->fetch();
$stmt->close(); //<-- this is the problem
if ($results < 1)
{
$stmt = $mysqli->prepare("INSERT INTO ".$db_table_prefix."attempts (exp_m, exp_n, base_x, max_base) VALUES (?,?,?,?)");
$stmt->bind_param("iiii", $m, $n, $x, $this->max_base);
.....
}

Categories