I am trying to do an INSERT only if the combination of two columns (a and b) does not exist already. Otherwise, I want to do an UPDATE. The issue of the following code is that it always INSERTs a new row instead of updating when I want to. The reason I think, is because I don't manage do have a kind of two-unique-column in the settings of my table.
Does any one have a solution? Google doesn't seem to be my friend today..
The table:
id : int, primary, AI
a b c and d : int
The code:
$req = $connexion -> prepare("
INSERT INTO position (a,b,c,d)
VALUES (:a,:b,:c,:d)
ON DUPLICATE KEY UPDATE
c=:c;");
$position->bindParam(':a', $a);
$position->bindParam(':b', $b);
$position->bindParam(':c', $c);
$position->bindParam(':d', $d);
$a = $val_a;
$b = $val_b;
$c = $val_c;
$d = $val_d;
$req -> execute();
ON DUPLICATE KEY requires a UNIQUE KEY if you are not matching to the PRIMARY KEY. You can add a UNIQUE KEY by using an ALTER TABLE query
ALTER TABLE position ADD UNIQUE KEY (a,b)
Have you already tried to alter the table to reflect what you need? try this before executing your code.
ALTER TABLE `position` ADD UNIQUE `unique_index`(`a`, `b`);
Related
I searched on stack and try to apply many solutions i found, but not a single is working with this one.
I have a problem with this query because ON DUPLICATE KEY UPDATE is INSERT new results instead of updating existing ones.
INSERT INTO signal_providers_relations (
id,
client_id,
provider_id,
active_sp,
subscription_sp,
created_by,
cr_datetime,
ea_settings_active_sp,
ea_settings_sp,
up_datetime,
sp_risk_allocation,
sp_max_trades )
VALUES (
'',
'".$user_id."',
'".$r['provider_id']."',
'".$r['active_sp']."',
'".$r['subscription_sp']."',
'".$r['created_by']."',
'".$r['cr_datetime']."',
'".$r['ea_settings_active_sp']."',
'".$r['ea_settings_sp']."',
'".$r['up_datetime']."',
'".$r['sp_risk_allocation']."',
'".$r['sp_max_trades']."'
)
ON DUPLICATE KEY
UPDATE
id = '".$r['id']."'
client_id = '".$user_id."',
provider_id = '".$r['provider_id']."',
active_sp = '".$r['active_sp']."',
subscription_sp = '".$r['subscription_sp']."',
created_by = '".$r['created_by']."',
cr_datetime = '".$r['cr_datetime']."',
ea_settings_active_sp = '".$r['ea_settings_active_sp']."',
ea_settings_sp = '".$r['ea_settings_sp']."',
up_datetime = '".$r['up_datetime']."',
sp_risk_allocation = '".$r['sp_risk_allocation']."',
sp_max_trades = '".$r['sp_max_trades']."'
Here is a image with table structure
Assuming this table holds data specific to a single client/provider relationship then your UNIQUE identifier is really a combination of the client_id and provider_id - so you could drop your current client_id and provider_id INDEXES and replace them with a UNIQUE compound index.
ALTER TABLE `signal_providers_relations` DROP INDEX `client_id`;
ALTER TABLE `signal_providers_relations` DROP INDEX `provider_id`;
ALTER TABLE `test`.`signal_providers_relations`
ADD UNIQUE `unique_client_provider` (`client_id`, `provider_id`);
This will give you a specific, unique key which would trigger ON DUPLICATE KEY UPDATE when you attempt to insert data for a specific client/provider combination that already exists, which is what I think you're trying to achieve.
It's quite likely you could, at this point, drop the meaningless id column and change that unique_client_provider key just created to being the PRIMARY instead - but that may have repercussions on other parts of your code.
to avoid this use REPLACE INTO instead of INSERT INTO in your query
I am using ON DUPLICATE UPDATE on my query, some of the result didn't store it. I tried all the possible way, but those still remain the same. here are the database picture.
Those NULL, is the row which didn't store successfully; the result should be 1 instead of NULL.
if($remark){
$query3 = "INSERT INTO `audit_section_remarkrecord` SET remark = '$remark', form_details_subquestion_id = '$form_details_subquestion_id', form_details_section_id = '$form_details_section_id', audit_section_no = '$audit_no' ON DUPLICATE KEY UPDATE
form_details_section_id = '$form_details_section_id' , remark = '$remark'";
$result3 = $db->query($query3);
$query4 = "UPDATE `remarkrecord_update_details` SET form_details_section_id = '$form_details_section_id', userlog = '$user_staff', ipaddress = '$ip' WHERE form_details_subquestion_id = '$form_details_subquestion_id' AND audit_section_no = '$audit_no' ";
$result4 = $db->query($query4);
}else{
}
}
Table Structure
Try changing one of your columns you are inserting value to primary key or add UNIQUE constraint to the column.
ALTER TABLE audit_section_remarkrecord ADD UNIQUE KEY (your column);
As there is currently only a unique key on the Primary Key, an auto-increment, you are going to have difficulty generating a unique key clash on an insert on duplicate key update (IODKU). Therefore, some other unique key needs to be created (even a composite), that will trigger the clash of a unique key and allow IODKU to work as expected.
After looking around on stackoverflow, I'm still having a little trouble understanding the one-to-many relationship in mysql. I have a request coming in from the user (form submission) which will be stored in one table. This is a dynamic form that lets the user add extra fields therefore those will be stored in a separate table. So in short, in my db design, there will be one table for the users with PRIMARY KEY AUTO INCREMENT and there will be another table for the hostnames PER user (multiple fields -array) and using a foreign key that references to the primary key in the user table. Sorry if this is long but trying to make this a good question.
Example:
User Table: (ONE)
1. John Doe, blah, 11-12-15
2. Sally Po, blah, 11-14-15
3. John Doe, blah, 11-15-15
(these are three separate requests)
(numbers are primary key auto incr.)
Host Name Table: (MANY)
1. www.johndoe.com
1. www.johndoe2.com
1. www.johndoe3.com
2. www.sallypo.com
2. www.sallypo2.com
(these numbers (foreign key) should match the primary key for each request)
Code (Leaving out the actual queries + pretty sure I shouln't be using last_id):
$sql = "CREATE TABLE IF NOT EXISTS userTable (
id int AUTO_INCREMENT,
firstName VARCHAR(30) NOT NULL,
date DATE NOT NULL,
PRIMARY KEY (id)
)";
//query
$sql = "CREATE TABLE IF NOT EXISTS hostNamesTable (
id int NOT NULL,
hostName VARCHAR(90) NOT NULL,
FOREIGN KEY (id) REFERENCES userTable(id)
)";
//query
$sql = "INSERT INTO userTable (firstName, date)
VALUES ('$firstName', '$date')";
//query
$last_id = mysqli_insert_id();
for($i = 0; $i < sizeof($hostName); $i++){
$sql = "INSERT INTO hostNamesTable (id, hostName)
VALUES ('$last_id', '$hostName[$i]')";
//query
}
What am I doing wrong? (is this the right way to go about it?)
note: I was trying to get the last_id of the user Table so that I can use it in the hostName table as the foreign key
EDIT: I'm using MySQLi with php
EDIT 2:
After the changes, this is the error I am getting now: Cannot add or update a child row: a foreign key constraint fails (d9832482827984hb28397429.hostNamesTable, CONSTRAINT hostNamesTable_ibfk_1 FOREIGN KEY (id) REFERENCES userTable (id))Error: INSERT INTO hostNamesTable (id, hostName, ) VALUES ('', 'secondhost.net')
--Looks like the $last_id isn't even being recorded?
EDIT 3: Started working. Not sure what it was but I think it was because of some type.
why dont you just add an extra column in the hostNames table which is called "ref_user" and contains the ID of the user you are reffering to? So you can use unique IDs in both tables.
Make a query like:
SELECT * FROM hostNames WHERE ref_user = (SELECT id FROM userTable WHERE <uniqueColumn> = <uniqueIdentifierOfUser>);
But the included request must return only one line from users.
try adding mysqli $link as a parameter in your mysqli_insert_id
$last_id = mysqli_insert_id($link);
i presume you have this somewhere in your code
$link = mysqli_connect("localhost", "mysql_user", "mysql_password", "mysql_db");
if this doesn't work, try using mysql LAST_INSERT_ID() function
$last_id = $mysqli->query("SELECT LAST_INSERT_ID() AS last_id")->fetch_object()->last_id;
create table cmu_patient
( patient_id character varying(13) NOT NULL,
patient_hn character varying(7),
patient_fname character varying(50),
patient_lname character varying(50),
home_id integer,
CONSTRAINT cmu_patient_pkey PRIMARY KEY (patient_id),
CONSTRAINT Fk_home FOREIGN KEY(home_id)
REFERENCES cmu_home(home_id)
);
create table cmu_treatment
( treatment_id serial NOT NULL,
treatment_date date,
treatment_time time without time zone,
treatment_typecome character varying(100),
treatment_detail text,
patient_id character varying(13),
appointment_id character varying(5),
transfer_id character varying(5),
res_users_id integer,
CONSTRAINT cmu_treatment_pkey PRIMARY KEY (treatment_id),
CONSTRAINT Fk_patient FOREIGN KEY(patient_id)
REFERENCES cmu_patient(patient_id),
CONSTRAINT Fk_user_id FOREIGN KEY(res_users_id)
REFERENCES res_users(id)
);
$treatment_date = $GET_[...];
$treatment_time = $GET_[...];
$treatment_typecome = $GET_[...];
$treatment_note = $GET_[...];
$CID = $GET_[...];
this code -------- it's incorrect
INSERT INTO cmu_treatment(treatment_id, treatment_date, treatment_time,
treatment_typecome, treatment_detail, patient_id, appointment_id,transfer_id, res_users_id)
VALUES(NULL,'".$tratment_date."','".$treatment_time."','".
$treatment_typecome."','".$treatment_note."','".$CID."',NULL,NULL,NULL)
WHERE cmu_patient.patient_id = cmu_treatment.patient_id ;
i think that's wrong
i don't know if i want to write insert data into table with where cause i should write sql ?
thank :)
I suspect what you really want is an update, to change existing values in an existing record:
update cmu_treatment
set treatment_date = $treatment_date,
treatment_time = $treatment_time,
treatment_detail = $treatment_typecome,
treatment_note = $treatment_note
where patient_id = $CID;
(I'm leaving out the NULL values on the assumption that those shouldn't really change.)
If you do indeed want a new record, you can do:
INSERT INTO cmu_treatment(treatment_id, treatment_date, treatment_time,
treatment_typecome, treatment_detail, patient_id, appointment_id,
transfer_id, res_users_id
)
select NULL,'".$tratment_date."', '".$treatment_time."','".
$treatment_typecome."','".$treatment_note."','".$CID."', NULL, NULL, NULL;
You can write an INSERT statement populating target table with a SELECT statement. In the SELECT statement you can use WHERE condition.
So instead this query:
INSERT INTO table VALUES (....)
You must write:
INSERT INTO table
SELECT fields
FROM anothertable
WHERE condition
In your case, I think you must use an INSERT without WHERE condition if you want to insert only a row in your treatment table.
Tell me if you want to know further info
EDIT After comment
IMHO your statement must be:
INSERT INTO cmu_treatment
(treatment_id, treatment_date, treatment_time,
treatment_typecome, treatment_detail, patient_id, appointment_id,
transfer_id, res_users_id)
VALUES
(NULL,'".$tratment_date."','".$treatment_time."',
'".$treatment_typecome."','".$treatment_note."','".$CID."',NULL,NULL,NULL)
INSERT INTO `cmu_treatment`(`treatment_id`, `treatment_date`, `treatment_time`,
`treatment_typecome`, `treatment_detail`, `patient_id`, `appointment_id`,`transfer_id`, `res_users_id`)
VALUES(NULL,'".$tratment_date."','".$treatment_time."','".
$treatment_typecome."','".$treatment_note."','".$CID."',NULL,NULL,NULL)
WHERE `cmu_patient.patient_id` = `cmu_treatment.patient_id` ;
And you don't need (table name).(column).
Is this Inside "" ? If yes then you don't need '".$tratment_date."' you can use only '' so your code will look like this.
INSERT INTO cmu_treatment(treatment_id, treatment_date, treatment_time,
treatment_typecome, treatment_detail, patient_id, appointment_id,transfer_id, res_users_id)
VALUES(NULL,'$tratment_date','$treatment_time','
$treatment_typecome','$treatment_note','$CID',NULL,NULL,NULL)
WHERE `patient_id` = patient_id ;
And finally what is patient_id? Is it variable? If not IT MUST BE. Don't give same names to different things.
This question already has an answer here:
Mysql - Add auto_increment to primary key
(1 answer)
Closed 9 years ago.
I have a form that sends the data it captures in to a database, i have a primary key attached to my table (form_id) which i want to autoincrement everytime a new form is submitted and consequently added into my database table. Currently it is just adding a 0 for the first form submitted then anymore forms i submit after do not show as it gives me a message saying you can not have two rows with the same id as zero, which is correct so i would like to change this?
Below is my php code that submits the data into the database:
public function action_claimincentive() {
$this->template->content = View::factory('crm/uk/claim_incentive_form');
$this->template->content->thanks = false;
$this->template->content->val = '';
$this->template->content->post = '';
if ($this->request->post('form')) {
$post = $this->request->post('form');
$stmt = DB::query(Database::INSERT, 'INSERT INTO `claim_incentive_form_data` (`Claimant Name`, `Claimant Postcode`, `Purchase Order No.`, `Claimant Email Address`, `Storename`, `Storetown`, `Date of Sale`, `Date of Delivery`, `Tempur Acknowledgement No.`, `Tempur Product`)
VALUES (:claimantname, :claimantpostcode, :orderno, :email, :storename, :storetown, :dateofsale, :dateofdelivery, :acknowledgementno, :tempurproduct)');
$stmt->param(':claimantname', $post['claimantname']);
$stmt->param(':claimantpostcode', $post['claimantpostcode']);
$stmt->param(':orderno', $post['orderno']);
$stmt->param(':email', $post['email']);
$stmt->param(':storename', $post['storename']);
$stmt->param(':storetown', $post['storetown']);
$stmt->param(':dateofsale', $post['dateofsale']);
$stmt->param(':dateofdelivery', $post['dateofdelivery']);
$stmt->param(':acknowledgementno', $post['acknowledgementno']);
$stmt->param(':tempurproduct', $post['tempurproduct']);
try {
$stmt->execute();
$this->template->content->post = $post;
$this->template->content->thanks = true;
} catch (Exception $e) {
FB::error($e);
}
}
}
This sounds more like a MySQL issue rather than anything else. Make sure you have your Primary Key setup to auto increment. Try altering the table to add the auto increment feature:
ALTER TABLE [table name] MODIFY COLUMN [column name] [column type] PRIMARY KEY AUTO_INCREMENT;
In the above example. Replace the keys in brackets with their appropriate names. Replace [table name] with the name of your table, [column name] with the name of the column and [column type] with the type of the column (SMALLINT, INT, etc).
For more information, see this answer posted by roman.
For more information on the AUTO_INCREMENT feature, check out the MySQL Development Documentation here.
You need to add AUTO_INCREMENT to the primary key column on the table check this http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
you should be able to alter the table with something like this
ALTER TABLE claim_incentive_form_data CHANGE id id INT(10)AUTO_INCREMENT PRIMARY KEY;
Just make sure you change the id column and the datatype if yours are diffrent from that.
You have to set the auto_increment setting in the table within mysql.
ALTER TABLE `claim_incentive_form_data` MODIFY COLUMN `your_primary_column` int(4) PRIMARY KEY AUTO_INCREMENT
Refs:
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
http://dev.mysql.com/doc/refman/5.0/en/alter-table.html
you have to set form_id as primary key, auto increment and not null.