Insert data with specific condition using Oracle procedure? - sql

I want to insert data from view to table by using Oracle Procedure.
The view is called VW_INVPART. The view consist of column from different tables:
(M_Product table)
AD_ORG_ID,
AD_Client_ID,
Name,
M_Product_ID,
(M_Storage table)
QtyOnHand,
(M_Replenish table)
level_min
(M_Product_PO table)
order_min
The table I want to insert is M_RequisitionLine.
My scenario is there's goods quantity which defined in QtyOnHand. QtyOnHand is dynamic so it can be changed depends on the logistic in-out process. then there's minimum level which is defined in level_min. When goods run out of stock, we can order it again and there's minimum order quantity which is defined in order_min.
So, when the amount of QtyOnHand is less than level_min, we can add data to column Qty in M_RequisitionLine in order to request stock. But there are minimum quantity to be put in M_RequisitionLine.Qty (order_min).
If level_min - QtyOnHand <= Order_min, then set M_RequisitionLine.Qty to Order_min.
But, If level_min - QtyOnHand >= Order_min, then set M_RequisitionLine.Qty into the difference between level_min and QtyOnHand.
How can I make the procedure in the Oracle? I've tried arranged the code but still confused as I am newbie in Oracle SQL.

You could write this into a PL/SQL stored procedure in the following way by using case command. Very basic example below. Keep in mind, I don't know what the entity relationships are for your tables or what their cadinality is, so a lot of what I did is based on singular value assumptions. If the select data returns more than one row, you have to use oracle collections.
Declare
t M_Storage.QtyOnHand%TYPE;
v M_Replenish.Level_min%TYPE;
o M_Product_PO.order_min%TYPE;
Begin
SELECT QtyOnHand INTO t FROM M_Storage;
SELECT Level_min INTO v FROM M_Replenish;
SELECT Order_min INTO o FROM M_Product_PO;
CASE
When t-v < o Then UPDATE M_RequisitionLine set qty = o;
When t-v >= o then UPDATE M_RequisitionLine set qty = t-v;
END CASE;
END;
/

This functionality already exists in standard Adempiere.
For a product, define the min, max & replenishment rules on the Replenish tab of the Product Window. On the Purchasing tab, of the same window, you can define, per Supplier the Minimum Order Qty.
Now, if you run the Replenishment Report under the Material Management menu, you can run the report and generate Purchase Orders to fulfill the replenishment based on the rules you defined and this will honour the minimum order quantity set on the Purchasing tab,
It's not a technical solution but it works.
Now if your needs were even more complex fulfilment method that the standard you could define a custom replenishment rule. This is a simple java class that must implement the Interface org.compiere.util.ReplenishInterface and requires that you implement one function... getQtyToOrder.
Once you have your class defined you specify this class on the Warehouse window.
Now, on the Product window->Replenish tab you can select Custom as the Replenish Type and this class will be used to calculate the quantity to replenish.
This approach would be better as it maintains your ability to use any supported database rather than just Oracle.

Related

How to keep the updated rows for a period of time

I am working with small project using SQL Server, and I need some help from you, to clarify the problems I am having with a task.
What I am trying to do is update the row in table and keep these updated rows for a period of time.
For example I am using this code to update:
ALTER PROCEDURE [dbo].[updtprice]
#bc int,
#price float
AS
UPDATE tblproduct
SET Price = #price
WHERE Barcode = #bc
What I am trying to do is, for example I update the price of the product with barcode 2233 from 0.99 cent to 0.70 (today). And I want the price to be reverted to old one after one or two week( certain data set by user).
How can I accomplish this task?
Thanks to everyone
There may be other ways to do it but it sounds like you need another table that records the previous value and date that it expires. Then you would have a "job" that runs daily that takes note of any expired and does the update back to previous value.
OR you have additional columns in this table with the special price and expiration date and any applications that use that row look at the special price, is it still good, if so use it, if not use the regular price.
To be honest, the only way to properly do this is either:
Write a script that does this.
Write a scheduled task in MS SQL.
Both not great ways to do it in all honesty. I would personally go with option 1 if it's a web-application and option 2 if it's just a Database.
you can have 3 columns in your table.
actual_price
current_price
price_update_date
actual_price columns will always have exact price of the product.
you can update the current_price with the discounted price and also update the strong text price_update_date column when updating the current_price.
like.
ALTER procedure [dbo].[updtprice]
#bc int,
#price float
as
update tblproduct set current_price= #price,
price_update_date=SYSDATETIME()
where
Barcode = #bc
and then you can create another stored Proc which will run everyday at 12 am.
and chech if current_time -price_update_date is greater than or equal to your threshold then update the current_price of the product with actual_price

Oracle database, conditional column

I'm not sure from where to start hitting this problem from.
I have huge table, at least hundreds of thousand rows.
One of the columns should be price, but in customers currency. The data available is
Price data in EUR
Package with function to get exchange rate
Of course, exchange rates will update frequently and first fetching the row, then checking if customer uses EUR and if not, doing another fetch for rate information seems like a bad idea.
Also many of the customers will use EUR, so always checking the rate with same query might cause useless overhead.
My first idea was to fetch price and customer data (both needed anyways) and then if customer uses different currency from EUR, I would make another query.
Second idea was to make table witch would have correct price in customer currency to start with. Maybe using Oracle function (which again I already have)
I think, second way is 'more correct' implementation but I have no idea how to use package function to get one column in view.
Is there better way, or should i go with one of these?
As you said that exchange rates are updated frequently and you will always need updated currency values so My suggestion is to create the VIEW and use it as a table wherever you need in your application.
create or replace view your_view_name as
select <column_list>,
case when currency = 'EUR' then price else price*conversion_rate end as price
from <both of your tables with join>
Cheers!!
Creating a view is not a bad call, but you have to realise it's actually just a header, so the query in there would execute each time the value is called, so I'm not sure that's exactly what you want.
what you can do is create a materialized view for all values in all currencies using the function, index it properly for fast search and refresh every time your rates change (doubt they will change every 15 mins) - for materialized view the refresh will perform automatically if set this way.
Virtual column comes to your rescue. Note that virtual columns are there starting with Oracle 11g.
Simple add the formula defining the calculation as an virtual column as in example below.
alter table price add
( home_price NUMBER GENERATED ALWAYS AS
(case when currency = 'USD' then price
else price * convert_rate('EUR','USD') end) VIRTUAL
);
Note that is is required, that the rate conversion function is declated as DETERMINISTIC.
Here is the full example for converting EUR in the home rate of UDS
create table price as
select 10 price, 'EUR' currency from dual union all
select 20 price, 'USD' currency from dual;
create or replace function convert_rate (p_from varchar2, p_to VARCHAR2) return number DETERMINISTIC as
BEGIN
return 1.1;
END;
/
alter table price add
( home_price NUMBER GENERATED ALWAYS AS
(case when currency = 'USD' then price
else price * convert_rate('EUR','USD') end) VIRTUAL
);
select *
from price;
PRICE CUR HOME_PRICE
---------- --- ----------
10 EUR 11
20 USD 20

How do I create a table the same time as other tables that pulls totals from each?

For class I'm creating a database that keeps track of my finances. I have a table for each type of item I purchase. For example Rent, Food, Hygiene, Entertainment,etc... I also have a table called Register that I want to display the monthly total for each item. The column names for the totals in the tables are as follows: MonthlyRentTotal, MonthlyFoodTotal, etc...
I want the Register table to pull the total from each Table so I don't have to enter them twice. Any Ideas on how I can do that? I don't want to create a view either. I want it to be an actual table. I'm not even sure if this is possible.
I assume that Rent, Food, Hygiene, Entertainment have same column type.
INSERT INTO Register
SELECT *
FROM
(SELECT SUM(a.rent_value) AS value,
'monthlyrent' AS TYPE
FROM Rent a
UNION SELECT SUM(b.food_value) AS value,
'monthlyfood' AS TYPE
FROM Food b) d pivot(max(value)
FOR TYPE IN (monthlyrent, monthlyfood)) piv;
Data was pivoted in order to be inserted into Register table.
You can put this query in a stored procedure or simply run it manually. If you want to have updated data in the Register table I suggest to :
Create a stored procedure using a TRUNCATE for Register table followed by the above query
Create an SQL Job and schedule the run of the stored procedure anytime you need.
Hope this helps. Let me know if you need additional details.
You should only separate the items into separate tables if there is a compelling reason. For the items you describe, I see no compelling reason.
I would imagine a data structure like this:
itemCategories -- contains the list of categories you care about, such as "food", "hygiene", and so on.
Purchases -- contains each purchase, with columns like purchaseDate, location, itemCategory, description, and so on.
You may want additional tables for other entities, such as "location".
What you are calling a Register table would then simply be a query or view on Purchases.

Creating a Scalar Function in SQL-Server To get Stock Preview

So I'm having trouble creating a function to get a Preview of the stock of a product.
Simplified Model explanation:
My database has a table of Products, Sales and Orders, and I need to create a function that receives as parameter the Product's NumberID and a date, and return the preview stock on that specific date.
Basically if I have in store 5 bottles, and have an order for tomorrow of 3 bottles, given the 'day after tomorrow' date, then the Stock Preview will be 2.
My problem is, given a date before the current one, I think I'll need to go and see the sales between that date and now and add them to the preview right? and only after that I'll check the orders table.
I've been using many if's and cursors and it's driving me crazy

stock table for inventory database design architecture

I am currently building a management system. Is it good practice to create a balance table for inventory to store the inventory at hand and constantly update the table if there are changes, or should one just directly query total inventory ordered table - total inventory used table? Which would be the most efficient and fastest way to do?
It is likely a bad idea to use two separate tables. You will have to perform a join which is unnecessary. Simply have one table with an 'ordered' column and a 'used' column. In your query you can very efficiently calculate the net value e.g. :
SELECT ordered, used, (ordered - used) as net FROM inventory