MySQL CREATE produces redundant index - php

When creating a new database table with the following code phpMyAdmin reports a redundant index like explained in this post. Is there a way to avoid this behavior and have only one index produced on table creation? I could remove the second index with ALTER TABLE mytest DROP INDEX id; but maybe there is a more elegant solution?
<?php
$sql = "CREATE TABLE IF NOT EXISTS `mytest` (
`id` SERIAL PRIMARY KEY,
`mytext` TEXT
) CHARSET=utf8";
mysqli_query($mysqli, $sql);
$sql = "SHOW INDEX FROM `mytest`";
if ($res = mysqli_query($mysqli, $sql)) {
while ($ds = mysqli_fetch_array($res)) {
echo "<pre>";
print_r($ds);
echo "</pre>";
}
} else echo mysqli_error($mysqli);
?>

According to the documentation:
SERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.
Hence, your declaration is:
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY
So, you are getting an index for UNIQUE and an index for PRIMARY KEY.
The simple solution is to not use "abbreviations" and be clear about what you want:
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY

Related

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 Duplicate rows

I am trying to insert values into a table in MYSQL, the table has a column which should be unique,so that column always will have different values.
I tried putting UNIQUE for the coloumn but it did not work,
Also tried putting that column as PRIMARY KEY and insert IGNORE INTO command it did not work (http://www.tutorialspoint.com/mysql/mysql-handling-duplicates.htm)
My intention is to put phonenumber column unique so every value in this column is different. if the newly inserting value is not unique it should skip wihout giving error.
My code to Create table:
public function create_member_table($table)
{
$this->sql ="CREATE TABLE IF NOT EXISTS $table ( id BIGINT NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
phonenumber VARCHAR(20) NOT NULL,
country VARCHAR(2) NOT NULL,
profession VARCHAR(5000) NOT NULL,
profilepic VARCHAR(5000) NOT NULL,
smskey VARCHAR(100) NOT NULL,
status INT NOT NULL,
reg_date_time DATETIME NOT NULL,
UNIQUE (id,phonenumber))
PARTITION BY HASH(id)
PARTITIONS 1023;";
$this->tb = mysqli_query($this->ret,$this->sql);
if(!$this->tb){
echo "Table not created<br>";
}
else{
echo "Table created<br>";
}
Insert table:
public function table_member_insert($table,$phonenumber="",$username="",$country="",$profession="",$profilepic="0",$smskey="",$status="") {
$this->sql = "INSERT INTO $table
(username,phonenumber,country,profession,profilepic,smskey,status,reg_date_time)
VALUES
('$username','$phonenumber','$country','$profession','$profilepic','$smskey','$status',now());";
$this->tb = mysqli_query($this->ret,$this->sql);
if(!$this->tb){
echo "values not inserted<br>";
}
else{
echo "values inserted<br>";
} }
The problem is that you defined the combination of id and phonenumber fields as unique. Since your id field is defined as auto_increment, it will be unique on its own, therefore any combination with phonenumber field will also be unique.
You need to define the phonenumber field alone as unique. After that you can use insert ignore to insert a new record with an existing phone number without raisin an error. However, pls note that in case of a match, the unique index will prevent the entire record from being inserted.

php database table creation fails

I use the following gist to make an OOP attempt to create a database connection:
https://gist.github.com/jonashansen229/4534794
It seems to work so far.
But the creation of the database table passed_exams fails.
Edit:
After recent comments and suggestions i updated my code:
require_once 'Database.php'; // the gist 4534794
class DatabaseSchema {
public function createStudents() {
$db = Database::getInstance();
$mysqli = $db->getConnection();
$create_students = 'CREATE TABLE IF NOT EXISTS students (
id INT(6) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
firstname VARCHAR(40) NOT NULL,
lastname VARCHAR(40) NOT NULL,
university VARCHAR(50)
)';
$result = $mysqli->query($create_students);
}
public function createPassedExams() {
$db = Database::getInstance();
$mysqli = $db->getConnection();
$create_passed_exams = 'CREATE TABLE IF NOT EXISTS passed_exams (
id INT(6) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(40) NOT NULL,
student_id INT(6),
FOREIGN KEY (student_id) REFERENCES students(id) ON DELETE CASCADE
)';
$result = $mysqli->query($create_passed_exams);
}
}
$db_student = new DatabaseSchema();
$db_student->createStudents();
$db_student->createPassedExams();
When i look in the mysql console, only table students is created.
Why is table passed_exams missing?
You create the string to check $query_students = 'SELECT ID FROM STUDENTS';
but you never actually run this. Then u check the string if it is Empty, it will never be empty in your code.
What you should do is use the CREATE ... IF NOT EXISTS syntax of mysql, and not what you do here.
First example show the syntax https://dev.mysql.com/doc/refman/5.5/en/create-table.html
The id column on your students table is INT(6) UNSIGNED but the student_id column on the passed_exams table is a signed INT(6). Therefore the FOREIGN KEY (student_id) REFERENCES students(id) ON DELETE CASCADE clause will fail with "Error Code: 1215. Cannot add foreign key constraint".
I advise you to implement some error handling so that you would see this error message rather than blindly continue executing code.

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.

Can't insert values to foreign key attribute in php

These are my tables:
create table sender(
sno varchar(6) not null,
sfname varchar(15) not null,
slname varchar(10) not null,
sphone varchar(10),
saddress varchar(40) not null,
constraint pk_sender primary key(sno)
);
create table courier(
cno varchar(6),
cost double precision not null,
weight double precision not null,
del_stat varchar(20) not null,
no_cour int(10),
sno varchar(6),
constraint fk_courier foreign key(sno)
references sender(sno),constraint pk_courier primary key(cno)
);
And this is my php code:
<?php
session_start();
$_SESSION['x']=$_POST[sno];
$con=mysqli_connect("localhost","root","project123","project");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$sql1="insert into sender(sno,sfname,slname,sphone,saddress) values (concat('SN','$_POST[sno]'),'$_POST[sf]','$_POST[sl]','$_POST[sph]','$_POST[sad]')";
$sql2="insert into courier(cno,cost,weight,del_stat,no_cour) values (concat('CN','$_POST[cno]'),'$_POST[cst]','$_POST[wght]','$_POST[del]','$_POST[num]')";
if(!mysqli_query($con,$sql1) && !mysqli_query($con,$sql2))
{
die('Error: ' . mysqli_error($con));
}
mysqli_close($con);
?>
But I'm getting error
Error: Cannot add or update a child row: a foreign key constraint fails (project.courier, CONSTRAINT fk_courier FOREIGN KEY (sno) REFERENCES sender (sno))
So please tell me how to insert values to foreign key.
It seems that you're not setting the foreign key value on your child table insert. Your courier table have a column sno VARCHAR(6) that references sender.sno VARCHAR(6) right? So you have to provide it value. In order to relate two fields as foreign key, you have to set a valid value for the child column existing on the parent related column.
Anyway, you should run those two queries like this:
$sno = "SN$_POST[sno]";
$cno = "CN$_POST[cno]";
$sql1="insert into sender(sno,sfname,slname,sphone,saddress) values ('$sno','$_POST[sf]','$_POST[sl]','$_POST[sph]','$_POST[sad]')";
if(mysqli_query($con,$sql1))
{
$sql2="insert into courier(cno,cost,weight,del_stat,no_cour, sno) values ('$cno','$_POST[cst]','$_POST[wght]','$_POST[del]','$_POST[num]', '$sno')";
if (mysqli_query($con,$sql2))
{
// Success
}
else
{
die('Error on query 2: ' . mysqli_error($con));
}
}
else
{
die('Error on query 1: ' . mysqli_error($con));
}
You can see here how to get the last inserted id from an auto_increment field. If you're not using an auto_increment field, you have to select it in other way that fits your needs.
I hope this helps.
UPDATE: I have change those variables sno and cno because you can avoid concatenating it inside your query. You can do that that way. I realize that you already have the sno value, so you don't need to query again after it. That code may now work.

Categories