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;
Related
Well, I am getting some values from the main table say MTB and summarising it in some another table say STB using this script. There is no Unique or Primary key so I can't use ON DUPLICATE KEY situation here.
What I want to do is if the node name) fetched from the MTB Already exists in the STB Then I just want to update it and if the node name from MTB does not exist in the STB then I want to insert the data into the table.
I tried using the If case by first selecting the row in the STB using the nodename fetched from the MTB that if the nodename from the MTB is present in STB (i.e Select query IS NOT NULL) then We Update it else We insert it.
However, this fails to work. Kindly suggest that what I have done wrong.
IF (SELECT * FROM `NodesInfo` WHERE `Nodename` = '".$row2['nodeName']."') IS NOT NULL
THEN
UPDATE `NodesInfo` SET `Time Stamp`= '".$row2['timeStamp']."',`Status`= '$status' WHERE `Nodename` = '".$row2['nodeName']."'
ELSE
INSERT INTO `NodesInfo`(`Nodename`, `Category`, `Time Stamp`, `Type`, `Status`) VALUES ('".$row2['nodeName']."','NodeMCUMQTTData','".$row2['timeStamp']."','$type','$status')
END IF
Just look at the following code, it works.
For MYSQL :
$qry = mysqli_query(<set your db connection variable>, "SELECT * FROM `NodesInfo` WHERE nodeName` = '".$row2['nodeName']."' ");
$res = mysqli_num_rows($qry);
if($res > 0)
{
$update_qry = mysqli_query(<set your db connection variable>, "UPDATE `NodesInfo` SET `Time Stamp`= '".$row2['timeStamp']."',`Status`= '$status' WHERE nodeName` = '".$row2['nodeName']."'");
}
else
{
$insert_qry = mysqli_query(<set your db connection variable>, "INSERT INTO `NodesInfo`(`Nodename`, `Category`, `Time Stamp`, `Type`, `Status`) VALUES ('".$row2['nodeName']."','NodeMCUMQTTData','".$row2['timeStamp']."','$type','$status')");
}
IF exists(SELECT * FROM `NodesInfo` WHERE nodeName` = '".$row2['nodeName']."')
THEN
UPDATE `NodesInfo` SET `Time Stamp`= '".$row2['timeStamp']."',`Status`= '$status' WHERE nodeName` = '".$row2['nodeName']."'
ELSE
INSERT INTO `NodesInfo`(`Nodename`, `Category`, `Time Stamp`, `Type`, `Status`) VALUES ('".$row2['nodeName']."','NodeMCUMQTTData','".$row2['timeStamp']."','$type','$status')
END IF
It seems you want to update nodeName if it already exits otherwise inserts a new entry.
To achieve this, you can make your nodeName field unique.
ALTER TABLE `NodesInfo` ADD UNIQUE INDEX `idx_nodeName` (`nodeName`);
Now you can try ON DUPLICATE KEY UPDATE
INSERT INTO `NodesInfo`(`Nodename`, `Category`, `Time Stamp`, `Type`, `Status`) VALUES ('".$row2['nodeName']."',
'NodeMCUMQTTData',
'".$row2['timeStamp']."',
'$type','$status'
)
ON DUPLICATE KEY UPDATE
`Time Stamp`= '".$row2['timeStamp']."',
`Status`= '$status';
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 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)
I am trying to track users sales based on the new transactions that come through. The transactions are assigned through our site and not their desktop application. It is giving me a syntax error, but I can't seem to figure out why.
This is my code:
DROP TRIGGER IF EXISTS AssignTrans;
DELIMITER $$
CREATE TRIGGER `testing_cake3`.`AssignTrans` AFTER INSERT ON `main_1` FOR EACH ROW
BEGIN
SET #t1 = (SELECT team_id FROM team_assignments WHERE team_assignments.misc_id = NEW.CUSTOMER_ID AND team_assignments.type = 1);
SET #t2 = (SELECT team_id FROM team_assignments WHERE team_assignments.misc_id = NEW.GROUP_ID AND team_assignments.type = 0);
IF (#t1) THEN
INSERT INTO team_trans (team_id, trans_id, type, misc_id) VALUES (#t1, NEW.id, 0, 1 );
ELSE IF (#t2) THEN
INSERT INTO team_trans (team_id, trans_id, type, misc_id) VALUES (#t2, NEW.id, 0, 1 );
END IF;
END $$
DELIMITER ;
THe answer is CHANGING THE ELSE IF TO ElSEIF
I have been working on my first webapp and I hit a bit of a wall. I have a table in my db set up as follows:
student_id(student_id, first_name, last_name, bdate, etc...)
I also have several tables for classes set up similarly to this
class_table(id, student_id, quiz_1, quiz_2, etc....)
student_id is how I would like to track everything, from my understanding, this would be a primary key that would become a foreign key on the class tables.
What I would like to do is create an entry for the student on each class table when the php script I am writing creates a new student. This is what my query looks like:
$query = "INSERT INTO student_id(0, '$first_name', '$last_name'.... etc);".
"INSERT INTO class_table(0, LAST_INSERT_ID(), '$quiz_1', $quiz_2'...etc)";
Is this the right way to do this? I keep getting an error from my mysqli_query... so I am guessing this is where the problem is. How would I achieve this?
mysqli_query() (and mysql_query()) will only execute a single query. You would need to perform two calls to mysqli_query() or use mysqli_multi_query(), which will execute multiple queries in one call.
You're missing the VALUES clause:
$query = "INSERT INTO student_id VALUES (0, '$first_name', '$last_name'.... etc);".
"INSERT INTO class_table VALUES (0, LAST_INSERT_ID(), '$quiz_1', '$quiz_2'...etc)";
and you will need to use the mysqli_multi_query() function. See the example at http://www.php.net/manual/en/mysqli.multi-query.php#106126:
if ($mysqli->multi_query($query)) {
$i = 0;
do {
$i++;
} while ($mysqli->next_result());
}
if ($mysqli->errno) {
echo "Batch execution prematurely ended on statement $i.\n";
var_dump($statements[$i], $mysqli->error);
}
You could also create a stored procedure, and call it with all the needed parameters:
CALL insert_student('$first_name', '$last_name', '$quiz_1', $quiz_2', ... etc);
Here's an example:
CREATE PROCEDURE add_student(
IN v_first_name VARCHAR(50),
IN v_last_name VARCHAR(50),
IN v_quiz_1 VARCHAR(255),
IN v_quiz_2 VARCHAR(255)
)
DETERMINISTIC
MODIFIES SQL DATA
proc: BEGIN
START TRANSACTION;
INSERT INTO student_id VALUES (0, v_first_name, v_last_name);
IF ROW_COUNT() <= 0 THEN
ROLLBACK;
SELECT 0 AS result;
LEAVE proc;
END IF;
INSERT INTO class_table VALUES (0, LAST_INSERT_ID(), v_quiz_1, v_quiz_2);
COMMIT;
SELECT 1 AS result;
END;