INSERT... ON DUPLICATE KEY UPDATE issue - php

I am having a mysql table named company_profile. It may have only one record. So I tried to insert and update data of the table using INSERT.... ON DUPLICATE KEY UPDATE query.
This is how I tried it:
$sql = "INSERT INTO company_profile (
company_name
, tel
, mobile
, fax
, email
) VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
company_name= VALUES(company_name)
, tel = VALUES(tel)
, mobile = VALUES(mobile)
, fax = VALUES(fax)
, email = VALUES(email)";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('sssss', $company_name
, $telephone
, $mobile
, $fax
, $email
);
$stmt->execute();
My problem is when I updating the data, it always inserting a new record into my table.
Can anybody tell me what would be the problem of this?
My table structure looks like this:
CREATE TABLE IF NOT EXISTS company_profile (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
company_name VARCHAR(120) NOT NULL,
tel VARCHAR(20) NOT NULL,
mobile VARCHAR(20) NOT NULL,
fax VARCHAR(20) DEFAULT NULL,
email VARCHAR(60) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

First, it is redundant to define a key as being both unique and primary key. Just define id to be primary key.
Then, you need a unique constraint/index on the columns used for duplication (the two are functionally equivalent for this purpose). I am guessing uniqueness is based on the company name:
create unique index unq_company_profile_company_name on company_profile(company_name);

Related

How to store list of strings in php/sql table

say I have object user that has a name and a list of emails of limitless lenght. Right now I have 3 tables in my database.
CREATE TABLE NAME (
name TINYTEXT primary key not null
)
CREATE TABLE EMAILS (
id int primary key not null,
email varchar(30)
)
CREATE TABLE USERS (
users_name int references NAME(ID),
users_email int references EMAILS(id),
constraint pk_USERS primary key (users_name, users_email)
)
I feel that there is some error in the making of my tables.
And here is how I am trying to insert the name and email into my database.
protected function setUser($name,$email){ $stmt = $this->estabConnect()->prepare("INSERT INTO USERS(users_email, users_name) VALUES (?,?)");
if(!$stmt->execute(array($email, $name))){ $stmt= null;
header('location: ../index.php?error=stmtfailed');
exit();
}
$stmt=null;
The SQL statement fails
I think the problem is with the sql statment
you must ask your self can users share an email address
yes your design is sorrect as you have a n:m relationship ehivh i represente dby the bridge table
no, your design is wrong and you need to show that a user can have any email adresses
The design would wlook like
CREATE TABLE USER(
id BIGint primary key not null,
name TINYTEXT
)
CREATE TABLE EMAILS (
user_idBIGint primary key not null,
email varchar(30)
)
But normally you want only one email adress per users or maybe a second for office, so that you have a 1:! relationship which is only a part of the user table
a more extended version has not an email table but instead a table that is linked to the user(id) and where you can have many adresses with phone and location in short a 1:n relationship
For your question
CREATE TABLE NAME (
ID int primary key not null,
name TINYTEXT not null
);
CREATE TABLE EMAILS (
id int primary key not null,
email varchar(30)
);
CREATE TABLE USERS (
users_name int references NAME(ID),
users_email int references EMAILS(id),
constraint pk_USERS primary key (users_name, users_email)
);
INSERT INTO USERS(users_name,users_email) VALUES (1,1)
SELECT * FROM USERS
users_name | users_email
---------: | ----------:
1 | 1
db<>fiddle here
To get that to work i changed your design, to corresond with your brisge table.
so as long as you don't enter the actual anme and email adress every should work

no entry into parent table but "0" or "blank" insert into FK in child table

Hi guys I am trying to solve one problem with inserting data to Parent - Child tables. Tables below and also ERR diagram show a structure and PK/FK keys. I am inserting data from webform and PHP is used to capture data and pass it to the database.
Fields in mainTable - F_Name, L_Name and Email are just input textfields,
fields in college tables are checkboxes.
Imagine that one teacher can teach at one, two or three colleges where he checks the checkbox for each college/school where he is teaching. But if he teaches only at one college there is when my problem comes. As all of the "college" tables are linked to "Teacher" with PK/FK.
My question is, is there any way how to store auto generated College ID's if for example teacher is teaching only at one college. At the moment with my PHP it fails and I don't know how to fix it.
I have a example of my PHP under the Schema structure. Just a small note that connection to database works properly.
If this or similar was already asked I do appologize.
Thanks for any tips.
-------------------------------------------------------
-- Schema test
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `test` DEFAULT CHARACTER SET latin1 ;
USE `test` ;
-- -----------------------------------------------------
-- Table `test`.`CollegeA`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `test`.`CollegeA` (
`CollegeAID` INT(11) NOT NULL AUTO_INCREMENT,
`SchoolA` VARCHAR(45) NOT NULL,
`SchoolB` VARCHAR(45) NOT NULL,
`SchoolC` VARCHAR(45) NOT NULL,
PRIMARY KEY (`CollegeAID`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `test`.`CollegeB`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `test`.`CollegeB` (
`CollegeBID` INT(11) NOT NULL AUTO_INCREMENT,
`School1` VARCHAR(45) NOT NULL,
`School2` VARCHAR(45) NOT NULL,
`School3` VARCHAR(45) NOT NULL,
PRIMARY KEY (`CollegeBID`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `test`.`CollegeC`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `test`.`CollegeC` (
`CollegeCID` INT(11) NOT NULL AUTO_INCREMENT,
`School11` VARCHAR(45) NOT NULL,
`School22` VARCHAR(45) NOT NULL,
`School33` VARCHAR(45) NOT NULL,
PRIMARY KEY (`CollegeCID`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `test`.`Teacher`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `test`.`Teacher` (
`TeacherId` INT(11) NOT NULL AUTO_INCREMENT,
`F_name` VARCHAR(45) NOT NULL,
`L_name` VARCHAR(45) NOT NULL,
`Email` VARCHAR(45) NOT NULL,
`CollegeAID` INT(11) NOT NULL,
`CollegeBID` INT(11) NOT NULL,
`CollegeCID` INT(11) NOT NULL,
PRIMARY KEY (`MainId`),
INDEX `CollegeAID_idx` (`CollegeAID` ASC),
INDEX `CollegeBID_idx` (`CollegeBID` ASC),
INDEX `CollegeCID_idx` (`CollegeCID` ASC),
CONSTRAINT `CollegeAID`
FOREIGN KEY (`CollegeAID`)
REFERENCES `test`.`CollegeA` (`CollegeAID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `CollegeBID`
FOREIGN KEY (`CollegeBID`)
REFERENCES `test`.`CollegeB` (`CollegeBID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `CollegeCID`
FOREIGN KEY (`CollegeCID`)
REFERENCES `test`.`CollegeC` (`CollegeCID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
PHP example
if(empty($SchoolA) && empty($SchoolB) && empty($SchoolC)){
$CollegeAId = "";
}
else {
$queryCOLLEGEA = "
INSERT INTO CollegeA (SchoolA, SchoolB, SchoolC)
VALUES('$SchoolA','$SchoolB','$SchoolC')";
$result = mysqli_query($con, $queryCOLLEGEA);
$CollegeAId = mysqli_insert_id($con);
};
if(empty($School1) && empty($School2) && empty($School3)){
$CollegeBId = "";
}
else {
$queryCOLLEGEB = "
INSERT INTO CollegeB (School1, School2, School3)
VALUES('$School1','$School2','$School3')";
$result = mysqli_query($con, $queryCOLLEGEB);
$CollegeBId = mysqli_insert_id($con);
};
if(empty($School11) && empty($School22) && empty($School33)){
$CollegeCId = "";
}
else {
$queryCOLLEGEC = "
INSERT INTO CollegeB (School11, School22, School33)
VALUES('$School11','$School22','$School33')";
$result = mysqli_query($con, $queryCOLLEGEC);
$CollegeCId = mysqli_insert_id($con);
};
$queryMain = "
INSERT INTO Teacher (F_Name, L_Name, Email, CollegeAID, CollegeBID, CollegeCID)
VALUES ('$F_Name', '$L_Name', '$Email', '$CollegeAId', '$CollegeBId', '$CollegeCId')";
$result = mysqli_query($con, $queryMain);
You are using NOT NULL column as foreign key. In this case you cannot leave it empty, you must set here correct key from referenced table. You can change table definition to
CREATE TABLE IF NOT EXISTS `test`.`Teacher` (
`TeacherId` INT(11) NOT NULL AUTO_INCREMENT,
`F_name` VARCHAR(45) NOT NULL,
`L_name` VARCHAR(45) NOT NULL,
`Email` VARCHAR(45) NOT NULL,
`CollegeAID` INT(11),
`CollegeBID` INT(11),
`CollegeCID` INT(11),
PRIMARY KEY (`MainId`),
INDEX `CollegeAID_idx` (`CollegeAID` ASC),
INDEX `CollegeBID_idx` (`CollegeBID` ASC),
INDEX `CollegeCID_idx` (`CollegeCID` ASC),
CONSTRAINT `CollegeAID`
FOREIGN KEY (`CollegeAID`)
REFERENCES `test`.`CollegeA` (`CollegeAID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `CollegeBID`
FOREIGN KEY (`CollegeBID`)
REFERENCES `test`.`CollegeB` (`CollegeBID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `CollegeCID`
FOREIGN KEY (`CollegeCID`)
REFERENCES `test`.`CollegeC` (`CollegeCID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
In this table you can insert NULL values into CollegeAID, CollegeBID and CollegeCID. So, if teacher works in college, it will have value in appropriate CollegeID. If no - CollegeID will be NULL.
Also you will ned to change your code. Change you code like this
if(empty($SchoolA) && empty($SchoolB) && empty($SchoolC)){
$CollegeAId = null;
}
for all three colleges. You need null, not empty string.
And another change is needed here
$queryMain = "
INSERT INTO Teacher (F_Name, L_Name, Email, CollegeAID, CollegeBID, CollegeCID)
VALUES ('$F_Name', '$L_Name', '$Email', '$CollegeAId', '$CollegeBId', '$CollegeCId')";
Variable $CollegeAId now contains proper NULL value. But this query will be produced into
INSERT INTO Teacher (F_Name, L_Name, Email, CollegeAID, CollegeBID, CollegeCID)
VALUES ('F_Name', 'L_Name', 'Email', '', 'CollegeBId', 'CollegeCId')
See it? Still empty string instead of NULL! You need to change query string. It must looks like
INSERT INTO Teacher (F_Name, L_Name, Email, CollegeAID, CollegeBID, CollegeCID)
VALUES ('F_Name', 'L_Name', 'Email', NULL, 'CollegeBId', 'CollegeCId')
For example, you can do it this way for college A:
$CollegeAId = isset($CollegeAId) ? "'$CollegeAId'" : 'NULL';
$queryMain = "
INSERT INTO Teacher (F_Name, L_Name, Email, CollegeAID, CollegeBID, CollegeCID)
VALUES ('$F_Name', '$L_Name', '$Email', $CollegeAId, '$CollegeBId', '$CollegeCId')";

MySQL query doesn't work in php and works when run directly

I have a very strange problem with MySQL and PHP.
I have into a function the below query:
Global $Linker;
$query = "INSERT INTO ".$user_type." (id) VALUES (?)";
if($stmt = mysqli_prepare($Linker->DataBase,$query)) {
mysqli_stmt_bind_param($stmt,"i",$max_id);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
} printf("Error: %s.\n", mysqli_stmt_error($stmt));
where
$Linker is the variable that holds the database connection
and
$user_type is the table I want to insert in the database
I get the following error printed
Error: Cannot add or update a child row: a foreign key constraint fails (std10179db/Students, CONSTRAINT fk_Students_Users1 FOREIGN KEY (id) REFERENCES mydb.Users (Table_ID) ON DELETE NO ACTION ON UPDATE NO ACTION).
The problem is that when I run the same query directly in MySQL through command line in the server it works as expected with no errors.
I found a work around using:
$query= "SET FOREIGN_KEY_CHECKS=0";
$stmt = mysqli_prepare($Linker->DataBase,$query);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
before my query in the PHP function and another workaround would be to change my database schema
but I want to know why that is happening?
I have even tried to execute the query without parameters:
$query = "INSERT INTO Students (id) VALUES (3)";
to be exactly the same with the one I put directly into the server with no success.
Any ideas?
edit:
Table USERS
CREATE TABLE `std10179db`.`Users` (
`ID` INT NOT NULL ,
`Username` VARCHAR(45) NOT NULL ,
`Password` VARCHAR(45) NOT NULL ,
`email` VARCHAR(45) NOT NULL ,
`User_Class` VARCHAR(45) NOT NULL ,
`Table_ID` INT NOT NULL ,
PRIMARY KEY (`ID`) ,
UNIQUE INDEX `Username_UNIQUE` (`Username` ASC) ,
UNIQUE INDEX `Password_UNIQUE` (`Password` ASC) ,
UNIQUE INDEX `email_UNIQUE` (`email` ASC) )
ENGINE = InnoDB;
and Table Students
CREATE TABLE `std10179db`.`Students` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`Univ_ID` VARCHAR(45) NULL ,
`Name` VARCHAR(45) NULL ,
`Surname` VARCHAR(45) NULL ,
`Telephone` VARCHAR(45) NULL ,
`Semester` INT NULL ,
`Department_id` INT UNSIGNED NULL ,
PRIMARY KEY (`id`, `Department_id`) ,
UNIQUE INDEX `idStudents_UNIQUE` (`id` ASC) ,
INDEX `fk_Students_Department1` (`Department_id` ASC) ,
CONSTRAINT `fk_Students_Department1`
FOREIGN KEY (`Department_id` )
REFERENCES `mydb`.`Department` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Students_Users1`
FOREIGN KEY (`id` )
REFERENCES `mydb`.`Users` (`Table_ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;

mysql - insert id from parent table

I have table definitions:
create table users(
id int not null auto_increment,
usernaname varchar(50) not null,
pass varchar(50) not null,
primary key(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
create table users_description(
user_id int not null,
description varchar(255),
key(user_id),
foreign key(user_id) references users(id) on delete cascade
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and it is good, works nice.
but when I add a new user I use a next query:
insert into users (username, pass) values('test', 'test');
but how to add a id of user automatically in users_description table?
Something similar to to this:
insert into users_description values(
select id from users where username = 'test',
'user description');
I want to use only two queries, is this possible?
You can use LAST_INSERT_ID() to get the last inserted primary key id (which would be from the users table):
INSERT INTO users_description VALUES
(LAST_INSERT_ID(), 'test', 'user description');
$query = mysql_query("insert form (username, pass) values('test', 'test')");
$id = mysql_insert_id();
gives you the last inserted id in PHP ..
Use LAST_INSERT_ID(). Example here.

Paypal IPN - store data on database, update and delete

I'm using this example to store in the database the info coming from PayPal, my problem is that the database create two records for the same sale, one with the status of 'Pending' and one with the status 'Completed', both for the same sale.
How can I change this part of the code so if there is a sale with the same 'txn_id' I just update the 'payment_status' row OR delete the whole thing before update it with the new info. Note that there is two rows that will be different, 'payment_status' and 'createdtime' .
function updatePayments($data){
global $link;
if(is_array($data)){
$sql = mysql_query("INSERT INTO `payments` (txnid, payment_amount, payment_status, item_name, receiver_email, payer_email, custom, itemid, createdtime) VALUES (
'".$data['txn_id']."' ,
'".$data['payment_amount']."' ,
'".$data['payment_status']."' ,
'".$data['item_name']."' ,
'".$data['receiver_email']."' ,
'".$data['payer_email']."' ,
'".$data['custom']."' ,
'".$data['itemid']."' ,
'".date("Y-m-d H:i:s")."'
)", $link);
return mysql_insert_id($link);
}
}
Database structure
CREATE TABLE IF NOT EXISTS `payments` (
`id` int(6) NOT NULL AUTO_INCREMENT,
`txnid` varchar(20) NOT NULL,
`payment_amount` decimal(7,2) NOT NULL,
`payment_status` varchar(25) NOT NULL,
`item_name` varchar(50) NOT NULL,
`receiver_email` varchar(50) NOT NULL,
`payer_email` varchar(50) NOT NULL,
`custom` varchar(25) NOT NULL,
`itemid` varchar(25) NOT NULL,
`createdtime` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Create a UNIQUE INDEX on txn_id (if one doesn't exist already) and then use either INSERT ... ON DUPLICATE KEY UPDATE or REPLACE in place of your existing INSERT.
UPDATE
In your case, to add the unique index:
ALTER TABLE payments ADD UNIQUE INDEX (txnid);
Then, append to the end of your INSERT statement:
ON DUPLICATE KEY UPDATE payment_status = '".$data['payment_status']"'
If you want to delete the existing record and replace it with your new one, just change the word INSERT to REPLACE instead.

Categories