Foreign Key Failure in MySQL - php

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.

Related

Insert value if recieved value is null

so, i'm trying to show a certain value in a table row, if the value recieved by post is null.
So far i've got this as my small database (it's in spanish):
DROP DATABASE IF EXISTS fantasmas;
CREATE DATABASE fantasmas;
USE fantasmas;
CREATE TABLE tipos(
ID tinyint(2) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
TIPO VARCHAR(45) UNIQUE
);
CREATE TABLE datos(
ID tinyint(2) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
NOMBRE VARCHAR(50) NOT NULL,
ARCHIVO VARCHAR(30),
AVISTAMIENTO VARCHAR(50) NOT NULL,
LOCALIDAD VARCHAR(50) NOT NULL,
INFO VARCHAR(200),
FKTIPOS TINYINT(2) UNSIGNED,
FOREIGN KEY (FKTIPOS) REFERENCES tipos(ID)
);
INSERT INTO tipos (TIPO) VALUES('Vapor'), ('Forma Animal'), ('Forma Humanoide'), ('Dios/Semidios'),('No Catalogado');
Those inserted values into "tipos" are then showed in options like this:
<select name="tipos">
<option value="sintipo">---------</option>
<?php
while( $row = mysqli_fetch_assoc($rta)):
$tipo = $row['TIPO'];
echo '<option value="'.$row['ID'].'">'.$tipo.'</option>';
endwhile;
?>
</select>
After, when the form is sent, the inset to the table, looks like this, it assigns null value if someone select the "------" option:
$query = "INSERT INTO datos SET NOMBRE='$nombre', AVISTAMIENTO='$lugar', LOCALIDAD='$localidad', INFO='$info', ARCHIVO='$ruta', FKTIPOS = NULLIF('$tipo','sintipo')";
All the data filled in the form, is then showed in a different row of a table.
What I need now, is that, if someone selects the "------" option, the value shown in screen is "No catalogado"
So far I have not been able to do it.
Can anyone help me?
Before the insert happens you can do a null check on the PHP side. Or... you can just use SQL's built in ISNULL()
You can also use CASE statements in SQL to accomplish this behavior across multiple values.
I know this isn't the most lengthy answer, but it should work.
Is this what your asking for?
$query = "INSERT INTO datos SET NOMBRE='$nombre', AVISTAMIENTO='$lugar', LOCALIDAD='$localidad', INFO='$info', ARCHIVO='$ruta', FKTIPOS = " . ($tipo == 'sintipo' ? 'NULL' : "'$tipo'");
Be aware that you have very dirty code, you don't even filter and escape income values, as I guess. Try to google php mysql escape values.

In a 1-1 relationship, why is my insert inserting two records in two tables?

I'm having trouble, as title says, when I INSERT a record in a table that has got a 1-1 relationship with another.
First things first, the SQL code that generates the tables:
DROP TABLE IF EXISTS Facebook_Info;
DROP TABLE IF EXISTS Conversations;
CREATE TABLE IF NOT EXISTS Conversations(
c_id INT AUTO_INCREMENT NOT NULL,
c_start TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
channel ENUM('desktop', 'facebook'),
u_name VARCHAR(20) DEFAULT NULL,
u_email VARCHAR(50) DEFAULT NULL,
PRIMARY KEY(c_id)
);
CREATE TABLE IF NOT EXISTS Facebook_Info (
c_id INT AUTO_INCREMENT NOT NULL,
f_id INT(12) NOT NULL,
PRIMARY KEY(c_id),
FOREIGN KEY(c_id) REFERENCES Conversations(c_id)
);
I assure you this code works: I tested it. I hope this is the best way to provide a 1-1 relationship between Conversations and Facebook_Info.
In any case, now I can introduce you my nightmare: I'm trying to insert a new record in Conversations via PHP (procedural style).
public function create_new_id_conv($channel = 1) {
$w_ch = '';
if ($channel == 2) {
$w_ch = 'facebook';
} else {
$w_ch = 'desktop';
}
$query = "INSERT INTO Conversations (c_id, c_start, channel) VALUES (NULL, CURRENT_TIMESTAMP,'$w_ch')";
$conn = mysqli_connect("localhost", Wrapper::DB_AGENT, Wrapper::DB_PSW, Wrapper::DB_NAME);
$res = mysqli_query($conn, $query);
$id_conv= mysqli_insert_id($conn);
mysqli_free_result($res);
return $id_conv;
}
The Wrapper:: * variables are all set well, in fact, an INSERT operation is done, but not only one! I'm having this situation after I call this function:
This is the content of Conversations table:
And here's the content of Facebook_Info:
What's happening?
I searched and searched...
Then I started to think about what I'm getting here: 2147483647. What represents this number? What's that? Seems like a big number!
And what if my script and my queries were correct but the mistake is the skeleton of my tables?
I must register a 14 digit integer, that is too large for the INT type.
So using BIGINT to store the f_id field made all correct and working!
Hope my mistake helps someone!

MySQL INSERT IGNORE Adding 1 to Non-Indexed column

I'm building a small report in a PHP while loop.
The query I'm running inside the while() loop is this:
INSERT IGNORE INTO `tbl_reporting` SET datesubmitted = '2015-05-26', submissiontype = 'email', outcome = 0, totalcount = totalcount+1
I'm expecting the totalcount column to increment every time the query is run.
But the number stays at 1.
The UNIQUE index composes the first 3 columns.
Here's the Table Schema:
CREATE TABLE `tbl_reporting` (
`datesubmitted` date NOT NULL,
`submissiontype` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`outcome` tinyint(1) unsigned NOT NULL DEFAULT '0',
`totalcount` mediumint(5) unsigned NOT NULL DEFAULT '0',
UNIQUE KEY `datesubmitted` (`datesubmitted`,`submissiontype`,`outcome`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
When I modify the query into a regular UPDATE statement:
UPDATE `tbl_reporting` SET totalcount = totalcount+1 WHERE datesubmitted = '2015-05-26' AND submissiontype = 'email' AND outcome = 1
...it works.
Does INSERT IGNORE not allow adding numbers? Or is my original query malformed?
I'd like to use the INSERT IGNORE, otherwise I'll have to query for the original record first, then insert, then eventually update.
Think of what you're doing:
INSERT .... totalcount=totalcount+1
To calculate totalcount+1, the DB has to retrieve the current value of totalcount... which doesn't exist yet, because you're CREATING a new record, and there is NO existing data to retrieve the "old" value from.
e.g. you're trying eat your cake before you ever went to the store to buy the ingredients, let alone mix/bake them.

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.

update then replace dies

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);

Categories