Missing FROM clause entry for table "product" - postgresql

CREATE OR REPLACE FUNCTION update_sellstatus()
RETURNS trigger AS
$body$
BEGIN
if products."sellStatus" = "Sold" then
update auctions
set "auctionStatus" = "End"
where (products."id" = auctions."idProduct");
end if;
END
$body$
language plpgsql
create trigger update_sellStatus_auctionStatus
after update on products
for each row
execute procedure update_sellstatus()
ERROR: missing FROM-clause entry for table "product"
I want to UPDATE column auctions.auctionStatus = "End" after UPDATE of column products.sellStatus = "Sold" where (products."id" = auctions."idProduct").
So I create a trigger but I got an error. It's make me can't UPDATE table products

You can't reference a table like in a function. But as this is a trigger. As documented in the manual you can access the values of the update row using the new record:
Also: string constants need to be enclosed in single quotes in SQL, double quotes are only needed for identifiers (and should be avoided like the plague).
"Sold" refers to a column, 'Sold' is a character (string) value
CREATE OR REPLACE FUNCTION update_sellstatus()
RETURNS trigger AS
$body$
BEGIN
if new."sellStatus" = 'Sold' then
update auctions
set "auctionStatus" = 'End'
where auctions."idProduct" = new."id";
end if;
END
$body$
language plpgsql

Related

How to update a column in all rows using functions?

I need to update a column in all rows in my table. I have a query which can do it for one row, but how to update all rows iterating each row at a time with a function?
I've tried something like this, but the syntax seems not to be correct.
CREATE OR REPLACE FUNCTION update_file_name()
$BODY$
BEGIN
UPDATE myTable
SET file = REPLACE(file, file, CONCAT(file, 'addingStringToTheEnd'))
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
alter function update_file_name()
Basically I expect to iterate every row and update the value of this column "file" editing the string, but I could not find a simple example which does that.
As mentioned in the comments, to update all rows in a table you shouldn't use a WHERE clause.
Here is a simple example that replaces all 'o' occurrences to 'a' in the column text of the table t1.
CREATE OR REPLACE FUNCTION public.update_o()
RETURNS void
LANGUAGE plpgsql
VOLATILE
AS $BODY$
BEGIN
UPDATE public.t1 SET text = REPLACE(text, 'o', 'a');
END;
$BODY$;
To invoke this function use:
SELECT update_o();

Trigger to reshape phonenumber

I want a trigger is my database which changes the first zero of a phone number to the appropriate country-code (in my case it's +31). My code so far is:
create or replace function correct_number()
returns trigger as $$
declare
Pnumber integer;
begin
select substring(phone, 1, 1) from "user" where phone = new.phone into Pnumber;
if Pnumber = 0 then
update "user"
set phone = overlay("user".phone placing '+31' from 1 for 1)
where id = new.id;
return null;
end if;
end
$$ language plpgsql;
create trigger force_countrynr
before insert on "user"
for each statement execute procedure correct_number();
There problem is that every time I try to add data, my DBMS gives an error that the end of the procedure is reached without a return. This means obviously that it doesn't consider the if-statement to be true, but I can't figure out why.
This is the DDL of the attribute that my function concerns is a varchar(13) and the my testquery is as follows:
insert into gebruiker
values('U5', 'Hans', '12345', 'Hans', null, 'Kraay', 'Hansworst', '0000QW', 'beukenweg', '4', null, '0612345678', 'test#notnow.nl', '2015-12-12');
I've tried changing the datatype of the zero in my if-statement, changing the datatype of the number-variable and many things more, but I can't get it to work.
You want to correct the number in each inserted row, so the trigger should be for each row.
There is no reason to query the table in the trigger, as the currently inserted row is available in the new variable.
There is no reason to update the table, just modify the new record and return it.
create or replace function correct_number()
returns trigger as $$
begin
if left(new.phone, 1) = '0' then
new.phone:= '+31' || right(new.phone, -1);
end if;
return new;
end
$$ language plpgsql;
create trigger force_countrynr
before insert on "user"
for each row execute procedure correct_number();

ERROR: unterminated dollar-quoted string at or near "$BODY$

I'm using sql fiddle...PostgreSQL 9.3:
CREATE TABLE HotelStays
(roomNum INTEGER NOT NULL,
arrDate DATE NOT NULL,
depDate DATE NOT NULL,
guestName CHAR(30) NOT NULL,
PRIMARY KEY (roomNum, arrDate))
;
CREATE OR REPLACE FUNCTION new_customer() RETURNS void AS
$BODY$
DECLARE
depatureDate DATE;\
BEGIN
SELECT depDate INTO depatureDate FROM HotelStays WHERE OLD.roomNum = NEW.roomNum;
IF (depatureDate <= NEW,arrDate)
INSERT INTO HotelStays (roomNum, arrDate, depDate, guestName)
VALUES (:NEW.roomNum, :NEW.arrDate, :NEW.depDate, :NEW.guestName);
END IF;
RETURN;
END
$BODY$
LANGUAGE 'plpgsql' ;
CREATE TRIGGER;
INSERT INTO HotelStays(roomNum, arrDate, depDate, guestName)
VALUES
(123, to_date('20160202', 'YYYYMMDD'), to_date('20160206','YYYYMMDD'), 'A');
Problem I am trying to solve: a new entry (for a new guest) could be put in for a room number, even before the existing guest has checked out.
I'm trying to solve this question using triggers. Please help me out. Thanks in advance.
As author mentioned, he used SQL Fiddle. I had the same problem with db-fiddle.com and resolved it by replacing $$ or $BODY$ with single quotes ' (and doubling single quotes elsewhere in between.
For example, db-fiddle
CREATE OR REPLACE FUNCTION update_datem()
RETURNS trigger AS
'
BEGIN
NEW.dateM = DATE_TRUNC(''MONTH'', NEW.date);
RETURN NEW;
END;
'
LANGUAGE plpgsql;
There are several errors in your code. First the backslash in depatureDate DATE;\. You are also missing a THEN for the IF clause and new does not need a : in front of it. You also have a , instead of a . in NEW,arrDate. And the final END is missing a ;.
Not an error, but the language name is an identifier, do not put it in single quotes.
The line CREATE TRIGGER; is also wrong. If you want to create trigger your function also needs to be declared as returns trigger and has to return the new row if it is a "before" trigger. If you intend to use an after trigger you still need to return something from that.
I am not sure what the condition WHERE OLD.roomNum = NEW.roomNum; is supposed to select. If you want to get the room number of the changed row, just use new.depdate. The select .. into ... will fail if that query returns more then one row. You probably meant to use where roomnum = new.roomnum or something similar.
So the function should be something like this:
CREATE OR REPLACE FUNCTION new_customer()
RETURNS trigger
AS
$BODY$
DECLARE
depatureDate DATE;
BEGIN
SELECT depDate
INTO depatureDate
FROM HotelStays
WHERE roomNum = NEW.roomNum;
IF (depatureDate <= NEW.arrDate) THEN
INSERT INTO HotelStays (roomNum, arrDate, depDate, guestName)
VALUES (NEW.roomNum, nEW.arrDate, NEW.depDate, NEW.guestName);
END IF;
RETURN NEW; -- this is important for a trigger
END;
$BODY$
LANGUAGE plpgsql;
And the code to create the trigger would be something like this:
CREATE TRIGGER check_stays
before update or insert on hotelstays
execute procedure new_customer();

Syntax error at CREATE TRIGGER query

I have this code, to add trigger for a View in my postgresql database
CREATE OR REPLACE FUNCTION changeCityProc() RETURNS TRIGGER AS $changeCity$
BEGIN
UPDATE vvs.tb_company SET city = "LAL" WHERE cardpresso.cardinfo.tb_company_city = vvs.tb_company.city;
RETURN null;
END;
$changeCity$ LANGUAGE plpgsql;
CREATE TRIGGER mytrigger
INSTEAD OF UPDATE ON
cardpresso.cardinfo FOR EACH ROW EXECUTE PROCEDURE changeCityProc();
pgAdmin says "syntax error at or near "INSTEAD""
Let's simplify this. First, the two schemas.
CREATE SCHEMA cardpresso;
CREATE SCHEMA vvs;
Next, the simplest possible table.
CREATE TABLE vvs.tb_company
(
city character varying(25)
);
INSERT INTO vvs.tb_company VALUES ('foo');
And a fairly useless view.
CREATE VIEW cardpresso.cardinfo AS
SELECT 'test' as tb_company_city UNION ALL
SELECT 'Orem' UNION ALL
SELECT 'Wibble'
;
Simplify the function. Warning: This will destructively update the table. Be careful if you copy stuff from this function into something headed for production.
CREATE OR REPLACE FUNCTION changecityproc()
RETURNS trigger AS
$BODY$
BEGIN
UPDATE vvs.tb_company SET city = 'bar';
RETURN null;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Finally, the trigger.
CREATE TRIGGER mytrigger
INSTEAD OF UPDATE
ON cardpresso.cardinfo
FOR EACH ROW
EXECUTE PROCEDURE changecityproc();
Now, if we update the view, we'd expect all the rows in vvs.tb_company to change to 'bar'.
select * from vvs.tb_company;
city
--
foo
update cardpresso.cardinfo
set tb_company_city = 'wibble';
select * from vvs.tb_company;
city
--
bar
So it looks like the problem is in the UPDATE statement of your function.
UPDATE vvs.tb_company SET city = "LAL"
WHERE cardpresso.cardinfo.tb_company_city = vvs.tb_company.city;
I'm not certain what you intended that statement to do, but it's not valid in PostgreSQL, regardless of whether "LAL" is supposed to be a column name or a string literal. As a string literal, 'LAL', it will raise an error.
ERROR: missing FROM-clause entry for table "cardinfo"
LINE 2: WHERE cardpresso.cardinfo.tb_company_city = vvs.tb_compa...

Not able to access the Primary Key value in PostgreSQL Trigger Function

I am just started writing the PL/pgSQL Trigger function. I am having couple of tables called Student and Result. Student having the following columns. ID,name,subject,mark (ID is the primary key) and the Result table is having two columns like ID,Status
Whenever one record has added in the student table, I want to update the Result table by checking the mark in the Student table, If the mark entered is greater than 50 then one record should be inserted in the Result table with ID and Status = Pass and if it is less than 50 then status will be fail.
I have the following Trigger function to achieve this
CREATE OR REPLACE FUNCTION "UpdateResult"() RETURNS trigger AS $BODY$
BEGIN
IF NEW.mark < 50 THEN
INSERT INTO "Result" SELECT 92,'fail';
RETURN NEW;
ELSE
INSERT INTO "Result" SELECT 92,'pass';
RETURN NEW;
END IF;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE STRICT SECURITY DEFINER
COST 100;
ALTER FUNCTION "UpdateResult"() OWNER TO postgres;
CREATE TRIGGER "Result"
AFTER INSERT
ON "Student"
FOR EACH ROW
EXECUTE PROCEDURE "UpdateResult"();
By this function trigger has worked as expected since I have hard coded the primary key value.
But When I modify the SQL inside Trigger function like the following
INSERT INTO "Result" SELECT NEW.ID,'fail'; (or)
INSERT INTO "Result" SELECT NEW.ID,'pass';
It is throwing error like
> ***Record "new" has no field "id" Context : PL/pgSQL function
> "UpdateResult" line 3 at SQL statement***
Means it is able to take the values of non primary key values from NEW variable not the primary key value. Can any one please tell me is there a restriction in PL/pgSQL or Am I doing anything wrong !
Just a hint: why are you using quoted names? When doing this, you have to care about capitalisation.
See if this works:
CREATE OR REPLACE FUNCTION UpdateResult() RETURNS trigger AS $BODY$
BEGIN
IF NEW.mark < 50 THEN
INSERT INTO result (id, status) values (92,'fail');
RETURN NEW;
ELSE
INSERT INTO result (id, status) values (92,'pass');
RETURN NEW;
END IF;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE STRICT SECURITY DEFINER
COST 100;
ALTER FUNCTION UpdateResult() OWNER TO postgres;
CREATE TRIGGER Result
AFTER INSERT
ON Student
FOR EACH ROW
EXECUTE PROCEDURE UpdateResult();