I want to abort batch sql query transactions if column value is less than or equal to user's input value and alert user.
Here's what happens:
available_qty value is subtracted from user's input qty value and the value is updated in food_menu table.
user's order records are inserted into food_order table.
Here's my query:
foreach($menuData as $item=>$qty)
{
if(empty($qty) || $qty == '0')
continue;
$sqlArray[] = "INSERT INTO food_order
(user_id, item_id, quantity, order_type, updated_on, updated_by, created_by, created_on)
VALUES ($uid, $item, $qty, '$menu_type', NOW(), $uid, $uid, NOW())";
$sqlArray[] = "UPDATE food_menu SET available_qty = IF($qty >= available_qty, available_qty - $qty, available_qty) WHERE item_id = $item AND type = '$menu_type' AND DATE(updated_on) = CURRENT_DATE";
}
return (boolean) $this->db->exec($sqlArray);
if $qty value is greater than available_qty field value, I want to abort the whole series of transactions in $sqlArray[].
Can I do that in the query itself?
I think a much better approach is to check the available quantity with remaining quantity before the start of your insert and update statement. But for the sake of information you can try the following:
Create a before update trigger on food_menu table. In the trigger check the available quantity of it is negative meaning the order quantity is more than available quantity then use the SIGNAL statement to raise an error which you will have to catch in your code and do the rollback and show appropriate message to the user.
Related
Now i have this sql update code:
$sql = "UPDATE products SET stock = stock - '$quantity' WHERE product_id = '$id'";
I have some problem with this. It works, but if the stock value in the table is smaller, than the quantity in the webshop cart, it will update the stock field to a minus value.
I know, that there is a function in mysql for this, that will only update it to 0, and not to minus. Whats that function, or how should i do this?
You can use case
UPDATE products SET stock
= case
when stock > '$quantity' then stock - '$quantity'
else 0 end
WHERE product_id = '$id';
Be sure that your variables $quantity and $id are checked to be sure that they are numeric to avoid SQL injection.
You can use the MySQL IF Statement for this. First check if stock - quantity is greater than 0 then return the value, else return 0.
UPDATE products
SET stock = IF(stock - '$quantity' > 0, stock - '$quantity', 0)
WHERE product_id = '$id';
You could use the GREATEST function to get the largest value of your existing calculation or 0, then if the current calculation is negative, 0 will be inserted.
I haven't tested this, but this should work:
$sql = "UPDATE products SET stock = GREATEST(stock - '$quantity', 0) WHERE product_id = '$id'";
I'd just be careful you aren't prone to SQL injection here as you are passing $quantity and $id directly to the query string and if this is from a $_POST or $_GET request variable then the query can be manipulated.
I'm currently using PHP and MySQL to retrieve a set of 100,000 records in a table, then iterate over each of those records to do some calculations and then insert the result into another table. I'm wondering if I'd be able to do this in pure SQL and make the query run faster.
Here's what I"m currently using:
$stmt= $pdo->query("
SELECT Well_Permit_Num
, Gas_Quantity
, Gas_Production_Days
FROM DEP_OG_Production_Import
ORDER
BY id ASC
");
foreach ($stmt as $row) {
$data = array('well_id' => $row['Well_Permit_Num'],
'gas_quantity' => $row['Gas_Quantity'],
'gas_days' => $row['Gas_Production_Days'],
'gas_average' => ($row['Gas_Production_Days']);
$updateTot = $pdo->prepare("INSERT INTO DEP_OG_TOTALS
(Well_Permit_Num,
Total_Gas,
Total_Gas_Days,
Total_Gas_Avg)
VALUES (:well_id,
:gas_quantity,
:gas_days,
:gas_average)
ON DUPLICATE KEY UPDATE
Total_Gas = Total_Gas + VALUES(Total_Gas),
Total_Gas_Days = Total_Gas_Days + VALUES(Total_Gas_Days),
Total_Gas_Avg =(Total_Gas + VALUES(Total_Gas)) / (Total_Gas_Days + VALUES(Total_Gas_Days))");
}
I'd like to see if this can be done in pure MySQL instead of having to use PHP just for the fact of using it to hold the variables.
My Result should be 1 record that is a running total for each Well. The source table may house 60-70 records for the same well, but over a few thousand different Wells.
It's a constant import process that has to be run, so it's not like there is a final table which you can just do SUM(Gas_Quantity)... etc.. on
As commented by Uueerdo, you seem to need an INSERT ... SELECT query. The role of such query is to INSERT insert the resultset returned by an inner SELECT. The inner select is an aggregate query that computes the total sum of gas and days for each well.
INSERT INTO DEP_OG_TOTALS (Well_Permit_Num, Total_Gas, Total_Gas_Days, Total_Gas_Avg)
SELECT
t.Well_Permit_Num,
SUM(t.Gas_Quantity) Total_Gas,
SUM(t.Gas_Production_Days) Total_Gas_Days
FROM DEP_OG_Production_Import t
GROUP BY t.Well_Permit_Num
ON DUPLICATE KEY UPDATE
Total_Gas = Total_Gas + t.Total_Gas,
Total_Gas_Days = Total_Gas_Days + t.Total_Gas_Days,
Total_Gas_Avg =(Total_Gas + t.Total_Gas) / (Total_Gas_Days + t.Total_Gas_Days)
I have a problem regarding SQL Query. I have 3 Insert queries in my code.
the first query is with auto-increment ID.
INSERT INTO master_tbl
The second Insert will get the ID from 1st query using LAST_INSERT_ID()function.
INSERT INTO process (id_ref, process_id, hot_cold, temp)
VALUES (LAST_INSERT_ID(), '4', '-', '12')
My problem is, I have third query which needed to use the ID generated in the 1st query as its id_ref also.
When I use the LAST_INSERT_ID(), the ID it gets was the ID of the second query.
Any suggestions on how can I still get the ID in the 1st query to use on 3rd?
You can declare the variable and store the first queries id in that variable and then use it wherever you want.
After first query as you mentioned you are using the separate queries you can try using select to set the `Last insert id` into the variable and then use that variable as below,
select #valuetoUse := LAST_INSERT_ID()
Or Other way is use select the to get the value in your code and then pass that value to insert as all other values. For getting value you can directly fire select
SELECT LAST_INSERT_ID()
then in second query
INSERT INTO process (id_ref, process_id, hot_cold, temp)
VALUES (valuetoUse , '4', '-', '12')
then again in the third query
INSERT INTO thirdtable (id_ref, process_id, hot_cold, temp)
VALUES (valuetoUse , '4', '-', '12')
For more info on how to use user defined variables see here.
Functionality is same as told by #Coder of Code But with PHP
Try This
Create Connection
$conn = new mysqli($servername, $username, $password, $dbname);
First Insert into Table 1
INSERT INTO master_tbl
Then do
$sql = "SELECT MAX(id) as id from master_tbl";
$result = $conn->query($sql);
$row = $result->fetch_array(MYSQLI_NUM);
$latest_id=$row[0];
$sql = "INSERT INTO process (id_ref, process_id, hot_cold, temp)
VALUES ($latest_id,'4','-','12')";
if ($conn->query($sql) === TRUE)
{
echo "New record created successfully";
}
$sql = "INSERT INTO table3 (id_ref , columns list)
VALUES ($latest_id,other fields)";
if ($conn->query($sql) === TRUE)
{
echo "New record created successfully";
}
I want my the id field in my table to be a bit more " random" then consecutive numbers.
Is there a way to insert something into the id field, like a +9, which will tell the db to take the current auto_increment value and add 9 to it?
Though this is generally used to solve replication issues, you can set an increment value for auto_increment:
auto_increment_increment
Since that is both a session and a global setting, you could simply set the session variable just prior to the insert.
Besides that, you can manually do it by getting the current value with MAX() then add any number you want and insert that value. MySQL will let you know if you try to insert a duplicate value.
You have a design flaw. Leave the auto increment alone and shuffle your query result (when you fetch your data)
As far as i know, it's not possible to 'shuffle' your current IDs. If you wanted though, you could pursue non-linear IDs in the future.
The following is written in PDO, there are mysqli equivalents.
This is just an arbitrary INSERT statement
$name = "Jack";
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
$sql = "INSERT INTO tableName (name) VALUES(:name)";
$q = $conn->prepare($sql);
$q->execute(':name' => $name);
Next, we use lastInsertId() to return the ID of the last inserted row, then we concatenate the result to rand()
$lastID = $conn->lastInsertId();
$randomizer = $lastID.rand();
Finally, we use our 'shuffled' ID and UPDATE the previously inserted record.
$sql = "UPDATE tableName SET ID = :randomizer WHERE ID=:lastID ";
$q = $conn->prepare($sql);
$q->execute(array(':lastID' => $lastID , ':randomizer' => $randomizer));
An idea.. (Not tested)
CREATE TRIGGER 'updateMyAutoIncrement'
BEFORE INSERT
ON 'DatabaseName'.'TableName'
FOR EACH ROW
BEGIN
DECLARE aTmpValueHolder INT DEFAULT 0;
SELECT AUTO_INCREMENT INTO aTmpValueHolder
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'DatabaseName'
AND TABLE_NAME = 'TableName';
SET NEW.idColumnName =aTmpValueHolder + 9;
END;
Edit : If the above trigger doesn't work try to update AUTO_INCREMENT value directly into the system's schema. But as noted by Eric, your design seems to be flawed. I don't see the point of having an auto-increment here.
Edit 2 : For a more 'random' and less linear number.
SET NEW.idColumnName =aTmpValueHolder + RAND(10);
Edit 3 : As pointed out by Jack Williams, Rand() produces a float value between 0 and 1.
So instead, to produce an integer, we need to use a floor function to transform the 'random' float into an integer.
SET NEW.idColumnName =aTmpValueHolder + FLOOR(a + RAND() * (b - a));
where a and b are the range of the random number.
i got two tables and my environment transaction is allowed...
Table A - ID + Name
Table B - ID + Value A+ Value B+ IDTable A
may i know how to write the query to insert value at once ? hope it can be done within single query...just performance is the highest concern.
mysql_query("BEGIN");
$result_1 = mysql_query("INSERT INTO table_a ('name') values ('Chris')");
if( ! $result_1) {
mysql_query("ROLLBACK");
die(); // or handle the error however you choose
}
$table_1_id = mysql_insert_id();
$result_2 = mysql_query("INSERT INTO table_b ('value_a', 'value_b', 'table_a_id') values ('v1', 'v2', $table_1_id)");
if( ! $result_2) {
mysql_query("ROLLBACK");
die(); // or handle the error however you choose
}
mysql_query("COMMIT");
You can't do insert on different tables with a single query.
insert into tableA (name) values ('name');
set #last = last_insert_id();
insert into tableB (valueA,valueB,idtableA) values ('valueA','valueB',#last);