update then replace dies - php

If there is a row for user_id then I want to update, if not insert (but I was told to use replace). In the table there is id (which is primary key, auto inc) and user_id (index, session relates to). I have a form that when the data is changed it should be changed in the database for that particular user in session, otherwise it is just added for that particular user in session
if (empty($err)) {
$thesis_Name = mysql_real_escape_string($_POST['thesis_Name']);
$abstract = mysql_real_escape_string($_POST['abstract']);
$query="UPDATE thesis SET thesis_Name ='$thesis_Name',
abstract='$abstract' WHERE id='$_SESSION[user_id]'
IF ROW_COUNT()=0
REPLACE INTO thesis (thesis_Name,abstract)VALUES ('$thesis_Name', '$abstract')
";
mysql_query($query) or die();
// query is ok?
if (mysql_query($the_query, $link) ){
// redirect to user profile
header('Location: myaccount.php?id=' . $user_id);
}
With this the page just dies.
EDIT:
`thesis` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`thesis_Name` varchar(200) NOT NULL,
`abstract` varchar(200) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`)
)
Thanks so much

You don't need to do the UPDATE first - REPLACE handles all of this for you. From the MySQL manual:
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”.
Therefore, so long as id is a unique key in your thesis table, the only SQL you need is:
REPLACE INTO thesis (id, thesis_Name, abstract)
VALUES ('$_SESSION[userid]', '$thesis_name', '$abstract');

There are a few things in your code that pose problem. First you don't have to do an insert and a replace in the same query : replace will insert if there is no row to replace (besides, I'm not even sure the sql syntax you're using is correct)...
Then you do a mysql_query($query) or die() which is probably where your code dies (maybe due to the fact that the sql syntax you used could be incorrect).
Right after that, you do a mysql_query again, which would reexecute the query a second time. Anyway, if your query didn't work, your code would have died on the previous line...
What you could do would be
$query = "REPLACE INTO blablabla";
if (!mysql_query($query))
echo "the query failed";
else header ("location:blabla");
but your query should mention for which user_id you want to update like this
REPLACE INTO thesis (id, thesis_Name, abstract)
VALUES ('{$_SESSION[userid]}', '$thesis_name', '$abstract');

INSERT
INTO thesis (id, abstract, thesis)
VALUES ('$_SESSION[user_id]', '$abstract', '$thesis_Name')
ON DUPLICATE KEY
UPDATE
abstract = VALUES(abstract),
thesis_Name = VALUES(thesis_Name)

You can do it with prepared statements.You can see an example sql ;
DROP PROCEDURE IF EXISTS `UPDATETHESIS`
|
CREATE PROCEDURE `UPDATETHESIS` (IN _id VARCHAR(50), IN _thesis_name VARCHAR(50), IN _abstract VARCHAR(50))
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY INVOKER
IF EXISTS (SELECT * FROM thesis WHERE id = _id)
BEGIN
UPDATE thesis SET thesis_Name = _thesis_name,
abstract = _abstract WHERE id = _id
END
ELSE
BEGIN
INSERT INTO thesis (thesis_Name,abstract) VALUES (_thesis_name, _abstract)
END
You can call this like CALL UPDATETHESIS(userid, thesis_name, abstratc);

Related

Foreign Key Failure in MySQL

I have created a database composed of three tables. This is my query in creating my tables with Foreign Key.
CREATE TABLE reporter
(
reporterid INT NOT NULL AUTO_INCREMENT,
firstname VARCHAR(1000) NOT NULL,
lastname VARCHAR(100) NOT NULL,
PRIMARY KEY (reporterid)
);
CREATE TABLE flood
(
floodid INT NOT NULL AUTO_INCREMENT,
address VARCHAR(500) NOT NULL,
description VARCHAR(1000) NOT NULL,
dateofflood DATE NOT NULL,
timeofflood INT NOT NULL,
PRIMARY KEY (floodid)
);
CREATE TABLE reports
(
reportid INT NOT NULL AUTO_INCREMENT,
timereport NODATATYPE NOT NULL,
datereport DATE NOT NULL,
rid INT NOT NULL,
fid INT NOT NULL,
PRIMARY KEY (reportid),
FOREIGN KEY (rid) REFERENCES reporter(reporterid),
FOREIGN KEY (fid) REFERENCES flood(floodid)
);
I created a system in order for me to add records/row on my database through PHP. This is my code:
<?php
mysql_connect("localhost", "root", "") or die("Connection Failed");
mysql_select_db("flooddatabase")or die("Connection Failed");
$description = $_POST['description'];
$address = $_POST['address']; // Make sure to clean the
$dateofflood=$_POST['dateofflood'];
$timeofflood=$_POST['timeofflood'];
$firstname=$_POST['firstname'];
$lastname=$_POST['lastname'];
$dateofreport=$_POST['dateofreport'];
$timeofreport=$_POST['timeofreport'];
$query = "INSERT into flood(address,description,dateofflood,timeofflood) values ('$address','$description','$dateofflood','$timeofflood')";
$query2 = "INSERT into reporter(firstname,lastname) values ('$firstname','$lastname')";
$query3 = "INSERT into reports(dateofreport,timeofreport) values ('$dateofreport','$timeofreport')";
if(mysql_query($query))
if(mysql_query($query2))
if(mysql_query($query3))
{
echo "";
} else
{
echo "fail";
}
?>
The result that I am getting is fine. It's just that, in my REPORTS table, there is no foreign key that is being generated. For example I input something on my reporter table and flood table, the foreign key 'rid' and 'fid' has no values that references to both tables. Need help thank you.
Get the just inserted Primary key value from flood table insert
query. And store it to a variable say $f_id;
Get the just inserted primary key value from reporter table insert
query and store it to a variable say $r_id;
Now Make your last insert statement like below:
"INSERT into reports(dateofreport,timeofreport,rid,fid) values ('$dateofreport','$timeofreport',$r_id,$f_id)";
I am not giving you a direct copy paste solution.
If you need to know how to get the last inserted id by executing an insert query then look at this link
there is no foreign key that is being generated
I'm not entirely sure what you even mean by that. Foreign keys aren't "generated". Primary keys can be, which you do:
reporterid INT NOT NULL AUTO_INCREMENT
(as well as for your other two tables)
the foreign key 'rid' and 'fid' has no values
Well, look at your query:
INSERT into reports(dateofreport,timeofreport) values ...
Where do you insert values for rid and fid? I'm actually pretty surprised this query works at all, since those columns don't allow NULL values:
rid INT NOT NULL,
fid INT NOT NULL,
(Though your column names also don't line up, so I find it likely that the code you're showing isn't actually the code you're using...) That point aside however, the fact still remains that if you want a value in those fields then you have to put a value in those fields:
INSERT into reports(dateofreport,timeofreport,rid,fid) values ...
After each query, you can get the last generated identifier from mysql_insert_id():
$last_id = mysql_insert_id();
Use that to then populate the values being inserted as foreign keys in subsequent queries.
Also worth noting, the mysql_* libraries are long since deprecated and have been replaced with mysqli_ and other libraries such as PDO. I highly recommend you upgrade to a current technology, since what you're using isn't supported by any vendor.
Additionally, and this is very important, your code is wide open to SQL injection attacks. This basically means that you execute any code your users send you. You should treat user input as values, not as executable code. This is a good place to start reading on the subject, as is this.

MySQLi does not return error code

In my MySQL database I have a table "table1" with unique constraint set on column "name" - I want to prevent duplicate names.
If there's already name 'John' in table this code:
$db=new mysqli(...);
$sql="INSERT INTO table1 SET id=10,name='John'";
if(!$db->query($sql))
{
if($db->errno==1062)
{
throw new InsertNonUniqueException(...);
}
else
{
throw new InsertException(...);
}
}
should throw InsertNonUniqueException() (my own exception). Instead, it throws InsertException().
Execution of query returns false and execution enters the if() loop. Also $db->row_affected is -1 but problem is that $db->errno is always O (it should be 1062)!!! So I can't detect that my insert error was caused by violating unique key constraint on name column!
I don't know why mysqli does not return 1062 code when unique key constraint violation occurs!
I can't leave a comment, thus going to ask you here.
Please provide the result of SHOW CREATE TABLE table1;
I can't reproduce your problem using your code and next table:
CREATE TABLE `table1` (
`name` varchar(11) COLLATE utf8_unicode_ci NOT NULL,
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Am I the only one around here that thinks you have an error in your SQL syntax?.. There is no room for SET in INSERT INTO, because you can only use SET in UPDATE statements (assuming you habe MySQL in version 5.5 or below).
INSERT INTO syntax is like the following (as described in the docs):
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
OR
INSERT INTO tbl_temp2 (fld_id)
SELECT tbl_temp1.fld_order_id
FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
Try it like this:
<?php
$sql="INSERT INTO table1 (id, name) VALUES ('10', 'John')";
...
step 1
make sure that the table has a unique key
SHOW CREATE TABLE table1
expected result
CREATE TABLE `table1` (
`id` INT(11) default NULL,
`name` varchar(11) COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci
if there is UNIQUE KEY name (name) we have a unique key
step 2
try to change your code
$db = new mysqli(...);
// first insert
if( !$db->query("INSERT INTO table1 (id, name) VALUES (10, 'John')") ) {
throw new Exception($db->error);
}
// second insert (for me raise: Duplicate entry 'John' for key 'name')
if( !$db->query("INSERT INTO table1 (id, name) VALUES (11, 'John')") ) {
throw new Exception($db->error);
}
Please, try these two steps
Side note: if you have name and id as duplicates, only the first duplicate encountered will be returned in the message.
The only issue i have with your code is that:
having setup your table and columns.
I setup a unique index on the table. I did .. stuff on a two column table that ensure it works.
You missed the 'new'
keyword when you 'throw exceptions'.
this is the only error with your posted code that i could find.
i.e: throw new Exception('Division by zero.'); // example taken from PHP manual.

Using INSERT WHERE with variables

I am trying to make an SQL query that :
IF the $post_id exists then it updates the records,
IF NOT then then it creates the record
Here is my code
$vote_new_total = $vote_total + $vote;
$vote_count = $vote_count + 1;
$query = " INSERT INTO cute_review_vote (vote_total, vote_count)
VALUES ('$vote_new_total', '$vote_count')
ON DUPLICATE KEY UPDATE vote_total = $vote_new_total, vote_count = $vote_count
WHERE post_id = $post_id";
mysql_query($query) or trigger_error(mysql_error()." in ".$sql);
However, I keep getting the following error:
Notice: 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 'WHERE post_id = 214748364' at line 4 in in C:\xampp\htdocs\xbm-vote\do_vote.php on line 68
Is this an issue with my syntax or am I missing something more obvious than that?
Any help/advice would be greatly appreciated. Thanks.
There is no where with ON DUPLICATE statement. Always check syntax: http://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html
Also, that is not a secure query. Turn that into a prepared statement.
http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
EDIT: Updating answer since OP didn't understand usage of ON DUPLICATE statement:
ON DUPLICATE will consider that you're trying to insert a KEY value.
Consider the example table:
CREATE TABLE `user` (
`email` varchar(50) NOT NULL,
`name` varchar(20) NOT NULL,
`is_active` tinyint(4) NOT NULL,
`datecreated` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`email`)
);
And the query:
INSERT INTO user (email, name, is_active) VALUES ("user#user.com", "User", 1)
ON DUPLICATE KEY UPDATE name = "User Edited", is_active = 0
Since we're setting PRIMARY KEY as email, and the insert statement is inserting a key, then, at the second time you run the query, ON DUPLICATE would run once a email is already on the table, because it is the KEY and you are trying to insert it again, but you defined a ON DUPLICATE KEY ....
If a table runs with a AUTO_INCREMENT column, is most likely you have to SELECT post_id applying some filter with WHERE statement.
Ok, I found my problem.
INSERT INTO cute_review_vote (post_id, vote_total, vote_count)
VALUES ('$post_id', '$vote_new_total', '$vote_count')
ON DUPLICATE KEY UPDATE vote_total = $vote_new_total, vote_count = $vote_count
I realized, thanks to Fabiano, that the WHERE clause is not required.
WHERE post_id = $post_id"
Is simply replaced by defining the database entry within the INSERT INTO command.

How can I avoid creating duplicate rows?

Everything I have searched for and found has yet to work because I am accessing the Table through a php script and differently than everything I see. Anyways,
I am importing Feeds from a website into a mysql table. My table was created like this...
$query2 = <<<EOQ
CREATE TABLE IF NOT EXISTS `Entries` (
`feed_id` int(11) NOT NULL,
`item_title` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_link` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_date` varchar(40) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
EOQ;
$result = $db_obj->query($query2);
I enter the data like so....
foreach($rss->channel->item as $Item){
$query5 = <<<EOQ
INSERT INTO Entries (feed_id, item_title, item_link, item_date)
VALUES ('$get_id','$Item->title','$Item->link','$Item->pubDate')
EOQ;
$result = $db_obj->query($query5);
}
Now, every time Import new feeds from the site I want to make sure I delete any duplicates that might already be there. Everything I have tried, especially DISTINCT, has not worked for me. Does anyone know what type of query I could use to create a temp table, copy over any distinct rows (ENTIRE ROWS, if a title is the same but the date is different I want to keep that), drop the old table, then rename the tamp table to what I want.... or something similar?
Avoid using the duplicate rows in the first place. Make any unique values into keys. When adding new values to your database, use
REPLACE INTO Entries (feed_id, item_title, item_link, item_date)
VALUES ('$get_id','$Item->title','$Item->link','$Item->pubDate')
EOQ;
The duplicates will be automatically overwritten. Replace is handy because it works like an insert when there is no conflict in the keys, but when there is then it will update the record and bump up any auto-incrementing keys.
EDIT
I've been drumming over this for a while. Here's what I came up with.
The problem with making a multi-column key on (feed_id, item_title, item_link, item_date) is that it will exceed the 1000 byte limitation in MySQL for key length. So instead alter your schema like so:
CREATE TABLE IF NOT EXISTS `Entries` (
`hash` varchar(32),
`feed_id` int(11) NOT NULL,
`item_title` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_link` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_date` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (hash)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Now when you store a new value, get a hash of the values together:
$hash = md5($get_id . $Item->title . $Item->link . $Item->pubDate);
And for your insert statements use the following:
REPLACE INTO Entries (hash, feed_id, item_title, item_link, item_date)
VALUES ('$hash', '$get_id','$Item->title','$Item->link','$Item->pubDate')
EOQ;
The hash will be a unique representation of the record in it's entirety, and will be easy to compare in order to avoid duplicates. Now when you attempt to add the same record more than once, it will just replace the existing entry, and your query will not fail. As an alternative, you could continue to use insert, and the query will return an error, which you could handle however you want to.
The fastest and easiest way to delete duplicate records is by issuing a very simple command.
ALTER IGNORE TABLE [TABLENAME] ADD UNIQUE INDEX UNIQUE_INDEX ([FIELDNAME])
What this does is create a unique index on the field that you do not want to have any duplicates. The ignore syntax instructs MySQL to not stop and display an error when it hits a duplicate. This is much easier than dumping and reloading a table. It will also add unique indexes so that no new duplicates will be added. Just change you INSERT to INSERT IGNORE.
This also will work, but is not as elegant:
delete from [tablename] where fieldname in (select a.[fieldname] from
(select [fieldname] from [tablename] group by [fieldname] having count(*) > 1 ) a )
Perhaps do something like this:
$query2 = 'CREATE TABLE entries_new LIKE entries';
$result = $db_obj->query($query2);
$query5 = 'INSERT INTO entries_new (feed_id, item_title, item_link, item_date) VALUES ';
foreach($rss->channel->item as $Item){
$query5 .= '('$get_id','$Item->title','$Item->link','$Item->pubDate'),';
}
$query5 = rtrim($query5, ',');
$result = $db_obj->query($query5);
$query6 = "RENAME TABLE entries TO entries_backup, entries_new TO entries";
$result = $db_object->query($query6);
This will create a table called entries_new like your entries table. Make a single insert of data into entries_new and then rename the old table to entries_backup and the new table to entries.
You might also want to consider wrapping this whole sequence up in a transaction.

Add a unique key to database

I've got a form on my website for users to input their fname, sname, company,phone,email which then gets updated to a database on submit. I also have a field in my database for a unique userID to incase users have same name and company ect. When submitting my form how is it possible to add in this field, a unique number so that it is +1 from the fields taken already. At the minute there are only 3 userIDs so i need the next inputted one to be 4 and so on.
At the moment I have this.
require_once('dbConnect.php');
//taken from a smarty template form.
$addForename = $_POST['forename'];
$addSurname = $_POST['surname'];
$addCompany = $_POST['company'];
$addContact = $_POST['contact'];
$addEmail = $_POST['email'];
public function addUser($addForename,$addSurname,$addCompany,$addContact,$addEmail)
{
$sql = "INSERT INTO `Users` (`Forename`, `Surname`, `ComanyName`, `Phone`, `Email`) VALUES ('".$addForename."','".$addSurname."','".$addCompany."','".$addContact."','".$addEmail."')";
$databaseAccess = new DatabaseConnect();
try
{
$result = $databaseAccess->connect($sql, "add");
}
catch (Exception $e)
{
throw new Exception("Adding User Failed !!!");
}
if ($result)
{
return 1;
}
else{return 0;}
}
thanks
If you are using phpmyadmin there should be a checkbox when youre creating a new column with "A_I" or Auto_Increment.. you have to check that and then it will count your entrys.
Create the row as an auto_increment in the database:
create table someName (ID int primary key auto_increment, col1 int ...);
Then when you are inserting data, either pass it a null, or don't insert that field like this:
insert into someName (col1) values (3);
or
insert into someName (ID, col1) values (null, 3);
You can modify your current table with the following:
ALTER TABLE someName MODIFY COLUMN ID INT NOT NULL AUTO_INCREMENT , ADD PRIMARY KEY (ID);
create the ID:
ALTER TABLE users ADD ID INT UNSIGNED
NOT NULL AUTO_INCREMENT, ADD PRIMARY KEY (ID);
and start the auto-increment where you want
ALTER TABLE tbl AUTO_INCREMENT = 4;
Create a column set it as a primary key and auto increment. You can even write a stored procedure for inserting in the table. That way you don't have to write query every time and not have to worry about escape characters. If you want the particular no to be returned from stored procedure use SCOPE_IDENTITY() in the stored procedure.

Categories