Select and Update in Stored Functions Postgresql - sql

I created a stored function for fetching data:
CREATE OR REPLACE FUNCTION sold_quantity()
RETURNS TABLE(
invoiceid BIGINT,
itemid BIGINT,
sum_sold_quantity NUMERIC)
AS $$
BEGIN
RETURN QUERY SELECT
invoice_id as invoiceid, item_id as itemid, sum(sold_quantity) as
sum_sold_quantity
FROM
invoice_item
WHERE
status='sold'
GROUP BY
invoice_id, item_id;
END; $$
LANGUAGE 'plpgsql';
How to store this data and using it to update the table below?
UPDATE invoice_item
SET sold_quantity = sum_sold_quantity
where invoice_id=invoiceid
and item_id = itemid;
How can we club these two queries (Select and update) in one stored function and execute to fetch all 500k records with the above three columns and update batch wise (like 10 000 records)

You can use the function directly in the UPDATE statement
UPDATE invoice_item ii
SET sold_quantity = sq.sum_sold_quantity
from sold_quantity() as sq
where ii.invoice_id = sq.invoiceid
and ii.item_id = sq.itemid;
For just 500.000 rows, I wouldn't bother doing any batching at all. Just update all rows in a single statement.
In fact you don't really need a function to begin with:
UPDATE invoice_item ii
SET sold_quantity = sq.sum_sold_quantity
from (
select invoice_id as invoiceid, item_id as itemid, sum(sold_quantity) as sum_sold_quantity
FROM invoice_item
WHERE status='sold'
GROUP BY invoice_id, item_id;
) as sq
where ii.invoice_id = sq.invoiceid
and ii.item_id = sq.itemid;

Related

TSQL: Given a set of IDs, obtain all headers such that the set is included in the header's children

I am looking for a query that would return all Order ID's that contain a set of productIDs, but might include more products.
Data structure:
CREATE TABLE dbo.Order(OrderID int, OrderDesc nvarchar(100))
CREATE TABLE dbo.OrderDetail(DetailID int, OrderID int, ProductID int)
CREATE TABLE dbo.Product(ProductID INT, ProductDesc nvarchar(100))
So given a set of productIDs, I want a query to return all orders that contain all (possibly more) products from the set.
You can use aggregation:
select od.orderid
from orderdetail od
where od.productId in (. . .)
group by od.orderid
having count(od.productid) = <n>; -- <n> is the number of products in the list
This assumes that there are no duplicate products in an order. If that is possible, use count(distinct od.productid).

Update multiple columns by ids

I have tables called tblPurchase and tblInvoice. When I Insert new record I want to update my TotalStock form tblInvoice. I tried following code.
Create procedure [dbo].[spUpdateTotalStock] #Stock int, #PurchaseId int
As
Begin
Begin Transaction
Update tblPurchase
Set TotalStock = #Stock
Where PurchaseId = #PurchaseId
RollBack Transaction
end
It worked as expected. But I want to update TotalStock column by many ids. It means when I insert more than one invoice at the same time, I want to update my TotalStock column. like this
tblInvoice
ItemName | Quantity
---------+----------
Phone 3
Mouse 6
tblPurchase
ItemName | TotalStock
-----------+------------
phone 3
Mouse 6
ID comes with parameter. Always more than 10 ids come with parameter.
When I Insert new record I want to update my TotalStock form tblInvoice
This would normally be handled via a trigger not a stored procedure. That would look something like this:
create trigger trig_invoice_update on tblInvoice
after insert, update, delete
begin
update p
set quantity = p.quantity + coalesce(i.quantity, 0) - coalesce(d.quantity, 0)
from tblPurchase p left join
(select i.itemName, sum(i.quantity) as quantity
from inserted i
group by i.itemName
) i
on p.itemName = i.itemName left join
(select d.itemName, sum(d.quantity) as quantity
from deleted d
group by d.itemName
) d
on p.itemName = d.itemName
where d.quantity <> 0 or i.quantity <> 0;
end;
This version handles inserts, updates, and deletes, but assumes that all items are already in the purchases table.

Can someone help me implement the following trigger in PL/SQL Oracle?

So,
I have 4 tables:
Suppliers( id_sup, name, city)
Products (id_prod, name, city)
Companies (id_co, name, city)
Deliveries (id_sup, id_prod, id_co)
I need a trigger so that if I want to update the city of a Supplier, I am not allowed if that supplier has a delivery where the product it delivers and the company it delivers to have the same city as it.
This is what I've tried so far, but it's not working:
CREATE OR REPLACE TRIGGER secure_suppliers
BEFORE UPDATE ON Suppliers
BEGIN
IF UPDATING ('city') THEN
IF (suppliers.id_sup IN (SELECT id_sup FROM Deliveries) AND suppliers.city = (Select p.city From Products p INNER JOIN Deliveries d ON (p.id_prod = d.id_prod)) AND suppliers.city = (Select c.city From Companies c INNER JOIN Deliveries d ON (c.id_co = d.id_co))) THEN
RAISE_APPLICATION_ERROR(-20500, 'Can't update city!');
End if;
End;
You can use one query to find if product, supplier and company are in one city with new value of the supplier then proceed with error handling in the trigger as following:
CREATE OR REPLACE TRIGGER secure_suppliers
For each row -- row level trigger
BEFORE UPDATE OF city ON Suppliers -- trigger will execute on update of column city only
DECLARE
cnt NUMBER := 0;
BEGIN
select count(1)
Into cnt
From deliveries d
Join companies c on d.id_co = c.id_co
Join products p on d.id_prod = p.id_prod
Where p.city = c.city
And p.city = :new.city;
If cnt > 0 then
RAISE_APPLICATION_ERROR(-20500, 'Can''t update city!');
End if;
End;
/
Cheers!!

ORACLE SQL Status check trigger

I wanted to create a trigger which when a new order is inserted in the ORDERS table the trigger updates the status level of a customer in the CUSTOMER table, depending on how many orders they have made. If a customer has 0 orders his status level is 'new' else if he has more than 1 he is a 'standard' customer.
The trigger below works if I add the customer_no in manually:
create or replace TRIGGER STATUS_CHECK
AFTER INSERT ON ORDERS
DECLARE
n INT;
BEGIN
SELECT COUNT(ORDER_NO)
INTO n
FROM ORDERS
INNER JOIN CUSTOMER
ON CUSTOMER.CUSTOMER_NO = ORDERS.CUSTOMER_CUSTOMER_NO
WHERE CUSTOMER.CUSTOMER_NO = '01';
IF(n > 1) THEN
UPDATE CUSTOMER
SET CUSTOMER.STATUS_LEVEL = 'STANDARD'
WHERE CUSTOMER.CUSTOMER_NO = '01';
END IF;
END;

oracle: update a column with not null value

I wanna update a column of a table:
UPDATE product prod
SET prod.prod_supplier_id = (SELECT s.prod_supplier_id
FROM supplier s
WHERE s.prodno = prod.prodno
)
the SELECT s.prod_supplier_id
FROM supplier s
WHERE s.prodno = prod.prodno
mustn't return a null result, if it's null, the update will not be made
How to do that?
You need to filter the rows to be updated in the WHERE clause as well:
UPDATE product prod
SET prod.prod_supplier_id = (SELECT s.prod_supplier_id
FROM supplier s
WHERE s.prodno = prod.prodno
)
WHERE EXISTS (SELECT 42
FROM supplier s2
WHERE s2.prodno = prod.prodno);
It might be faster using a MERGE (assuming prodno is the primary key in product):
merge into product
using
(
select p.prodno,
s.prod_supplier_id
from product p
join supplier s on s.prodno = p.prodno
) t on (t.prodno = prod.prodno)
when matched then update
set prod_supplier_id = t.prod_supplier_id;
Not tested!
first of all create a back up table:
CREATE TABLE productBAK AS SELECT * FROM product;
now you can use update query like this:
UPDATE product prod
SET prod.prod_supplier_id = (SELECT s.prod_supplier_id
FROM supplier s
WHERE s.prodno = prod.prodno and
s.prod_supplier_id is not null
)
WHERE prod.prodno in (SELECT s1.prodno FROM supplier s1 where s1.prod_supplier_id is not null);
The WHERE clause specifies which record or records that should be updated. If you omit the WHERE clause, all records will be updated!
I see prod_supplier_id being a column in both product and supplier.
Can you explain in which table the prod_supplier_id must not be null?
Looking at your query you want something like
update product
set prod_supplier_id = (select prod_supplier_id
from supplier
where prod_supplier_id is not null);
Issues you're facing:
all product records will be updated with the same prod_supplier_id
if the subselect statement returns more than one record -let's say you have 5 suppliers, so 5 prod_supplier_id's, the update statement will fail.
Can you tell us:
do you want all your products to be set to 1 supplier?
if not, do you have a list of which product should have which supplier?
R