I have created a stored procedure that returns the distinct table_schema name. My database is using redshift and I am using SQL workbench/J to create it.
As recommended by AMAZON Redshift, we can use a cursor to return the result set. Below is my code.
CREATE OR REPLACE PROCEDURE get_dist_schema(rsout INOUT refcursor)
AS $$
BEGIN
OPEN rsout FOR SELECT DISTINCT table_schema FROM information_schema.tables;
END;
$$ LANGUAGE plpgsql;
BEGIN;
CALL get_dist_schema('sname');
FETCH ALL FROM sname;
commit;
Result from FETCH ALL FROM sname is as shown below:
table_schema
tableA
tableB
tableC
tableD
I want to save the result in a table such that when I do select statement for a table, the same result will appear.
I have tried this:
BEGIN;
CALL get_dist_schema('sname');
FETCH ALL FROM sname INTO public.distTable
The error say:
Invalid operation: syntax error at or near "INTO"
Position: 22;
Is there any way I can save the result into a table?
FETCH ALL FROM sname INTO public.distTable
UPDATE:
IF I USE SELECT INTO:
CREATE OR REPLACE PROCEDURE get_dist_schema(rsout INOUT refcursor)
AS $$
BEGIN
OPEN rsout FOR SELECT DISTINCT table_schema INTO public.distTable FROM information_schema.tables;
END;
$$ LANGUAGE plpgsql;
ERROR:
CALL get_dist_schema('sname')
[Amazon](500310) Invalid operation: Column "table_schema" has unsupported type "information_schema.sql_identifier".;
Related
I would like to do a very simple pl/sql transaction with loop and for to insert values into a table. It should work like this:
CREATE PROCEDURE cs_refresh_reports() AS $$
DECLARE
last_nps RECORD;
BEGIN
FOR last_nps IN SELECT "date" FROM table_1 ;
LOOP
EXECUTE insert into table_2 ("value") select "value" from table_3 where "date" = :last_nps ;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
Very simple but I didn't find any solution for this and if I try I just get errors.
While creating the store procedure to create the table in redshift, I am not able to create the table by concatenating with current date. could please help me anyone.
Here is my code :
create or replace procedure stud.studentlists()
as $$
declare get_date date;
begin
execute 'CREATE TEMP TABLE stud.students_list_||"get_date"
as
select * from stud.students_list;
'
end
$$ LANGUAGE plpgsql;
I am trying to convert a column that has mixed date formats - 2017/12/10, 2018-02-27, 8/18/2017 to YYYY-MM-DD format through a Snowflake stored procedure. When executing through CALL statement, the order in which it executes the case statement doesn't seem to be consistent.
TableA:
CREATE TABLE TABLE_A
(
START_DATE VARCHAR,
END_DATE VARCHAR,
RECORDED_DATE VARCHAR);
INSERT INTO TABLE_A VALUES ('2021-11-09', '2021-11-09','2018/03/29');
INSERT INTO TABLE_A VALUES ('2021-11-09', '2021-11-09','2018-02-27');
INSERT INTO TABLE_A VALUES ('2021-11-09', '2021-11-09','8/18/2017');
Stored procedure:
CREATE OR REPLACE PROCEDURE LOAD_TABLE_B(LD VARCHAR)
RETURNS STRING
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
var insert_command =`INSERT INTO TABLE_B
SELECT START_DATE
,END_DATE
,CASE WHEN RECORDED_DATE RLIKE '\\d{4}/\\d{2}/\\d{2}' THEN TO_DATE(RECORDED_DATE, 'YYYY/MM/DD')
ELSE TO_DATE(RECORDED_DATE)
END AS RECORDED_DATE
,HASH(S.$1,S.$2,S.$3) AS CHECKSUM_HASH
FROM TABLE_A S;
`;
try {
snowflake.execute({sqlText:insert_command});
return "Success";
}
catch (err) {
throw err;
}
$$ ;
CALL LOAD_TABLE_B(1);
Error message:
Execution error in store procedure LOAD_TABLE_B: Date '2018/03/29' is not recognized At Snowflake.execute, line 18 position 11
Because you're running this in a stored procedure. The query itself has an extra round of parsing and character escaping before it is executed. meaning you need extra backslashes. The syntax gets borderline silly, but this is what you need.
var insert_command =`CREATE OR REPLACE TABLE TABLE_B AS
SELECT START_DATE
,END_DATE
,CASE WHEN RECORDED_DATE RLIKE '\\\\d{4}/\\\\d{2}/\\\\d{2}' THEN TO_DATE(RECORDED_DATE, 'YYYY/MM/DD')
ELSE TO_DATE(RECORDED_DATE)
END AS RECORDED_DATE
,HASH(S.$1,S.$2,S.$3) AS CHECKSUM_HASH
FROM TABLE_A S;
`;
another solution instead of using RLIKE in a CASE is to just nest the TRY_TO_DATE formats in a COALESCE
COALESCE(TRY_TO_DATE(recorded_date), TRY_TO_DATE(recorded_date, 'YYYY/MM/DD')) AS RECORDED_DATEAS recorded_date
I have created below procedure in AWS redshift.
In the query2 (at ????) I want to select the column from rec based on value provided in field input variable.
e.g. if field = 'Fname' then in query2 it should insert rec.Fname.
Please let me know how to select column names dynamically from RECORD in open cursor.
CREATE OR REPLACE PROCEDURE test3(source_table varchar(100), target_table varchar(100), field varchar(100) )
LANGUAGE plpgsql
AS $$
declare
query1 text;
query2 text;
rec RECORD;
begin
query1 := 'SELECT id, ' || field ||', load_date, end_date FROM ' || source_table || ' ORDER BY id, load_date';
FOR rec IN execute query1
loop
query2 := 'insert into '|| target_table ||' values ('||quote_literal(rec.id)||', '||quote_literal(field)||','||**????**||','||quote_literal(rec.load_date)||')';
execute query2;
END LOOP;
RETURN;
END;
$$
;
It is early here so let me just reference an answer I gave for a similar situation (inserting instead of selecting). This should get you started - How to join System tables or Information Schema tables with User defined tables in Redshift
The code looks like:
CREATE OR REPLACE procedure rewrite_data()
AS
$$
DECLARE
row record;
BEGIN
drop table if exists fred;
create table fred (schemaname varchar(256),tablename varchar(256),"column"varchar(256), "type"varchar(256));
for row in select "schemaname"::text, "tablename"::text, "column"::text, "type"::text from pg_table_def where "schemaname" <> 'pg_catalog' LOOP
INSERT INTO fred(schemaname,tablename,"column","type") VALUES (row.schemaname,row.tablename,row."column",row."type");
END LOOP;
END;
$$ LANGUAGE plpgsql;
call rewrite_data();
select * from fred;
Given that you have gotten this far on your stored procedure this should get you over the finish line.
I am writing a stored procedure which does involving using information schema in AWS Redshift.
VARIABLES FOR ALL THE Below -
Using same user
Using same Redshift database (endpoint)
Stored procedure:
create or replace procedure dev.gp_information_schema_test
(tablename varchar(64))
as $$
declare
table_name varchar(64);
schema_name varchar(64);
counts int;
begin
table_name := split_part(tablename,'.',1);
schema_name:= split_part(tablename,'.',2);
raise info 'table_name - %,Schema_name - %',table_name,schema_name;
counts := (select count(*) from information_schema.tables where table_schema = schema_name);
raise info 'count is -%',counts;
end;
$$
language plpgsql
call dev.gp_information_schema_test('dev.abc');
Result :
Warnings:
table_name - dev,Schema_name - abc
count is -0
0 rows affected
call executed successfully
Execution time: 0.55s
But if I run the same query outside (i.e not via stored procedure), then:
select count(*)
from information_schema.tables
where table_schema = 'dev'
Results:
I have already read the limitations of stored procedure in the AWS documentation (Link), but there is no mention of access restriction to system tables.
You can't set the value of a variable from a query using :=. Instead you need to use the SELECT INTO variable form. https://docs.aws.amazon.com/redshift/latest/dg/c_PLpgSQL-structure.html
Try this SP:
CREATE OR REPLACE PROCEDURE gp_information_schema_test(tablename VARCHAR(64)) AS
$$
DECLARE
table_name VARCHAR(64);
schema_name VARCHAR(64);
counts INT;
BEGIN
schema_name := split_part(tablename, '.', 1);
table_name := split_part(tablename, '.', 2);
RAISE INFO 'table_name - % , Schema_name - %',table_name,schema_name;
counts := (SELECT count(*) FROM information_schema.tables WHERE table_schema = schema_name);
RAISE INFO 'Tables in schema: %',counts;
END;
$$ LANGUAGE plpgsql;
Call:
CALL gp_information_schema_test('dev.abc');