I am new to Mysql. I want to create a stored procedure that update the price for a product. I use jdbc to implement this stored procedure.But my stored procedure command failed many times. The following is mysql code. "p" means product, "des" means the decrease in price and "pro" means product name. The CallableStatement in java will give the product name and the decrease for that the product's price. Thus the stored procedure will decrease the price for the corresponding product.
`CREATE PROCEDURE updateP(IN pro CHAR(10), IN des INT)`
`
BEGIN`
UPDATE customers
`DECLARE p INT;`
`SET p = (SELECT price FROM customers WHERE product= pro);`
`SELECT p;`
`p = p - des;`
END
I think this is all you need:
DELIMITER $
CREATE PROCEDURE updateP(IN pro CHAR(10), IN des INT)
BEGIN
UPDATE customers
SET price = price-des
WHERE product= pro;
END$
DELIMITER ;
That should decrease the current price by the decrease amount passed in as parameter.
One suggestion: don't name your procedures updateP use full names like sprocUpdateProduct or UpdateProduct_sp; if tomorrow you need to update a person you no longer will know whether updateP updates a Person or a Product. The same goes for variables, use full names.
Related
I'm attempting to create a trigger that increases the value of a column INCOME in the Salary database by 500 each time the value of WorkYear in the Employee table is increased by one year. For example, if the workYear is 4 and the salary is 1000, the salary should be 1500 if the workYear is increased by one year, 2000 if the workYear is increased by two years, and so on.
I tried to create such trigger and here is my code :
DELIMITER $$
create trigger increment AFTER UPDATE on employee
for each row
BEGIN
IF OLD.workYear <> new.workYear THEN
update salary
set income = (income + (new.workYear-old.workYear)*500);
END IF;
END$$
The idea behind this code is that after we update the workYear, the trigger should increase the salary by the difference of years * 500, (new.workYear-old.workYear)*500, but it increases all the rows by the same number, (5500 if we add one year, 27500 if we add two years, etc.) which not what we are looking for .
I am new to MySQL and would appreciate it if someone could assist me with this.
Thanks in advance
FaissalHamdi
In MySQL an AFTER trigger can affect the entire table, so you must declare the update scope in the form of criteria or a join.
Create Trigger in MySQL
To distinguish between the value of the columns BEFORE and AFTER the DML has fired, you use the NEW and OLD modifiers.
The concept is similar but each RDBMS has a slightly different syntax for this, be careful to search for help specifically on your RDBMS.
In the original query these special table references were used to evaluate the change condition however the scope of the update was not defined.
Assuming that there is a primary key field called Id on this salary table.
Also note that if you can, the query should be expressed in the form of a set-based operation, instead of static procedural script, this will be more conformant to other database engines.
So lets try this:
DELIMITER $$
create trigger increment AFTER UPDATE on employee
for each row
BEGIN
UPDATE salary s
SET income = (income + (new.workYear-old.workYear)*500)
WHERE s.Id = OLD.Id
END$$
I am trying to make a MySQL stored procedure that processes a book purchase and inserts records into other tables about the purchase. However, these insertions can only happen if three conditions are met: the customer is in the system, the book is in the system, and there is enough quantity.
I want to check for each condition individually, and if it passes the first condition, it moves to the next, but if it doesn't, I want it to end the procedure and return a value, and so on for each condition. If it passes all three conditions, the insertions can happen. Here's how I coded it:
DELIMITER //
CREATE PROCEDURE process_purchase(
IN book_key INT,
IN customer_key INT,
IN quantity INT
)
BEGIN
DECLARE book_inventory_key_var INT;
DECLARE purchase_key_var INT;
SELECT book_inventory_key
INTO book_inventory_key_var
FROM book_inventory
WHERE book_key = book_key.book_inventory_key;
SELECT purchase_key
INTO purchase_key_var
FROM purchases
WHERE customer_key = customer_key.purchases;
IF customer_key != customer_key.customers THEN
SELECT '-1';
ELSEIF book_key != book_key.books THEN
SELECT '-2';
ELSEIF quantity < quantity_on_stock(book_key) THEN
SELECT '-3';
ELSE
INSERT INTO purchases VALUES (customer_key, CURDATE());
INSERT INTO purchase_items (book_inventory_key, purchase_key, quantity) VALUES (book_inventory_key_var, purchase_key_var, quantity);
SELECT '1';
END IF;
END//
DELIMITER ;
I compare the customer and book keys to their values in the other tables, and the quantity to the quantity_on_stock stored function I previously made. I use a chain of IF-ELSEIF to go through each condition one by one, and if all of them are passed, the insertions occur. If not, it won't go to the next condition, and will return the SELECT message, correct? The procedure runs without errors, but I am unsure if this is the correct method, or if there's a better way of going about this.
Checking sequentially is subject to race conditions. Breaking this paradigm is key to moving from a procedural to SQL based method. Use the database features of to obtain consistency rather than procedural code.
purchase_items should have foreign key constraints to book_key and customer_key tables. If an insert generates a FK exception then one of these apply depending on the error. DECLARE HANDLER will help catch these errors.
For the quantity:
INSERT INTO purchase_items (book_inventory_key, purchase_key, quantity)
SELECT book_key, purchase_key, quantity
FROM books WHERE book_key = book.id AND book.available >= quantity
If there are no ROW_COUNT for this, then there wasn't sufficient quantity.
You will also need to reduce the amount of books available in the same SQL transaction.
If you don't have to do this in a STORED PROCEDURE, don't. A lot of the constructs here are easier in application code. If this is an assignment, where store procedures are require to get extra marks, get through it, and never write a stored procedure again.
I have created a database called stock trades and two tables (company data and stock_data) I want to create a procedure that will help me find stocks over 500K volume and in the technology sector. sector variable is in table company data and volume variable in stock_data) here is my code so far:
stockcode
create procedure highvolumetechstock
as
select Volume
from stock_data
INNER JOIN Companydata ON stock_data.Volume = Companydata.Sector
where Sector = 'Technology' and Volume > 500000
exec highvolumetechstock
Here is how to declare in procedure in mysql. Please note that, as commented, using a procedure is does not make a lot of sense, as you could obtain the same result with a simple SQL query.
delimiter //
CREATE PROCEDURE highvolumetechstock()
BEGIN
SELECT Volume
FROM stock_data
INNER JOIN Companydata ON stock_data.Volume = Companydata.Sector
WHERE Sector = 'Technology' AND Volume > 500000
END //
delimiter ;
Then you execute the procedure with :
CALL highvolumetechstock();
I am working on a car rental system. The table 'Hire' has fields like hireDate, returnDate, etc. I want to be able to calculate the rent and insert that value automatically into the database (same table).
I am wondering if I can subtract these two date fields, and the value which comes out of this can be multiplied by a certain number (say 300) and automatically added to another attribute called 'Rent_Due'. The idea is to calculate the total rent due by getting the number of days and then multiplying that by a certain number. So for every Hire that is made, I just enter the hiring date and the return date, and the Rent Due attribute is automatically filled. Is this possible by any chance?
I dont know what more information I need to provide to seek help, kindly let me know if you might require an image of my ERD.
Thanks!
Assuming the difference you want to compute in in days, this should work.
INSERT INTO yourTable (hireDate, returnDate, Rent_Due) VALUES
(StartDate. EndDate, DATEDIFF(EndDate, StartDate)*300)
Personally I would steer clear of having calculated fields in the database, and try to keep it normalized.
You could, instead, use a view for the duration of hire and hence the price.
Example as follows:
create view hire_duration as (
select hireId, hireDate, datediff(returnDate,hireDate) as duration
from Hire
);
(This assumes you have a primary key called hireId in your Hire table)
You could easily modify the view to have cost of hire as well, by multiplying duration by some constant, and that would be OK if the cost never changes, but if it you want to have the flexibility of different hire rates you wound't want to hard-code a rate in your SQL.
You don't required to create another field you can get your result be the following query.
select (datediff(hireDate, returnDate)*300) as rent,hireDate,returnDate from Hire;
Are you looking for maybe something like this?
Before-Insert-Event:
DELIMITER $$
CREATE TRIGGER name_of_before_insert_trigger BEFORE INSERT ON name_of_table
FOR EACH ROW BEGIN
SET NEW.Rent_Due = DATEDIFF(NEW.returnDate, NEW.hireDate) * 300;
END;
$$
DELIMITER ;
Before-Update-Event:
DELIMITER $$
CREATE TRIGGER name_of_before_update_trigger BEFORE UPDATE ON name_of_table
FOR EACH ROW BEGIN
SET NEW.Rent_Due = DATEDIFF(NEW.returnDate, NEW.hireDate) * 300;
END;
$$
DELIMITER ;
The daily rate you can also outsource in a separate table:
DELIMITER $$
CREATE TRIGGER name_of_before_insert_event_trigger BEFORE INSERT ON name_of_table
FOR EACH ROW BEGIN
SET NEW.Rent_Due = DATEDIFF(NEW.returnDate, NEW.hireDate) * (SELECT value FROM name_of_price_table LIMIT 1);
END;
$$
DELIMITER ;
Example of function:
call getThings(amount, place, limit, marginError)
SYNOPSIS: CALL getThings(4, PA, 3, 1.2);
example of goal:
CREATE PROCEDURE getThings(IN amount X, place VARCHAR(30), lim INT, marginError double)
SELECT place, limit, amount
FROM AREA, PRODUCT
WHERE AREA.place=PRODUCT.place
AND PRODUCT.AREA=place
ORDER BY ABS(AMOUNT-marginError)
LIMIT lim;
END
Desired goal is to retrieve the closest 3 products from a stored procedure (using MySQL) but I keep getting sytax errors in trying to create the procedure.
since you didn't post the exact error/message,
EDIT: I assume you are
missing the IN/OUT for the 2.and 3. parameter. - Not true, see comments.
e.g.
DELIMITER$$
CREATE PROCEDURE getThings(IN amount X, IN place VARCHAR(30), IN lim INT)
SELECT place, `limit`, amount
FROM AREA, PRODUCT
WHERE AREA.place=PRODUCT.place
AND PRODUCT.AREA=place
ORDER BY ABS(AMOUNT-5)
LIMIT lim;
END$$
DELIMITER;
LIMIT is MySQL's reserved word. If you really need to use it as column name, put in in backticks (``). Also, your paramteres have same names as columns in your table, which adds to confusion.