How invoke PL/pgSQL from command line instead of SQL - postgresql

I write PL/SQL scripts using Oracle and I'm trying my first PL/pgSQL script with PostgreSQL. For example, I created this test.sql file.
DECLARE
v_loc_nbr INTEGER;
BEGIN
v_loc_nbr := 0;
END;
Which I try to execute using the command line:
\postgresql\9.3\bin\psql.exe -d postgres -f test.sql
but I get syntax errors like:
psql:test.sql:4: ERROR: syntax error at or near "v_loc_nbr"
I think the problem is it trying to execute SQL when I want it to run PL/pgSQL. What should the command be?

Like with other procedural languages, you cannot run PL/pgSQL directly.
You can only run SQL. Use plpgsql inside a function body or wrapped in a DO command, where the range of DO commands is limited since they cannot return data.
Check out the plpgsql tag for examples.

I don't want to explain more about this because Erwin explained well.You need to wrap your sql inside a DO, so your test.sql should write like this
DO
$$
DECLARE
v_loc_nbr INTEGER;
BEGIN
v_loc_nbr := 0;
END;
$$
and try to execute it \postgresql\9.3\bin\psql.exe -d postgres -f test.sql

Related

postgresql copy from csv file into table in windows through procedure

below is my procedure executed to upload file into table and do joins etc.
CREATE OR REPLACE FUNCTION sp_product_price()
RETURNS void
LANGUAGE 'plpgsql'
COST 100
AS $BODY$
BEGIN
truncate table prd_product_data;
truncate table price_import;
COPY price_import FROM 'C:\Users\Ram\Documents\prices.csv' CSV HEADER;
truncate table active_product_price;
insert into active_product_price(key,name,price)
SELECT prd.key,prd.name,prd.price FROM prd_product_data prd JOIN price_import import ON prd.name = import.name;
raise notice 'success';
END
$BODY$;
Above procedure giving error could not open file "C:\Users\Ram\Documents\prices.csv" for reading: No such file or directory HINT: COPY FROM instructs the PostgreSQL server process to read a file. You may want a client-side facility such as psql's \copy.
I have given access to file for everyone in file properties.
I tried \copy in procedure but this gives error syntax error at or near "\" .
\copy is working when I ran cmd in psql but not in above procedure.
Is there a way to import file into table in above procedure/functions ?
The procedure and the COPY statement are running on the database server, so the file C:\Users\Ram\Documents\prices.csv must be on the database server as well (and your database user must either be a superuser or a member of pg_read_server_files).
The only way you can use COPY to load data from the client is COPY ... FROM STDIN, and you won't be able to use that in a procedure.
\copy is a psql command, not an SQL statement, so it cannot be used in a procedure either.
My suggestion is to use \copy, but to forget about the procedure.

How do you trigger a script from inside an if statement in PostgreSQL?

I want to run some sql scripts if a specific schema exists. This is my attempt:
do $$
begin
if exists (select 1 from information_schema.schemata where schema_name = 'public')
then
\ir ./script.sql
end if;
end
$$;
But I get this error:
$ psql my_database -f test.sql
psql:test.sql:8: ERROR: syntax error at or near "\"
LINE 5: \ir ./script.sql
The same script without the if statement works and is able to trigger ./script.sql.
Adding the code from script.sql directly in the if statement also works, there doesn't seem to be anything wrong with the if syntax.
How can you conditionally trigger SQL scripts?
You cannot do that in PL/pgSQL.
You could write a function in PL/PerlU or PL/Python that does that, or you can install the PL/sh language.

PostgreSQL, plpython3u function. os.getenv does not find the envinronment variable

I get the below situation with PostgreSQL plpython3u function.
I've recently added a envinronment variable to my shell startup file. The env | grep MY_VAR command returns MY_VAR=/path/. But when I run a select * from my_func(); query from a psql command line, the function says that the envinronment variable is None.
create or replace function my_func()
returns int as
$$
import os
for k, v in os.environ.items():
plpy.info(k + ':' + v)
MY_VAR = os.getenv('MY_VAR')
if MY_VAR is None:
plpy.info('was not found')
return -1
plpy.info('MY_VAR:' + MY_VAR)
return 0
$$ language 'plpython3u';
returns int AS
The for k, v in os.environ.items(): ... prints all variables except the one I search for. The MY_VAR gets missed somehow.
Please advice. Why did the function can't find MY_VAR?
Update
The \! env command in psql command prompt also lists MY_VAR
As it turned out, the PostgreSQL server only reads envinronment variables once, upon the main server process start. I had to restart the server to get access to full envinronment varaibles list.

PostgreSQL PL/PerlU trigger issue

I'm trying to create a PostgreSQL trigger on Linux written in Perl which should execute code based on external libraries. The SQL script containing the trigger looks like this:
CREATE OR REPLACE FUNCTION notify_mytable_update() RETURNS trigger AS $$
use lib "full_path_to_lib_dir";
use MyModule;
return;
$$ LANGUAGE plperlu
SECURITY DEFINER
SET search_path = myschema, public, pg_temp;
DROP TRIGGER IF EXISTS notify_mytable_update ON mytable;
CREATE TRIGGER notify_mytable_update AFTER UPDATE ON mytable
FOR EACH ROW
EXECUTE PROCEDURE notify_mytable_update();
The issue with this is that whenever I try to this script with psql I get a permission denied error in the Perl code for accessing MyModule. Giving full access to my home directory to postgres didn't help.
Thank you in advance!
Don't forget that to have access to a file, you not only need permissions to the file and the directory where it resides, but also to all directories in the path.
So if your module is /home/george/MyModule.pm, you need access to / and /home in addition to /home/george and the file itself.
You'll have to give these permissions to the operating system user running the PostgreSQL server process, commonly postgres.

psql function written in separate file

i'm learning psql in Postgres.
My basic question is when i create a function like this one :
CREATE OR REPLACE FUNCTION totalRecords ()
RETURNS integer AS $total$
declare
total integer;
BEGIN
SELECT count(*) into total FROM COMPANY;
RETURN total;
END;
$total$ LANGUAGE plpgsql;
i must write all of the code in the prompt command line.
How can i save this code in a script and call it from the command line ? the extentsion of the scirpt must be a .sql ? how can i call this script.
Save your script to a file. Then execute like this:
psql -p portnumber -d database -U user -f mysqlscrpt.sql
The extension of the script does not matter.
#jkdba's answer is sufficient but, alternatively, if you are already logged in the psql console, you can use:
\i <sqlscript>.sql
The \i being for input. \o is output, and it would write to the file instead of bringing it in.
I mention this because this is what made me remember the command :)