mysql DB not adding rows with similar elements - php

i have created a DB with 3 columns:
aid, qid and message.
aid is a foreign key which will be commond with another table.
comments is a varchar which stores user comments
its partially working. the problem is aid is not adding duplicate values.
suppose i want to add comments related to specific aid. there are 18 aid's in all. and i want to filter the comments according to aid's. the table is not adding a duplicate aid.
this is the query I am using in php:
$query = "UPDATE answers SET acount = acount + 1 WHERE aid = $vote";
$result = mysql_query($query);
$cadd = "INSERT INTO comments (aid, msg) VALUES ('$vote','$comment')";
mysql_query($cadd);
what am i doing wrong. i am attaching a screenshot of the DB structure.
caution: extreme n00b.

It looks like aid is your primary key, which should be unique.

Show table comments. I would guess the PK there is aid.
b.t.w your code is vulnerable to sql injection (unless this is only for the sake of debugging).

Related

Check that data in a SQL table already exists

I want to log what a user enters into a PHP form, and make sure they are not entering data that already exists in a database table.
I have the code already that enters the data into the table from user input, but I'm not sure how to check for duplicates. For example I want to check that there is no product under the same name being added again.
This is what I have so far:
$sql = "INSERT INTO user_data (product_name, code, comments)
VALUES ('$_POST[product_name]','$_POST[code]','$_POST[comments]')";
This is terrible SQL coding practice and, as stated before, is vulnerable to SQL Injection Attacks but something along these lines should work.
$sql = "
INSERT INTO user_date
SELECT
product_name = '$_POST[product_name]'
,code = '$_POST[code]'
,comments = '$_POST[comments]'
WHERE
NOT EXISTS(SELECT * FROM user_data WHERE product_name = '$_POST[product_name]') ";
The best way to do this is by adding a uniqueness constraint to your table itself. This way you can prevent duplicate records from being added.
In your case I would go with this:
ALTER TABLE `user_data` ADD UNIQUE (
`product_name`
)
Also, you could check for the record before you add it:
$sql="SELECT count(*) AS number FROM user_data WHERE product_name LIKE '".$_POST['product_name']."'";
If the column "number" 1 (or bigger), you know it already exists. Also when you get 2, or bigger, you will know that you already have duplicate records.

PHP Code for fetching one row in MSSQL in each registration process

Here is my query part of my registration PHP form.
columns account,password,email and age could be inserted by registration page user and they work well but, the column account_id needs to be increased by 1 automatically with each registration process.
Table name is Account not account and column name is account_id.
$query = "INSERT Account( account,password,email,pk_,type_ ) VALUES('$username','$converted_password','$email',1,'$age')";
$query_total = mssql_query("SELECT COUNT(account_id) FROM Account");
$results_check = mssql_query($query_check);
$results_total = mssql_fetch_row($query_total);
$result_total = $results_total['0'];
It gives me a NULL value for the (account_id) column and INSERT fails.
Perform the following query on your database: (Mysql based query!! not Mssql!!)
ALTER TABLE `Account` CHANGE `account_id` `account_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY;
this wil result in an autoincrement.
If this fails you'll probably already own duplicates, you'd have to solve this first. There are many ways for this, though it mostly depends upon connections with other tables.
After that for each insert into account do not include the account_id.
use the mysql query:
select LAST_INSERT_ID();
to retrieve the last inserted id.
within PHP you can use http://nl1.php.net/mysql_insert_id though i'd highly advice you to start looking into http://www.php.net/PDO or http://www.php.net/mysqli with prepared statements.
Because as far as i've understood in the next version of PHP the basic Mysql functions will become deprecated. And prepared statements are better/safer. (If properly used)
Set account_id to auto increment in MySQL and just don't shoot anything to the MySQL database for the field account_id. MySQL will automatically create a new ID.
Read something about auto increment:
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
*edit:
Also change
$query = "INSERT Account( account,password,email,pk_,type_ ) VALUES('$username','$converted_password','$email',1,'$age')";
to
$query = "INSERT INTO Account(account,password,email,pk_,type_) VALUES('$username','$converted_password','$email',1,'$age')";

Incorrect data in MyISAM database due to concurrency

Problem
I have a webpage that does the following (the code is much simplified to show only relevant code.
mysql_query("insert into table1 (field1) values ('value')");
$last_id = mysql_insert_id();
$result = mysql_query("select * from table1 t inner join ... where id = $last_id");
write_a_file_using_result($result);
It happened, that the file was created using a different data set than what I found in the table row.
The only explanation I have is:
call1: page was called 1. time with data set 1.
call1: data set 1 gets inserted for connection 1 but gets not committed to the table.
call2: page was called 2. time with data set 2
call2: data set 2 gets inserted for connection 2 and mysql_insert_id returns the same value
call1: file is generated with date set 1
call2: file cannot be written, because it already exists
Result: The file is generated with data set 1 while the table row contains data row 2.
Config
mysql 5.0.51b
The table:
CREATE TABLE `table1` (
`id` int(11) NOT NULL auto_increment,
(...)
Question
I know that MyISAM does not support transactions. But I really expect that it is impossible to insert two rows and get twice the same id inserted, so that the row can be overwritten.
Is MyISAM unsafe to this point or is there another explanation that I overlook ?
Note
I know the mysql extension for php is outdated, but I did not yet rewrite the application.
Is MyISAM unsafe to this point
No. mysql_insert_id guaranteed to return the right value only.
or is there another explanation that I overlook ?
Most likely. Check your code.
Haven't heard about id issues in MyISAM.
You can try to set link identifier when calling last_insert_id, for example
$link = mysql_connect(...);
mysql_query("insert into table1 (field1) values ('value')",$link);
$last_id = mysql_insert_id($link);
$result = mysql_query("select * from table1 t inner join ... where id = $last_id",$link);
write_a_file_using_result($result);

Updating a many-to-many connector table all at once

Say I have two tables:
articles
categories
There's a many to many table that connects them.
CREATE TABLE cat2art (
article_id INT,
category_id INT
);
For a specific article, I have a 'new list' of category id's, and we need to update the cat2art table with these.
Some categories got removed, some got added and some stayed where they were. What is the most effective way to update this table?
I could naively delete all records with the specified article_id and simply add them again. However, if I were to record a date in that same table that tracks when an article was linked to a category, that information will now be destroyed.
I'm looking for a great pattern that easily solves this issue. This question is specifically for PHP and MySQL, but answers in other languages are also fine provided they are applicable to PHP+MySQL as well.
Other systems support MERGE statement which would do exactly what you want.
However, in MySQL, you would need at least two queries (it cannot delete and insert/update in a single statement):
DELETE
FROM cat2art
WHERE art_id = $art_id
AND cat_id NOT IN ($new_cat_1, $new_cat_2, …);
INSERT
IGNORE
INTO cat2art
VALUES
($art_id, $new_cat_1),
($art_id, $new_cat_2),
…;
You can define (article_id, category_id) as unique key, and when inserting a connection use INSERT IGNORE syntax. That way if this connection already exists it will not be added again, nor will it update the existing record, and the create_date column stays untouched.
example:
INSERT IGNORE INTO cat2art (article_id, category_id, create_date)
VALUES(100,200,NOW());

Database normalization and lazy development

I believe the question have emerged as my irritation of doing twice as much work as I could imagine is necessary.
I accept the idea that I could be lacking experience with both MySQL and PHP to think of a simpler solution.
My issue is that I have several tables (and I'd might be adding more) and of these is a parent table, only containing two fields - an id (int) and a name identifying it.
At this moment, I have seven tables with at least 15 fields in each one. Every table has a field, containing the id which I can link to the parent table.
All of these data isn't required to be filled - you will just have to create that one entry in the parent table. For the other tables, I have separate forms.
Now, these forms are made for updating the data in the fields, which means I have to pull out the data from the table if any data is available.
What I would like to do is when I receive the data from my form, I could just use an UPDATE query in my model. But if the table I want to update doesn't have an entry for that specific id, I need to do an insert.
So, my current pseudo code is like this:
$sql = "SELECT id FROM table_x WHERE parent_id = ".$parent_id;
$res = $mysql_query($sql);
if( mysql_num_rows($res) == 1 )
{
$sql = "UPDATE table_x SET ... WHERE parent_id = ".$parent_id;
}
else
{
$sql = "INSERT INTO table_x VALUES ( ... )";
}
mysql_query($sql);
I have two do this for every table I have - can I do something different or smarter or is this just the way it has to be done? Cause this seems very inefficient to me.
Use
INSERT ... ON DUPLICATE KEY UPDATE Syntax
It will insert if record not found,
otherwise, it will update existing record,
and you can skip the check before insert - details
This assuming relation for each 7 table to the parent table is 1:1
Or use REPLACE instead of INSERT - it's an insert, but will do an DELETE and then INSERT when a unique key (such as the primary key) is violated.
in mysql you can do this:
INSERT INTO table
(
col1,
col2
) VALUES(
'val1',
'val2'
) ON DUPLICATE KEY UPDATE table SET
col2 = 'val2'
take a look at the documentation for more information
mysql_query("UPDATE table table_x ..... WHERE parent_id=".$parent_id);
if (mysql_affected_rows()==0) {
mysql_query("INSERT INTO .....");
}

Categories