I am new to snowflake and SQL scripting. I am trying to achieve a logic to execute commands in IF statement block when a variable condition is true using Snowflake, i went to the documentation but eventually i am doing mistakes in writing code. Can you please help me in correcting it.
//Step 1:
//Declare variable
declare
CNT NUMBER;
//Step 2:
//Assigning Value to variable
begin
CNT := (Select count(*) from CLOUDMED_AI.DATAWAREHOUSE_INTEGRATION_ADMIN.SYNAPSE_TO_SNOWFLAKE_CONTROL );
//Step 3:
//Using Variable in IF statement
IF (CNT < 100)
then
Select top 10 * from CLOUDMED_AI.DATAWAREHOUSE_INTEGRATION_ADMIN.SYNAPSE_TO_SNOWFLAKE_CONTROL
end IF;
end;
But the above lines for me is throwing issues.
Here is an example that works. Different table names, but you should be able to follow the structure.
execute immediate $$
declare
RECORD_COUNT NUMBER;
output RESULTSET;
begin
SELECT COUNT(*) INTO :RECORD_COUNT FROM INFORMATION_SCHEMA.TABLES;
IF (RECORD_COUNT<100) THEN
output:=(SELECT TOP 10 * FROM INFORMATION_SCHEMA.TABLES);
END IF;
RETURN TABLE(output);
end;
$$
;
I´m new in programming with plpgsql and stored functions in postgresql.
I´ve programmed one function called this:
CREATE OR REPLACE FUNCTION public.uploadbutton(VARIADIC arr character varying[])
RETURNS text
LANGUAGE plpgsql
AS $function$DECLARE
arrayi ALIAS for $1;
result text;
begin
return result;
END;
$function$
;
As you can see, the function does not have many code. The problem is that i don´t really understand how to handle Arrays in Postgresql and plpgsql.
I need to split the array every 3 delimeters until the end of array, the array can have many inputs but minimum 3.
SELECT uploadbutton('59373033336415021231','5','a','59373033335915022fff','5','b')
Here an example for calling it.
The output should look like that:
('59373033336415021231','5','a')('59373033336415021231','5','a')
Can you teach me, how to handle that ?
Kind regards guys!
EDIT:
After getting this Result :
('59373033336415021231','5','a')('59373033336415021231','5','a')
I need to put every 3 parameters, and call a second function with the first part of the result as parameters. And the second Value have to be Int. This should look like this:
edit('59373033336415021231',5,'a')
and the same for the second part of the result
edit('59373033336415021231',5,'a')
I´m trying it at the moment and want to get the id of the first parameter with my edit() function. This is what i have:
CREATE OR REPLACE FUNCTION public.upload(string_in text)
RETURNS integer
LANGUAGE plpgsql
AS $function$DECLARE
string_in ALIAS FOR $1;
id integer;
begin
id= (select id from public.buttons where fbisn =
split_part(string_in,',',1));
return val;
end;
$function$
;
string_in is everytime the for clause of the first function is completed, the result string of that. This function will be called every time.
But currently, i will get no result.
Thanks for your help
Maybe a FOR LOOP using BY 3 is what you're struggling with
CREATE OR REPLACE FUNCTION public.uploadbutton(VARIADIC arr TEXT[])
RETURNS TEXT LANGUAGE plpgsql AS $$
DECLARE result TEXT DEFAULT '';
BEGIN
FOR i IN 1..array_length($1,1) BY 3 LOOP
result := result || '(' || array_to_string($1[i:i+2],',') || ')';
END LOOP;
RETURN result;
END;
$$;
Testing
SELECT uploadbutton(VARIADIC '{"59373033336415021231","5","a","59373033335915022fff","5","b"}'::text[]);
uploadbutton
------------------------------------------------------
(59373033336415021231,5,a)(59373033335915022fff,5,b)
(1 Zeile)
If you need the quotation marks ' in every element, just change the concatenation of the result variable accordingly:
result := result || E'(\'' || array_to_string($1[i:i+2],E'\',\'') || E'\')';
Edit: see comments
CREATE OR REPLACE FUNCTION public.uploadbutton(VARIADIC arr TEXT[])
RETURNS VOID LANGUAGE plpgsql AS $$
DECLARE slice TEXT[];
BEGIN
FOR i IN 1..array_length($1,1) BY 3 LOOP
slice := $1[i:i+2];
PERFORM edit(slice[1]::TEXT,slice[2]::INT,slice[3]::TEXT);
END LOOP;
END;
$$;
My answer may look ugly, but it works. You can optimize it if you want.
CREATE OR REPLACE FUNCTION uploadbutton(arr character varying[])
RETURNS text AS $$
DECLARE
arr_data character varying[] := arr;
array_len integer;
ar_data text;
incr INTEGER := 1;
result_data TEXT;
start_scope text := '(';
end_scope text := ')';
ins_incr integer := 1;
next_val text := '';
BEGIN
array_len := (select array_length(arr_data,1));
WHILE incr <= array_len LOOP
ar_data := CONCAT('''',arr_data[incr],'''');
IF (result_data IS NULL) THEN
result_data := CONCAT(result_data,'',ar_data);
ELSE
result_data := CONCAT(result_data,',',ar_data);
END IF;
ins_incr := ins_incr + 1;
IF (ins_incr = 4) THEN
result_data := CONCAT(start_scope,result_data,end_scope);
next_val := CONCAT(next_val,result_data);
result_data := NULL;
ins_incr := 1;
END IF;
incr := incr + 1;
END LOOP;
RETURN CONCAT(next_val,'(',result_data,')');
END $$
LANGUAGE plpgsql;
Sample:
SELECT uploadbutton(array ['59373033336415021231','5','a','59373033335915022fff','5','b','59373033335915022CCC','6','C','59373033335915022KKK','77','KK'])
I'm unable to find where the issue is for the below program. the values of the custom type are displaying without any errors when I use RAISE NOTICE statements at the end. When I run the final select statement, the error is Array value must start with "{" or dimension information. Please help me with the select statement on how to call the package/function.
create
or
replace TYPE t_col_foo as object
(
ID NUMBER
, CLUSTERNAME VARCHAR2(300)
, "1200AM" varchar2(10));
create
or
replace TYPE T_COL_R AS TABLE OF t_col_foo;
CREATE OR REPLACE PACKAGE foo_avail_pkg
IS
FUNCTION foo_slots
(
p_ref_data anyarray
)
RETURN t_col_r[];
END foo_avail_pkg;
CREATE OR REPLACE PACKAGE BODY foo_avail_pkg
IS
FUNCTION foo_slots
(
p_ref_data anyarray
)
RETURN t_col_r[]
IS
-- declare
r_target_data t_col_foo:=t_col_foo(null,null,null);
r_target_data_1 t_col_foo;
r_source_data text[];
t_return t_col_tab1;
BEGIN
t_return:=t_col_tab1();
select
array
(
select
unnest( p_ref_data )
)
into r_source_data
;
-- r_target_data = '{}';
for i in coalesce(array_lower(r_source_data,1),0) .. coalesce(array_upper(r_source_data,1),0)
LOOP
r_target_data.ID := substr(r_source_data[i],1,instr(r_source_data[i],',',1,1)-1);
r_target_data.CLUSTERNAME := substr(r_source_data[i],length(r_target_data.ID)+2,(instr(r_source_data[i],',',length(r_target_data.ID)+1,2) - instr(r_source_data[i],',',1,1))-1);
r_target_data."1200AM" := 3;
r_target_data_1 :=row(r_target_data.ID ,r_target_data.CLUSTERNAME,r_target_data."1200AM") :: t_col_foo;
END LOOP;
-- dbms_output.put_line(r_target_data_1);
RETURN r_target_data_1;
end;
END foo_avail_pkg;
This is how I have to call
select * from foo_avail_pkg.foo_SLOTS(array
(
select
ID
||','
||CLUSTER_NAME
||','
||LOB
from
y limit 1
));
And the error is
ERROR: malformed array literal: "(1398,Sanity20feb,3)"
DETAIL: Array value must start with "{" or dimension information.
I am trying to build a declared array from all the dogs that share the same family_id and query the dog_characteristics table using the array.
CREATE OR REPLACE FUNCTION update_dog_characteristics_guarantor_id()
RETURNS trigger AS $$
DECLARE dog_ids INT[];
BEGIN
SELECT id into dog_ids FROM dogs WHERE dogs.family_id = OLD.id;
IF ((OLD.family_id IS NOT NULL) && ((SELECT COUNT(*) FROM dog_ids) > 0)) THEN
UPDATE
dog_characteristics
SET
guarantor_id = NEW.guarantor_id
WHERE
dog_characteristics.account_id = OLD.account_id
AND dog_characteristics.dog_id IN ANY(dog_ids);
RETURN NULL;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
What I have tried
AND dog_characteristics.dog_id = ANY(dog_ids);
AND dog_characteristics.dog_id = ANY(dog_ids::int[]);
AND dog_characteristics.dog_id IN (dog_ids::int[]);
AND dog_characteristics.dog_id IN (dog_ids);
AND dog_characteristics.dog_id IN (ARRAY(dog_ids));
AND dog_characteristics.dog_id IN ARRAY(dog_ids);
AND dog_characteristics.dog_id IN implode( ',', dog_ids);
Most common error
ERROR: malformed array literal: "672"
DETAIL: Array value must start with "{" or dimension information.
CONTEXT: PL/pgSQL function update_dog_characteristics_guarantor_id() line 5 at SQL statement
There are multiple errors in your trigger function.
As dog_ids is declared as an array, the result of the first select has to be an array as well. To do that, you need to aggregate all IDs that are returned from the query.
So the first select statement should be
select array_agg(id) --<< aggregate all IDs into an array
into dog_ids
FROM dogs
WHERE dogs.family_id = OLD.id;
To check if an array has elements, you can't use select count(*), you need to use use array_length() or cardinality().
The && is not the "AND" operator in SQL - that's AND - so the if should be:
IF OLD.family_id IS NOT NULL AND cardinality(dog_ids) > 0 THEN
...
END IF;
The where condition on the array should be:
AND dog_characteristics.dog_id = ANY(dog_ids);
I'm kinda new into pgplsql and so far I have to create a function that loops an array that is received as a function.
The main idea of the function is to insert new records into a table that maps each id contained in the array received with a new formatted id, the format depends on the second parameter received and return the table "idsTable".
The problem is that when I try to create the function it sends me an error:
ERROR: loop variable of FOREACH must be a known variable or list of variables
LINE 38: FOREACH objectid IN ARRAY idsList LOOP
I'm not sure if I have to declare the objectid variable cause in the examples that I have seen they didn't.
So far I have this:
CREATE OR REPLACE FUNCTION createId(idsList varchar[], objectType varchar)
RETURNS TABLE(original_id varchar, new_id char) as
$$
BEGIN
IF LOWER(objectType) = 'global' THEN
FOREACH objectid IN ARRAY idsList LOOP
INSERT INTO idsTable(original_id, new_id)
VALUES(objectid, 'GID'||nextval('mapSquema.globalid')::TEXT);
END LOOP;
ELSE
FOREACH objectid IN ARRAY idsList LOOP
INSERT INTO idsTable(original_id, new_id)
VALUES(objectid, 'ORG'||nextval('mapSquema.globalid')::TEXT);
END LOOP;
END IF;
END;
$$ LANGUAGE plpgsql;
Any ideas of what could be wrong?
edit: I haven't add the part where the idsTable is returned.
Unrelated, but: you don't really need a loop for that. And you can simplify the function by only writing the INSERT once. You also forgot to return something from your function. As it is declared as returns table that is required:
CREATE OR REPLACE FUNCTION createid(idslist varchar[], objecttype varchar)
RETURNS TABLE(original_id varchar, new_id varchar) as
$$
declare
l_prefix text;
BEGIN
IF LOWER(objectType) = 'global' THEN
l_prefix := 'GID';
ELSE
l_prefix := 'ORG';
END IF;
RETURN QUERY --<< return the result of the insert
INSERT INTO idstable(original_id, new_id)
select t.x, l_prefix||nextval('mapSquema.globalid')::TEXT
from unnest(idslist) as t(x)
returning *
END;
$$ LANGUAGE plpgsql;