I have an issue that I can`t figure out. I have prepared table that will store some data of delivery prices.
CREATE TABLE delivers_prices(
id SERIAL PRIMARY KEY
, price NUMERIC(40,2) NOT NULL
, weight_from NUMERIC(20) NOT NULL
, weight_to NUMERIC(20) NOT NULL
, zone INTEGER NULL REFERENCES zones (id) ON UPDATE CASCADE ON DELETE CASCADE
, deliver INTEGER NOT NULL REFERENCES delivers (id) ON UPDATE CASCADE ON DELETE CASCADE
, CHECK(weight_from < weight_to)
);
The issue is that I need to constraint two fields weight_from and weight_to
algorithm need to check if currently inserting row will not be in the range between weight_from and weight_to of already inserted rows. More precisely there cant be situation when price of delivery (row) is twice for deliver in specified range
I already implemented the trigger but they not working as I expected
CREATE FUNCTION delivers_prices_unique( ) RETURNS TRIGGER AS
$func$
DECLARE weightFrom NUMERIC(20);
DECLARE weightTo NUMERIC(20);
DECLARE deliverId INTEGER;
BEGIN
CASE
WHEN TG_OP = 'DELETE' THEN
weightFrom := OLD.weight_from;
weightTo := OLD.weight_to;
deliverId := OLD.deliver;
ELSE
weightFrom := NEW.weight_from;
weightTo := NEW.weight_to;
deliverId := NEW.deliver;
END CASE;
IF
EXISTS (
SELECT * FROM delivers_prices oth
WHERE oth.deliver = deliverId
AND oth.weight_from BETWEEN weightFrom AND weightTo
OR oth.weight_to BETWEEN weightFrom AND weightTo
)
THEN
RAISE EXCEPTION 'delivery price for given weight exist';
RETURN NULL;
ELSE
RETURN NEW;
END IF;
END;
$func$ LANGUAGE 'plpgsql';
usage of function
CREATE TRIGGER check_delivers_prices
BEFORE UPDATE OR INSERT OR DELETE
ON delivers_prices
FOR EACH ROW
EXECUTE PROCEDURE delivers_prices_unique();
and some examples:
INSERT INTO delivers_prices(price, weight_from, weight_to, deliver)
VALUES (22, 20, 100, 1); // we inserting the range 20 - 100
so from now delivery of some products between 20 and 100 kg will cost 22 EUR
INSERT INTO delivers_prices(price, weight_from, weight_to, deliver)
VALUES (22, 21, 22, 1); // should not be inserted beacuse we already have row with range 20 - 100 and this row will be between that range.
Why trigger not throw exception beacuse
SELECT * FROM delivers_prices oth
WHERE oth.deliver = 1
AND oth.weight_from BETWEEN 21 AND 22
OR oth.weight_to BETWEEN 21 AND 22
I know something wrong with SELECT in trigger in If clause. I will be grateful for and suggestions or help