Creating stored procedure in redshift - sql

When creating stored procedure in redshift like below:
CREATE OR REPLACE PROCEDURE sp_test()
AS '
BEGIN
TRUNCATE TABLE TABLE_1;
INSERT INTO TABLE_1
SELECT COL1, COL2
FROM TABLE_2
WHERE CONDITION='SAMPLE';
END;
'
LANGUAGE plpgsql;
This gives an error syntax error near 'SAMPLE' because single quotes is already used for stored procedure begin and end. Also, here we would not be able to replace single quotes in INSERT query to double because redshift will consider it to be a column.
Few other posts suggests to use $$ for stored procedure, however $$ is not supported in sql workbench.
Any work around for this. Thanks.

Have you tried double-quoting the string?
WHERE CONDITION=''SAMPLE'';
Data Sample
CREATE TABLE t (id int, status text);
INSERT INTO t VALUES (42,'foo');
Procedure
CREATE OR REPLACE PROCEDURE sp_test()
AS'
BEGIN
TRUNCATE TABLE t;
INSERT INTO t
SELECT 8,''new record'';
END;'
LANGUAGE plpgsql;
Test procedure
CALL sp_test();
SELECT * FROM t
id | status
----+------------
8 | new record
(1 Zeile)

Related

only one AS items needed for language "plpgsql";

I am trying to run a copy command inside a stored procedure.
This copy command copies from aws s3 to a table in aws redshift
This is the copy command
copy schema1_ghsheet.ghseet_temp
from
''''s3://root2/rawfiles/''''
iam_role ''''arn:aws:iam::743:role/redshift''''
csv DELIMITER ',' IGNOREHEADER 1 TRUNCATECOLUMNS;
I am trying to add it into a stored proc, which now looks like this.
here i am trying to create a temp table which contains all the data from s3, which is being copied to temp table using a copy command.
CREATE OR REPLACE PROCEDURE proc_test() LANGUAGE plpgsql
AS
'
BEGIN
drop table if exists
schema1_ghsheet.ghseet_temp
;
create table
schema1_ghsheet.ghseet_temp(emp_id int, emp_name varchar(100),hrly_rate int,mod_timestamp timestamp)
;
copy schema1_ghsheet.ghseet_temp
from
''''s3://root2/rawfiles/''''
iam_role ''''arn:aws:iam::743:role/redshift''''
csv DELIMITER ',' IGNOREHEADER 1 TRUNCATECOLUMNS;
drop table if exists
schema1_ghsheet.ghseet_main
;
create table
schema1_ghsheet.ghseet_main
as
select h1.emp_id,h1.emp_name,h1.hrly_rate,h1.mod_timestamp
from schema1_ghsheet.ghseet_hstry h1
inner join (
select emp_id ,emp_name , max(mod_timestamp ) mod_timestamp
from schema1_ghsheet.ghseet_hstry
group by 1,2
) h2
on h1.emp_id=h2.emp_id
and h1.mod_timestamp=h2.mod_timestamp
group by 1,2,3,4
;
END;
'
But this throws the error :
only one AS items needed for language "plpgsql";
So , how to add a copy command inside a stored procedure or do i need to call the copy command separately ?
COPY is an allowed DML statement within a stored procedure.
It looks like the error is referring to the AS keyword. As far as I know, the syntax in the documentation requires the script after AS to be wrapped in $$ and the LANGUAGE plpgsql designation should come after the script body . Example given in the documentation is:
CREATE OR REPLACE PROCEDURE test()
AS $$
BEGIN
SELECT 1 a;
END;
$$
LANGUAGE plpgsql
;
/
so you should change the order of the script like follows (I cannot test this locally at this time)
CREATE OR REPLACE PROCEDURE proc_test()
AS
$$
BEGIN
drop table if exists
schema1_ghsheet.ghseet_temp
;
create table
schema1_ghsheet.ghseet_temp(emp_id int, emp_name varchar(100),hrly_rate int,mod_timestamp timestamp)
;
copy schema1_ghsheet.ghseet_temp
from
''''s3://root2/rawfiles/''''
iam_role ''''arn:aws:iam::743:role/redshift''''
csv DELIMITER ',' IGNOREHEADER 1 TRUNCATECOLUMNS;
drop table if exists
schema1_ghsheet.ghseet_main
;
create table
schema1_ghsheet.ghseet_main
as
select h1.emp_id,h1.emp_name,h1.hrly_rate,h1.mod_timestamp
from schema1_ghsheet.ghseet_hstry h1
inner join (
select emp_id ,emp_name , max(mod_timestamp ) mod_timestamp
from schema1_ghsheet.ghseet_hstry
group by 1,2
) h2
on h1.emp_id=h2.emp_id
and h1.mod_timestamp=h2.mod_timestamp
group by 1,2,3,4
;
END;
$$
LANGUAGE plpgsql;

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');

No data output from stored procedure (Postgresql)

I have a basic stored procedure for a select statement. The select statement by itself works and shows me the data output, but when I try calling it from a stored procedure, it says 'CALL Query returned successfully in 107 msec', but there's no data output. Is there something that I'm missing from my stored procedure?
(I'm also connecting a database on AWS with the basic tier, not sure if that makes a difference. Every other CRUD operation works except for select.)
CREATE PROCEDURE
experiment1()
LANGUAGE SQL
AS $$
SELECT * FROM assignment
$$
A Postgres procedure does not return anything. You can use a function instead, with the return query syntax. This requires enumerating the columns that the query returns. Assuming that your table has two columns, id and val, that would be:
create function experiment()
returns table (id int, val text)
as $$
begin
return query select * from assignment;
end;
$$ language plpgsql;
You can then invoke this set-returning function like so:
select * from experiment();
Demo on DB Fiddle:
create table assignment (id int, val text);
insert into assignment values(1, 'foo'), (2, 'bar');
-- 2 rows affected
create function experiment()
returns table (id int, val text)
as $$
begin
return query select * from assignment;
end;
$$ language plpgsql;
select * from experiment();
id | val
-: | :--
1 | foo
2 | bar

PostgreSQL - Shared temp table between functions

I wnat to know if its possible to share a temporary table between functions that are called in a "main function", like this:
-- some sub function
create or replace function up_sub_function (str text)
returns table (id int, descr text) as $$
begin
return query select * from temp_table where descr like concat('%', str , '%');
end; $$
language plpgsql;
-- main function
create or replace function up_main_function ()
returns table (id int, descr text) as $$
begin
create temporary table temp_table if not exists (
id int,
descr text
);
insert into temp_campaigns select id, descr from test_table;
return query select * from up_sub_function('a');
end; $$
language plpgsql;
BEGIN;
select * from up_main_function();
drop table temp_table;
COMMIT;
If you can show me the correct way to achieve this, I want to be able to populate a temporary table and then filter rows by calling othe functions inside the main function.
Thanks ans happy programming! :)
See the documentation https://www.postgresql.org/docs/current/static/sql-createtable.html
temp tables are valid for the entire session. That is as long as you stay connected to the database.
In your case you only need it during the transaction. So you should create it with ON COMMIT DROP
create temporary table temp_table if not exists (
id int,
descr text
) ON COMMIT DROP;
Once you created the table you can use it within any function in the current transaction.
You do not need the BEGIN to start the transaction. A transaction is automatically started when the outer function is called.
Nested function calls share the same transaction. So they all see the table.

How should i execute and get the result of a query which is stored in a column as a data value

How do I execute a Sybase query which is stored in a column of another Sybase table?
Suppose that "SELECT COLa FROM TABLE_A" is stored in a column called 'command' in a separate table (table_log). I want to find a way that allows me to execute this query and get the answer.
Try:
create table test_table(f1 varchar(64))
insert into test_table values( "select getdate()" )
go
declare #myvar varchar(30)
select #myvar=f1 from test_table
execute(#myvar)
go
Try looking for
execute immediate
I'm not familiar with sybase but in Oracle it would be something like the following:
declare
query varchar2(1000);
begin
select val from saved_query into query;
execute immediate query;
commit;
end;