I have a simple HTML form and some php variables as follows to submit book details to a MySQL table named Book using submit method. clcode is a auto increment field.
$isbn =$_POST["isbn"];
$bno =$_POST["b_no"];
$bname =$_POST["b_name"];
$qty =$_POST["qty"];
$price =$_POST["price"];
And need to insert records depending on the qty. eg:- If a qty=2,
It needs to execute the insert query twice (Should be inserted 2 same records with auto increment clcodes). If a qty=5,
It needs to execute the insert query 5 times (Should be inserted 5 same records with auto increment clcodes) and so on... I used a stored procedure and the following SQL query to do that.
$query ="CREATE PROCEDURE myproc()
BEGIN
DECLARE i int DEFAULT 0;
DO
INSERT INTO book (isbn, b_no, b_name, qty, price) VALUES ('$isbn', '$bno', '$bname', '$qty', '$price');
SET i = i + 1;
WHILE i < $qty;
END WHILE;
END";
$result = mysql_query($query) or die ( mysql_error());
But it is return a syntax error. I can not uderstand what I am going wrong. Pls. anyone can help me...? Tnx.
Create table
create table book (
id int not null auto_increment,
isbn VARCHAR(20) not null,
b_no VARCHAR(20) not null,
b_name VARCHAR(20) not null,
qty INT not null,
price decimal(8, 2) not null,
primary key(id)
);
Create SP
DELIMITER //
CREATE PROCEDURE proc_book (
IN isbn VARCHAR(20),
IN no VARCHAR(20),
IN name VARCHAR(20),
IN qty INT,
IN price DECIMAL(8,2)
)
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < qty DO
INSERT INTO book (isbn, b_no, b_name, qty, price) VALUES (isbn, no, name, qty, price);
SET i = i + 1;
END WHILE;
END;
DELIMITER ;
Test SP
call proc_book('978-3-16-148410-0', '1', 'name1', 2, 10.00);
Data in table
+----+-------------------+------+--------+-----+-------+
| id | isbn | b_no | b_name | qty | price |
+----+-------------------+------+--------+-----+-------+
| 1 | 978-3-16-148410-0 | 1 | name1 | 2 | 10.00 |
| 2 | 978-3-16-148410-0 | 1 | name1 | 2 | 10.00 |
+----+-------------------+------+--------+-----+-------+
Call SP from PHP
Use mysqli instead of mysql
<?php
// input data should be filterd to prevent SQL injection etc.
$isbn = $_POST["isbn"];
$bno = $_POST["b_no"];
$bname = $_POST["b_name"];
$qty = $_POST["qty"];
$price = $_POST["price"];
//connect to database
$connection = mysqli_connect("hostname", "user", "password", "db", "port");
//run the store proc
$sql = "CALL proc_book('" . $isbn . "', '" . $bno . "', '" . $bname . "', " . $qty . ", " . $price . ")";
$result = mysqli_query($connection, $sql) or die("Query fail: " . mysqli_error());
?>
Reference
CREATE PROCEDURE
Stored Procedures
MySQL WHILE
How to call a MySQL stored procedure from within PHP code?
It doesn't make sense to create a procedure to meet your requirement.
Suppose it worked for first run, but create procedure will show error in next run because procedure is already there.
You just need to run insert query a number of times, or build insert query with multiple values and run once.
Here is what I think you should do.
1.for($i=0;$i< $qty;$i++){
$sql = "INSERT INTO table_name (field1,field2,fieldn) VALUES ('field-val1','field-val2','field-valn')";
$result = mysql_query($sql) or die ( mysql_error());
}
Or approach 2
$sql = "INSERT INTO table_name (field1,field2,fieldn) VALUES";
for($i=0;$i< $qty;$i++){
$sql .= "('val1','val2','valn')";
if($i < ($qty -1 )){
$sql .=",";
}
}
$result = mysql_query($sql) or die ( mysql_error());
You don't want to CREATE PROCEDURE in your query. You just want to INSERT. You should really be just looping in php to execute a prepared statement to perform the insert.
Read the PHP docs on using a mysqli prepared statement.
$count = 0
while($qty >= $count){
//insertion code goes here...
$count++
}
[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
this is what the syntax of while loop
For e.g.:-
CREATE PROCEDURE dowhile()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < $qty DO
INSERT INTO book (isbn, b_no, b_name, qty, price) VALUES ('$isbn', '$bno', '$bname', '$qty', '$price');
SET i = i + 1;
END WHILE;
END;
Try this one.
Modify your sql statement :
$query = "DELIMITER $$
CREATE PROCEDURE myproc()
BEGIN DECLARE i integer DEFAULT 0;
while (i< ".$qty.") do
begin
INSERT INTO book (isbn, b_no, b_name, qty, price) VALUES (".$isbn.", ".$bno.", ".$bname.", ".$qty.", ".$price."); SET i = i + 1; end; end while;
END $$
DELIMITER" ;
For more details visit: http://www.mysqltutorial.org/stored-procedures-loop.aspx
Performance benchmark with and without transaction in SP.
1.) Without transactions.
DELIMITER //
CREATE PROCEDURE proc_book (
IN isbn VARCHAR(20),
IN no VARCHAR(20),
IN name VARCHAR(20),
IN qty INT,
IN price DECIMAL(8,2)
)
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < qty DO
INSERT INTO book (isbn, b_no, b_name, qty, price) VALUES (isbn, no, name, qty, price);
SET i = i + 1;
END WHILE;
END;
DELIMITER ;
Try to add 1000 qty (without transactions)
mysql> call proc_book('978-3-16-148410-0', '1', 'name1', 10000, 10.00);
Query OK, 1 row affected (8 min 43.01 sec)
2.) With transactions.
DELIMITER //
CREATE PROCEDURE proc_book (
IN isbn VARCHAR(20),
IN no VARCHAR(20),
IN name VARCHAR(20),
IN qty INT,
IN price DECIMAL(8,2)
)
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
END;
DECLARE EXIT HANDLER FOR SQLWARNING
BEGIN
ROLLBACK;
END;
START TRANSACTION;
WHILE i < qty DO
INSERT INTO book (isbn, b_no, b_name, qty, price) VALUES (isbn, no, name, qty, price);
SET i = i + 1;
END WHILE;
COMMIT;
END;
DELIMITER ;
Try to add 1000 qty (with transactions)
call proc_book('978-3-16-148410-0', '1', 'name1', 10000, 10.00);
Query OK, 0 rows affected (0.21 sec)
Related
I am learning SQL and I am in situation where I have to INSERT values into database only if it do not exist already.
My tableview structure is like this:
+----------+-----------+-----+-----+
| first_id | second_id | timestamp |
+----------+-----------+-----------+
I Want to insert only if there is not same first_id and second_id e.g if in table there is first_id 1 and second_id 2 and I am adding it again, I do not want to add it anymore. So if the first_id and second_id rows already have values 1 and 2 then do not add but if first_id is 3 and second_id is 1 then I would allow the inserting.
This is my query ATM:
INSERT INTO `testtable`.`ids` (`first_id`, `second_id`) VALUES (:first_id, :second_id)
And like this I tried with NOT EXISTS but it is not working:
NOT EXISTS (SELECT first_id, second_id FROM `testtable`.`ids` WHERE first_id = : first_id AND second_id = : second_id) INSERT INTO `testtable`.`ids` (`first_id `, `second_id `) VALUES (: first_id, : second_id)
The last mentioned query gives me Syntax error but once I even got the integrity violation and it told me to check documentation.
I am executing my queries using PHP ->query(""); function.
I tried to do like IF NOT EXISTS and NOT EXISTS but those didn't work. How should I approach to this?
This is simple. Declare first_id and second_id as composite key. I would prefer not to make any changes in your PHP Code but make your DB structure versatile so that it doesn't accept any duplicate values how-so-ever you are inserting it.
CREATE TABLE `demo` (
`first_id` smallint(6) DEFAULT NULL,
`second_id` smallint(6) DEFAULT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY `first_id` (`first_id`,`second_id`)
)
Now first_id and second_id will never accept duplicate values.
^ table contains values (1,2). Now inserting (1,3).
^the table accepts (1,3). Now inserting (1,2) again.
the insert statement throws an error. Now the table will never accept duplicate values for the key (first_id,second_id).
If the table already exists and you're not creating it from scratch, simply execute:
alter table `table_name` add unique key (first_id, second_id);
This will prevent the duplicate values henceforth.
You may try this if you are using PHP and MySql:
<?php
//Added database connection code here
$first_id = $_POST['first_id '];
$second_id = $_POST['second_id '];
$sql = "select * from ids where first_id = ".$first_id ." and second_id ='".$second_id."'" ;
$result = $mysqli->query($sql);
$row = $result->fetch_row();
if($row[0]) {
$mysqli->close();
} else {
//preapare an insert statement
$stmt = $mysqli->prepare(" INSERT INTO `ids` (first_id, second_id) VALUES (?,?)");
$stmt->bind_param("ii", $first_id, $second_id);
//execute the statement
if( $stmt->execute() ) {
unset($first_id);
unset($second_id);
} else {
echo $mysqli->error;
}
//close statement
$stmt->close();
$mysqli->close();
}
?>
Checking for existence for the first and second ids and additionally declare 2 sql variables for first and second ids and set them as per required.
DECLARE #Exists int; #first_id int; #second_id int;
SET #first_id = 1;
SET #second_id = 2;
SELECT #Exists = COUNT(*) FROM [testtable] where [first_id] = #first_id and [second_id] = #second_id;
Condition to insert if count of matched records is 0:
IF(#Exists = 0)
BEGIN
INSERT INTO [testtable](first_id, second_id)
VALUES(#first_id,#second_id)
END
I am trying to update my db table by checking if my product_number column already exists. I know you can use the INSERT OR UPDATE ON DUPLICATE KEY but the column I am trying to use is not a primary key.
I found the following query on a stack post but I keep getting the error Unrecognized statement type. (near Duplicate) when I try run it using phpMyAdmin.
DECLARE #numrecords INT
SELECT #numrecords = count(*)
FROM users_remark
WHERE product_number = '444'
IF #numrecords > 0 THEN
UPDATE products
SET product_name = 'abc',
product_description = def,
product_detail = '',
product_price = '100',
product_price_canada = '200'
WHERE product_number = '444'
ELSE
INSERT INTO products (product_number, product_name, product_description, product_price)
VALUES (444, abc, def, 100)
END IF
Why is this query not working?
Is there a better way to achieve what I am trying to accomplish?
I created a procedure for you:
DELIMITER $$
DROP PROCEDURE IF EXISTS insert_or_update $$
CREATE PROCEDURE insert_or_update(pProduct_number INT, pProduct_name VARCHAR(200), pProduct_description VARCHAR(200), pProduct_detail VARCHAR(200), pProduct_price FLOAT(15,2), pProduct_price_canada FLOAT(15,2))
BEGIN
DECLARE numrecords INT;
SELECT count(*) INTO numrecords FROM products WHERE product_number = pProduct_number;
IF numrecords > 0 THEN
UPDATE products SET
product_name = pProduct_name,
product_description = pProduct_description,
product_detail = pProduct_detail,
product_price = pProduct_price,
product_price_canada = pProduct_price_canada
WHERE product_number = pProduct_number;
ELSE
INSERT INTO products (product_number, product_name, product_description, product_price)
VALUES (pProduct_number, pProduct_name, pProduct_description, pProduct_price);
END IF;
END $$
DELIMITER ;
To call just:
CALL insert_or_update(444, , 'abc', 'def', '', '100', '444');
I have Mysql stored procedure, that in some cases give a signal error like this:
CREATE DEFINER=`root`#`localhost` PROCEDURE `InsertAction`(IN `EmployerID` INT, IN `StoreFromID` INT, IN `StoreToID` INT, IN `StoreID` INT, IN `ProductID` INT, IN `Quantity` DECIMAL(10,2), IN `DualOperation` TINYINT, IN `inOrOut` TINYINT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
START TRANSACTION;
SELECT #lastActionID;
SELECT #lastTransferID;
SELECT #retval;
SELECT SUM(ad.Quantity) INTO #retVal FROM productin pri JOIN actiondetails ad ON ad.ID=pri.ID;
IF DualOperation = 1
THEN
IF #retVal>Quantity
THEN
INSERT INTO Actions (EmployerID, StorehouseID, `Date`)
VALUES (EmployerID, StoreFromID, CURDATE());
SET #lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
INSERT INTO ProductTransfer (ID, TransferType)
VALUES (#lastActionID, 0);
INSERT INTO ActionDetails (ID,ProductID, Quantity)
VALUES (#lastActionID, ProductID, Quantity);
SET #lastTransferID = (SELECT ID FROM ProductTransfer ORDER BY ID DESC LIMIT 1);
INSERT INTO Actions (EmployerID, StorehouseID, `Date`) VALUES (EmployerID, StoreToID, CURDATE());
SET #lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
INSERT INTO ProductTransfer (ID, TransferType, ParentID) VALUES (#lastActionID, 1, #lastTransferID);
INSERT INTO ActionDetails (ID,ProductID, Quantity)
VALUES (#lastActionID, ProductID, Quantity);
ELSE
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Not enough materials';
END IF;
ELSE
INSERT INTO Actions (EmployerID, StorehouseID, `Date`)
VALUES (EmployerID, StoreID, CURDATE());
SET #lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
INSERT INTO ActionDetails (ID, ProductID, Quantity)
VALUES (#lastActionID, ProductID, Quantity);
IF InOrOut = 0
THEN
INSERT INTO ProductIn (ID, OrganizationID) values (#lastActionID, NULL);
ELSE
IF #retVal>Quantity
THEN
INSERT INTO ProductOut (ID, OrganizationID) values (#lastActionID, NULL);
ELSE
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Not enough materials';
END IF;
END IF;
END IF;
COMMIT;
END
When i run this code through Mysql query everything seems to be working just fine. it gives a signal of "not enough materials" IF #retVal<=Quantity and no records are inserted(works as it should be)...
But when i call this procedure from PHP it simply doesn't give any error. none of rows are inserted but i cant get notification that the oppreration failed... here is php code:
$mysqli->query("CALL `InsertAction`('6', '1', '2', '0', '13', '431243241', '1', '0')");
the $mysqli->sqlstate gives 0000.
how should i understand the procedure was done or got signal?
so what i really want is, if #retVal<=Quantity then give php exception. and this code prints "string" out:
try {
$mysqli->query("CALL `InsertAction`(6, 1, 2, 0, 13, 431243241, 1, 0)");
}
catch (Exception $e){
echo "string";
}
MYSQLI does not throw exceptions you have to do the old fashioned way
$result = $mysqli->query("CALL InsertAction(6, 1, 2, 0, 13, 431243241, 1, 0)");
if ($result === false) {
echo $mysqli->error;
exit;
}
Also the 6th param is a decimal (10,2) not an int the number you are passing does not fit that 10,2 which if I rememebr correctly mean 8 digits before the decimal place and 2 after, so try a number that fits like
$result = $mysqli->query("CALL InsertAction(6, 1, 2, 0, 13, 4312432.41, 1, 0)");
The real problem in the code above is that variables are not Declared. so i changed this Select statements to Declare statements.
BEGIN
DECLARE lastActionID INT unsigned;
DECLARE lastTransferID INT unsigned;
DECLARE retval INT unsigned;
START TRANSACTION;
SELECT SUM(ad.Quantity) INTO retVal FROM productin pri JOIN actiondetails ad ON ad.ID=pri.ID;
IF DualOperation = 1
THEN
IF retVal>Quantity
THEN
INSERT INTO Actions (EmployerID, StorehouseID, `Date`)
VALUES (EmployerID, StoreFromID, CURDATE());
SET lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
INSERT INTO ProductTransfer (ID, TransferType)
VALUES (lastActionID, 0);
INSERT INTO ActionDetails (ID, ProductID, Quantity)
VALUES (lastActionID, ProductID, Quantity);
SET lastTransferID = (SELECT ID FROM ProductTransfer ORDER BY ID DESC LIMIT 1);
INSERT INTO Actions (EmployerID, StorehouseID, `Date`) VALUES (EmployerID, StoreToID, CURDATE());
SET lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
INSERT INTO ProductTransfer (ID, TransferType, ParentID) VALUES (lastActionID, 1, lastTransferID);
INSERT INTO ActionDetails (ID,ProductID, Quantity)
VALUES (lastActionID, ProductID, Quantity);
ELSE
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Not enough materials';
END IF;
ELSE
INSERT INTO Actions (EmployerID, StorehouseID, `Date`)
VALUES (EmployerID, StoreID, CURDATE());
SET #lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
INSERT INTO ActionDetails (ID, ProductID, Quantity)
VALUES (lastActionID, ProductID, Quantity);
IF InOrOut = 0
THEN
INSERT INTO ProductIn (ID, OrganizationID) values (lastActionID, NULL);
ELSE
IF retVal>Quantity
THEN
INSERT INTO ProductOut (ID, OrganizationID) values (lastActionID, NULL);
ELSE
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Not enough materials';
END IF;
END IF;
END IF;
COMMIT;
select true;
END
now i am able to get $mysqli->sqlstate 45000 and check whether there was an error in procedure
Actualy you'll need to make some preparation to catch exceptions from MySql in PHP.
Use:
$driver = new mysqli_driver();
$driver->report_mode = MYSQLI_REPORT_ALL ^ MYSQLI_REPORT_INDEX;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
MySQL trigger to update a field to the value of id
Please I have a table with three fields :
Id (auto increment)
GroupById
Text
And I want when inserting a new row : If I left the field groupById blank, it must get by default the same value of the field Id.
Please have you any Idea ? Thanks in advance.
Edit : My code :
mysql_query("INSERT INTO group SET GroupById = (must get the current Id), Text = 'bla bla bla' ");
How about a trigger:
DELIMITER $$
CREATE TRIGGER trg_yourtable
BEFORE INSERT ON yourtable
FOR EACH ROW
BEGIN
IF NEW.GroupById IS NULL THEN
SET NEW.GroupById = (
SELECT AUTO_INCREMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'yourtable'
);
END IF;
END $$
I'm not sure how safe this is... or what happens when you insert multiple rows from one query, or when two connections attempt to insert at the same time... but it works.
This simple SQL should do what you want:
INSERT INTO myTable (GroupById, Text) VALUES (NULL, 'your text');
SET #lastID = LAST_INSERT_ID();
UPDATE myTable SET GroupById = #lastID WHERE Id = #lastID;
Use a stored procedure
Get the MAX id
Add 1 to it and add insert it into both rows
You get the desired result in a single transaction.
Hope this helps.
Use this function | Tested
Example of use:
function get_current_insert_id($table)
{
$q = "SELECT LAST_INSERT_ID() FROM $table";
return mysql_num_rows(mysql_query($q)) + 1;
}
$txt = "text";
$groupID = '';
if ( empty($groupID) ) { $groupID = get_current_insert_id(test); }
$query = mysql_query("INSERT INTO test VALUES ('', '$groupID', '$txt') ");
if ( $query ) { echo 'Saved using ID:' . $groupID; } else { echo 'Oh noes!' . $query; }
Looks like you might need to run 2 queries:
insert into 'table' ('GroupById', 'Text') VALUES ('{group id}', '{sometext}')
update 'table' set GroupById = id where GroupById = null - it mightbe 0 instead of null depending on what you insert in db.
You can always optimize it through indexes, limits, order.
I have problem in updating mysql table. While the problem seems somewhat strange I'm explaining it below.
I am working on user's profile update in which the data from single form is inserting/updating to two different tables but if i update the whole form information then updating data is successful but if i only update some 2 or 3 fields then updation is fail. I'm using mysql stored procedure for sql update the code is as under...
DELIMITER $$
DROP PROCEDURE IF EXISTS `usp_user_profile_save` $$
CREATE PROCEDURE `usp_user_profile_save`(IN sIntro_para VARCHAR(255), IN sBook VARCHAR(255), IN sProfileNewName VARCHAR(255),
IN iRel VARCHAR(255), IN iBdate VARCHAR(255), IN iSO INT, IN iMerital_status INT, IN iChildren INT, IN iProfession INT,
IN iIncome INT, IN iIncome_unit INT, IN iCountry INT, IN iState INT, IN iCity_or_post_code INT, IN iHeight VARCHAR(255), IN iSp INT, IN iEthnicity INT,
IN iHair_color INT, IN iHair_lenght INT, IN iEye_color INT, IN iSmoker_or_not INT, IN iUserId INT)
BEGIN
DECLARE n,n1,respCode INT;
DECLARE respMsg,dbg VARCHAR(255);
START TRANSACTION;
UPDATE `tbl_user` SET
`introduction` = sIntro_para,
`profile_picture` = sProfileNewName,
`birthdate` = iBdate,
`s_o` = iSO,
`marital_status` = iMerital_status,
`children` = iChildren,
`profession` = iProfession,
`income` = iIncome,
`income_unit` = iIncome_unit,
`my_book` = sBook,
`r_s` = iRel,
`counrty` = iCountry,
`state` = iState,
`city` = iCity_or_post_code,
`modified` = NOW(),
`modified_by` = iUserId
WHERE `id` = iUserId;
SET n = ROW_COUNT();
IF n <= 0 THEN
ROLLBACK;
ELSE
IF EXISTS (SELECT * FROM `tbl_user_physical` WHERE `tbl_user_id` = iUserId) THEN
UPDATE `tbl_user_physical` SET
`tbl_user_id` = iUserId,
`height` = iHeight,
`shape` = iSp,
`ethnicity` = iEthnicity,
`hair_color` = iHair_color,
`hair_length` = iHair_lenght,
`eye_color` = iEye_color,
`smoker_or_non_smoker` = iSmoker_or_not
WHERE `tbl_user_id` = iUserId;
SET n1 = ROW_COUNT();
ELSE
INSERT INTO `tbl_user_physical`(`tbl_user_id`, `height`, `shape`, `ethnicity`, `hair_color`, `hair_length`, `eye_color`, `smoker_or_non_smoker`) VALUES (iUserId, iHeight, iSp, iEthnicity, iHair_color, iHair_lenght, iEye_color, iSmoker_or_not);
SET n1 = LAST_INSERT_ID();
END IF;
IF n1 > 0 THEN
COMMIT;
SELECT 1 AS respCode, 'Registration successfull.' AS respMsg;
ELSE
ROLLBACK;
SELECT 0 AS respCode,'Registration couldn\'t be completed.' AS respMsg, n, n1;
END IF;
END IF;
END $$
DELIMITER;
Though i have googled my question many time with different keywords but i dont find relevant questions as mine, I have written update statement correctly but its not updating because most of the new data which is going to be update is same as old and my senior said me that update only work if there is a new set of data is submitted and used..
so, please help me to solve this problem
thanks in advance..
I lately come to know that UPDATE statement return error if we update same data. So, I've update added new column modified_date and updating this field with NOW() so that at least one column got changed and UPDATE statement returns no error.