Postgres to Snowflake - sql

How to change a Postgres code to Snowflake that has the following signs?
$$ and $1?
Example:
CREATE FUNCTION FCT_Name(timestamp without time zone) returns integer
language plpgsql
as
$$
DECLARE
payperiod integer;
year_start_timestamp timestamp;
BEGIN
IF $1 is null then
return null;
END IF;
IF date_part('year', $1 at time zone 'z' at time zone 'us/central')::int < 2019 THEN
...
I tried to replace $1 by timestamp without time zone but didn't work.

Related

Postgres add parameter to interval statement

I am trying to add a parameter inside a postgres function interval statement. Not sure how to add it...
Like follows:
CREATE OR REPLACE FUNCTION test_date(number integer)
RETURNS table (date_value date)
AS
$body$
BEGIN
RETURN QUERY (select (now() + interval '$1 days') ::date as column_value);
END;
$body$
language plpgsql;
I think you want:
RETURN QUERY select (now() + number * interval '1 day') ::date as column_value;
Expression number * interval '1 day') gives you an interval of number days.
You could also use make_interval():
RETURN QUERY select (now() + make_interval(days := number))::date as column_value;
Demo on DB Fiddle
You can add an integer to a date value directly, which adds the number of days. So if you use current_date no casting is needed.
CREATE OR REPLACE FUNCTION test_date(number integer)
RETURNS table (date_value date)
AS
$body$
BEGIN
RETURN QUERY select current_date + number;
END;
$body$
language plpgsql;
But I don't understand why you use a set-returning function for a single value. A scalar SQL function would be better in this case:
CREATE OR REPLACE FUNCTION test_date(number integer)
RETURNS date
AS
$body$
select current_date + number;
$body$
language sql
stable;

datediff function in postgressql

i am new in PostgreSQL i try to create function
this is code
CREATE OR REPLACE FUNCTION diff(date Timestamp) RETURNS void
As
$$
declare
CURRENT_DATE Timestamp;
number numeric;
begin
CURRENT_DATE=(SELECT CURRENT_DATE) ;
number=(SELECT DATE_PART('day', 'date'::Timestamp - 'CURRENT_DATE'::Timestamp));
end
$$ LANGUAGE plpgsql;
select diff('2020-08-18');
when i select diff it error = invalid input syntax for type timestamp: "date"
If you want to write a wrapper around the - operator for dates that always subtracts the passed date from the current date, you will need to change your function to return a result, e.g. returns integer.
A PL/pgSQL function also needs a return statement to actually return a value.
current_date is a built-in function, you can not use it as a variable name - and the assignment of current_date to itself makes not sense to begin with. Just use current_date wherever you need it without (re)declaring it as a variable or assigning a value to it.
As documented in the manual subtracting a date value from another date value yields the difference in days. There is no need to use date_part() to get that (and you can't use date_part() on an integer to begin with).
You also don't need PL/pgSQL for wrapping a simple expression like that into a function:
Without knowing more details, it seems you are looking for this:
create function diff(p_input date)
returns integer
as
$$
select p_input - current_date;
$$
language sql;
The equivalent implementation in PL/pgSQL using an (not needed) intermediate variable to store the result would look like this:
create function diff(p_input date)
returns integer
as
$$
declare
l_result integer;
begin
l_result := p_input - current_date;
return l_result;
end;
$$
language plpgsql;
Then you can use it like this:
select diff(date '2020-08-18');

postgresql: pass variable to sql query

I'm trying to pass a variable to a select statement using PostgreSQL. The overall goal is to use this logic in a stored procedure where the variable deadline_interval would be an input parameter. Here's what I've tried so far:
DO
$$
DECLARE
date_deadline date;
deadline_interval varchar := '6 month';
BEGIN
date_deadline := (SELECT CURRENT_DATE - INTERVAL deadline_interval);
RAISE NOTICE 'here: %', date_deadline;
END;
$$
Unfortunately the variable deadline_interval is undefined in the select statement. What am I doing wrong here?
Use a cast instead of the prefix.
...
date_deadline := (SELECT CURRENT_DATE - deadline_interval::interval);
...
Or, even better, use interval as type for deadline_interval from the beginning.
DO
$$
DECLARE
date_deadline date;
deadline_interval interval := INTERVAL '6 month';
BEGIN
date_deadline := (SELECT CURRENT_DATE - deadline_interval);
RAISE NOTICE 'here: %', date_deadline;
END;
$$

Fetch cursor in plpgsql

After reading this link http://microjet.ath.cx/WebWiki/ResultPaginationWithPostgresql.html, I decided to using cursor for pagination. But it seems I don't know how to fetch the result in plpgsql.
This is my function
CREATE OR REPLACE FUNCTION get_pagination_custom_word_moderation(_moderation_id bigint, _is_black boolean, _index integer, _max_result integer)
RETURNS TABLE(word_id bigint,
word character varying,
is_num_rlpcm boolean,
is_word_bund boolean,
note text,
create_time timestamp without time zone,
last_update timestamp without time zone) AS
$BODY$
DECLARE custom_word_moderation_cursor CURSOR FOR
SELECT
word_id,
word,
is_num_rlpcm,
is_word_bund,
note,
create_time,
last_update
FROM
custom_word_moderation
WHERE
moderation_id=_moderation_id
AND is_black=_is_black;
BEGIN
MOVE ABSOLUTE _index FROM custom_word_moderation_cursor;
RETURN QUERY FETCH _max_result FROM custom_word_moderation_cursor;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
The Error is:
ERROR: syntax error at or near "$1"
LINE 1: FETCH $1 FROM $2
^
QUERY: FETCH $1 FROM $2
CONTEXT: SQL statement in PL/PgSQL function "get_pagination_custom_word_moderation" near line 18
********** Error **********
ERROR: syntax error at or near "$1"
SQL state: 42601
Context: SQL statement in PL/PgSQL function "get_pagination_custom_word_moderation" near line 18
I think the problem is about how to return a fetch result form cursor.
What you are trying to do is not implemented. Cursors are intended to be returned as such, so that the client can fetch rows as he pleases. Especially for big results. You would define a function with RETURNS refcursor for that.
You could make it work with a FOR LOOP and explicit assignment of OUT variables, but that's tricky to combine with RETURNS TABLE ...
You would also have to OPEN the cursor, because DECLARE has a different meaning in the context of plpgsql than the same key word as SQL DECLARE for cursors. And you would have to FETCH .. INTO ..
Instead, use a simple equivalent without cursor:
CREATE OR REPLACE FUNCTION get_pagination_custom_word_moderation(
_moderation_id bigint, _is_black boolean
, _index integer, _max_result integer)
RETURNS TABLE(word_id bigint,
word varchar,
is_num_rlpcm boolean,
is_word_bund boolean,
note text,
create_time timestamp,
last_update timestamp) AS
$func$
BEGIN
RETURN QUERY
SELECT word_id
,word
,is_num_rlpcm
,is_word_bund
,note
,create_time
,last_update
FROM custom_word_moderation
WHERE moderation_id = _moderation_id
AND is_black = _is_black
OFFSET _index
LIMIT _max_result;
END
$func$ LANGUAGE plpgsql;
Or even simpler with an SQL function:
CREATE OR REPLACE FUNCTION get_pagination_custom_word_moderation(
_moderation_id bigint, _is_black boolean
, _index integer, _max_result integer)
RETURNS TABLE(word_id bigint,
word varchar,
is_num_rlpcm boolean,
is_word_bund boolean,
note text,
create_time timestamp,
last_update timestamp) AS
$func$
SELECT word_id
,word
,is_num_rlpcm
,is_word_bund
,note
,create_time
,last_update
FROM custom_word_moderation
WHERE moderation_id = $1
AND is_black = $2
OFFSET $3
LIMIT $4;
$func$ LANGUAGE sql;
I am using $n notation in the function body, since parameter cannot be referenced by name in SQL functions before version 9.2.
If you actually want to return all columns of a table, you can further simplify:
CREATE OR REPLACE FUNCTION get_pagination_custom_word_moderation(
_moderation_id bigint, _is_black boolean
, _index integer, _max_result integer)
RETURNS SETOF custom_word_moderation AS
$func$
SELECT *
FROM custom_word_moderation
WHERE moderation_id = $1
AND is_black = $2
OFFSET $3
LIMIT $4;
$func$ LANGUAGE sql;

PostgreSQL execute + date

I am trying to create an SQL select statement in PL/pgSQL procedure. It was all fine until I had to add a date to the select. The problem is that to compare dates in select clause my date must be enclosed in single quotes '' (e.g. '01.01.2011'), but in my case it is already a text type and I can't add it there.
Below is a sample code that should have same problem:
CREATE OR REPLACE FUNCTION sample(i_date timestamp without time zone)
RETURNS integer AS
$BODY$
DECLARE
_count integer := 0;
_sql text := '';
BEGIN
IF i_date IS NOT NULL THEN
_cond := _cond || ' AND t.created>' || i_date;
END IF;
_sql := 'SELECT count(*) FROM test t WHERE 1=1' || _cond;
EXECUTE _sql INTO _count;
RETURN _count;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Is there any other way to "escape" date? Or some other suggestions?
To use insert values safely and efficiently into a dynamically build and executed SQL string, there are a number of possibilities. The best one is to use the USING clause like this:
CREATE OR REPLACE FUNCTION sample(_date timestamp without time zone)
RETURNS integer AS
$BODY$
BEGIN
RETURN QUERY EXECUTE '
SELECT count(*)::int
FROM test t
WHERE t.created > $1'
USING _date;
END;
$BODY$ LANGUAGE plpgsql VOLATILE;
This is actually a bad example, because it could be simplified to:
CREATE OR REPLACE FUNCTION sample(_date timestamp)
RETURNS integer AS
$BODY$
SELECT count(*)::int
FROM test
WHERE created > $1;
$BODY$ LANGUAGE sql;
Another way would be to use quote_literal().
I wrote more about dynamic SQL in plpgsql here.