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.
Related
Working on Amazon Redshift stored procedure. Having issue in while loop syntax error near "integer"
create or replace procedure WHILE_COM(REC_COUNT INT)
AS $$
DECLARE
I INTEGER =1
SET REC_COUNT=SELECT COUNT(*) FROM table
BEGIN
WHILE I<=REC_COUNT LOOP
WITH FIRST_RECORD AS
(SELECT * FROM ods_epremis.new_old_merge
where new_old_merge.claim_oid IN(select TOP 1 claim_oid from ods_epremis.new_old_merge order by clain_oid)),
MERGE_RECORD AS
(SELECT * from ode_epremis.new_old_merge JOIN FIRST_RECORD
ON T1_accountno=T2_accountno)
insert into targettable (select * from MERGE_RECORD)
I=I+1
END LOOP
END
$$ LANGUANGE plpgsql;
Based on the examples from Structure of PL/pgSQL - Amazon Redshift, variables should be set with := rather than just =:
CREATE PROCEDURE update_value() AS $$
DECLARE
value integer := 20;
BEGIN
...
It also shows colons (;) at the end of commands.
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 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".;
I'm creating a procedure on db2 that will insert values into a table only if the table is empty. I've created the following statements, but something is wrong since I'm getting error:
[42601][-104] An unexpected token "END-OF-STATEMENT" was found
following "END FOR".
Expected tokens may include: " END IF".. SQLCODE=-104, SQLSTATE=42601,
DRIVER=4.7.85
create or REPLACE PROCEDURE proc1
BEGIN
IF (exists (select 1 from table1)) then
TRUNCATE TABLE table1;
ELSE
FOR l1 as
select id, max(bla) as bla from table2 group by id
do
insert into table1 (column1, column2)
values (id, bla);
END FOR;
END IF;
END;
thanks!
Apparently, this little change helped to solve the problem:
create or REPLACE PROCEDURE proc1
BEGIN
IF (exists (select 1 from table1)) then
DELETE FROM TABLE table1;
END IF;
FOR l1 as
select id, max(bla) as bla from table2 group by id
do
insert into table1 (column1, column2)
values (id, bla);
END FOR;
END;
why you dont do just this
create or REPLACE PROCEDURE proc1
BEGIN
DELETE FROM table1;
insert into table1 (column1, column2)
select id, max(bla) from table2 group by id;
END;