Postgresql 11 - Create Procedure to Execute COPY function - sql

I'm currently trying to create a procedure to automatically copy data into my database when I call the procedure. However, every time I call it I get the following error:
ERROR: column "name" does not exist
LINE 1: SELECT format('COPY test(%L) FROM %s CSV HEADER', name, '/Us...
How does the column not exist? Here's everything I've written out:
CREATE PROCEDURE
test_insert() AS
$$
BEGIN
EXECUTE format('COPY test(%L) FROM %s CSV HEADER', name, '/Users/Receiving.csv');
END;
$$ LANGUAGE plpgsql;

If you use name without single quotes, it is interpreted as a column name in the (tacit) SELECT statement
SELECT format('...', name, '...')
that PL/pgSQL runs when you execute your function.
Since this SELECT statement does not have a FROM clause, you get the observed error.
The solution is to use a string literal instead, i.e. write 'name' instead of 'name'.

Related

Procedure (unknown) does not exist PostgreSQL

I'm new to PostgreSQL, and trying to learn about stored procedure with PostgreSQL. Here are the steps I followed.
Installed pgAdmin4
Created the Database
Created the table "Users" under public schema
Created the procedure "GetUserByEmail"
CREATE OR REPLACE PROCEDURE GetUserByEmail
(
Email Varchar(100)
)
LANGUAGE plpgsql AS
$$
BEGIN
Select * from public."Users" where "Email" = Email
END
$$;
When calling it from query tool, I get an error.
CALL public.GetUserByEmail('d#d.com')
ERROR: procedure public.getuserbyemail(unknown) does not exist LINE
1: CALL public.GetUserByEmail('d#d.com')
^ HINT: No procedure matches the given name and argument types. You might need to add explicit type casts. SQL state: 42883
Character: 6
Checked the permission, and the user has execution rights.
Tried different ways but not sure what is wrong.
Are PostgreSQL column names case-sensitive?
if you create table "users"(a int...) then you stick with "users" every time you select/update/delete "users" table.
You can easily imitate 38.5.9. SQL Functions Returning Sets(https://www.postgresql.org/docs/current/xfunc-sql.html)
CREATE FUNCTION getusers(text) RETURNS SETOF "users" AS $$
SELECT * FROM "users" WHERE email = $1;
$$ LANGUAGE SQL;
SELECT * FROM getusers('hi') AS t1;
stored procedure versus function
demo

Accessing parameters in a SQL stored Procedure in Snowflake

I am trying to create a stored procedure that uses an integer parameter and dateadd() to create a timestamp that's used to filter results in a where clause. I am getting "Uncaught exception of type 'STATEMENT_ERROR' on line 3 at position 2 : SQL compilation error: error line 9 at position 53 invalid identifier 'X_DAYS_BACK'" when I try to run the procedure below. If I move the return line above the create table line the procedure successfully runs and the return string includes the actual value of x_days_back (e.g. base.ITEM updated for last 3 days.).
CREATE OR REPLACE PROCEDURE BASE.ITEM_LOAD_test(X_DAYS_BACK INTEGER)
returns string not null
language SQL
as
$$
BEGIN
CREATE OR REPLACE TEMPORARY TABLE BASE.TEMP_DELTA_ITEM (
ID STRING
)
AS
SELECT
SOURCE||KEY AS ID
FROM BASE.SUPPLIER_CATALOG_ITEM
WHERE
CDP__ETL_UPDATE_TIMESTAMP >= DATEADD(Day ,-1*X_DAYS_BACK, CURRENT_DATE);
drop TABLE BASE.TEMP_DELTA_ITEM;
RETURN 'base.ITEM updated for last ' || X_DAYS_BACK || ' days.' ;
END;
$$
How do I access a parameter of a SQL stored procedure within a function such as dateadd? I know it's a preview feature, so is this not currently implemented or?
Toss a colon in front of the variable/parameter:
DATEADD(day, -1*:X_DAYS_BACK, CURRENT_DATE);
Their documentation isn't amazing for SQL stored procedures but there is mention of this here where it states:
You can use a variable in a SQL statement. (This is sometimes referred to as binding a variable.) Prefix the variable name with a colon.

Column '' has unsupported type "information_schema.sql_identifier"

I am trying to test my stored procedure in MySQL workbench/j. I get an error when I am trying to call the stored procedure.
I have created a table to store the result of my stored procedure
CREATE TABLE IF NOT EXISTS ableok
(
name VARCHAR(50) ENCODE lzo
);
This is my stored procedure:
CREATE OR REPLACE PROCEDURE sp_GetDistSchema()
AS '
BEGIN
SELECT table_schema INTO ableok FROM information_schema.tables;
END;
'
LANGUAGE plpgsql;
This is how i call my stored procedure in SQL workbench/j:
call sp_getdistschema();
Result:
An error occurred when executing the SQL command:
call sp_getdistschema()
[Amazon](500310) Invalid operation: Column "table_schema" has unsupported type "information_schema.sql_identifier".; [SQL State=0A000, DB Errorcode=500310]
1 statement failed.
The SELECT ... INTO structure is used to store a query result into variables. It looks as though you are really just trying to populate the distTable directly. Try this instead:
Update: When processing the information schema in Redshift/PostgreSQL, you apparently need to convert the column datatypes using CAST:
CREATE OR REPLACE PROCEDURE sp_GetDistSchema()
BEGIN
INSERT INTO distTable SELECT DISTINCT CAST(table_schema AS VARCHAR) FROM information_schema.tables;
END;
As #user9601310 mentioned (up voted), you need to CAST the column data types.
I was scratching my head too, even in plain old Postgres when your using the information_schema.
This will 'describe' a table or a view, but won't work unless the query columns are cast as VARCHAR:
CREATE OR REPLACE FUNCTION public.fn_desc(p_tablename VARCHAR)
RETURNS TABLE(vtable_name VARCHAR, vcolumn_name VARCHAR, vdata_type VARCHAR)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT
table_name::VARCHAR,
column_name::VARCHAR,
data_type::VARCHAR
FROM
information_schema.columns
WHERE
table_name ILIKE p_tablename;
END;
$function$
SELECT * FROM public.fn_desc('any_table_or_view');

Postgres run SQL statement from string

I would like to execute a SQL statement based on a string. I have created the SQL statement through a function which returns a string. Can anybody explain how I can execute the statement that is returned? I know that you can't do it in plain SQL, so I was thinking about putting it in a function. The only issue is that the columns in the statement aren't always the same, so I don't know which data types to use for the columns. I'm using Postgres 9.1.0.
For example, suppose the SQL string returned from my function the is:
Select open, closed, discarded from abc
But, it can also be:
Select open from abc
Or
Select open, closed from abc
How can I execute any of these strings, so that the results would be returned as a table with only the columns listed in the statement?
Edit: the function is written in PL/pgSQL. And the results will be used for reporting where they don't want to see columns that have no values. So the function that I wrote returns the names of all columns that have values and then add it to the SQL statement.
Thanks for your help!
I don't think you can return the rows directly from a function, because its return type would be unknown. Even if you specified the return type as RECORD, you'd have to list the returned columns at call time. Based on Wayne Conrad's idea, you could do this:
CREATE FUNCTION my_create(cmd TEXT) RETURNS VOID AS $$
BEGIN
EXECUTE 'CREATE TEMPORARY TABLE temp_result AS ' || cmd;
END;
$$ VOLATILE LANGUAGE plpgsql;
Then use the function like this:
BEGIN;
SELECT my_create(...);
SELECT * FROM temp_result;
ROLLBACK; -- or COMMIT

Problem with PostgreSQL function parameters (Converting MySQL Stored Procedures)

I am converting a few simple MySQL stored procedures to PostgreSQL Functions and for some reason when I execute the following function it throws an error when executed.
I created the function with the following code:
CREATE FUNCTION cc.fs_ivr_updatecalltransfer(_ParentContactID
int[11], _CalledID varchar[32])
RETURNS int AS $$
DECLARE
pcID int;
BEGIN
if _ParentContactID<>0 then
update cc.tblcontacts set cc.tblcontacts.transferdest =
_CalledID where cc.tblcontacts.contactid =
_ParentContactID;
end if;
RETURN _ParentContactID;
END;
$$ LANGUAGE plpgsql;
I Execute it manually like this:
SELECT cc.fs_ivr_updatecalltransfer(3,"test")
It throws this error:
SQL error:
ERROR: column "test" does not exist
LINE 1: SELECT cc.fs_ivr_updatecalltransfer(3,"test")
In statement: SELECT cc.fs_ivr_updatecalltransfer(3,"test")
Any Suggestions?
Use single quotes to quote strings, not double quotes. 'test' means the string "test", whereas "test" means the identifier "test", which postgresql tries to resolve as a column, same as using backquotes in MySQL.