Snowflake sql Procedure - snowflake-cloud-data-platform

Am trying to create a procedure using sql in snowflake,but its giving an error when calling it.
create or replace procedure get_max_date( )
returns datetime not null
language sql
as
$$
begin
set max_date= (select max(last_updated) from Control_Variables);
return max_date;
end
$$;
Error:SQL compilation error: error line 5 at position 9 invalid
identifier 'MAX_DATE'
please give me a solution ,actually i want to declare a variable inside proc and store data in that variable as shown in procedure
Regards,
Nadeem
Tried to create snowflake procedure

Indeed, you need to declare your variable inside the procedure. Try this:
create or replace procedure get_max_date( )
returns datetime not null
language sql
as
$$
declare
max_date datetime;
begin
max_date := (select max(last_updated) from Control_Variables);
return max_date;
end
$$;
Example how it works with some test data:
create or replace table Control_Variables (last_updated datetime);
insert into CONTROL_VARIABLES values ('2022-11-28 23:59:59');
insert into CONTROL_VARIABLES values (current_timestamp());
call get_max_date();

Related

write multipe statments in snowflake

Hi i have one doubt in snowflake how to write multiple update stments using stored procedure.
i have tried like below
create or replace procedure sp_multipleupdate()
returns table()
lANGUAGE sql
as
$$
declare res rsultset(
update TEST.PUBLIC.DEPT set Dname='PM' where deptid=10;
update TEST.PUBLIC.emp set name='veavi' where deptno=20;
update TEST.PUBLIC.loc set locname='del' where id=5;
)
begin
return table(res);
end;
$$;
getting error :
000006 (0A000): Multiple SQL statements in a single API call are not supported; use one API call per statement instead.
Syntax error: unexpected '('. (line 2)
please let me know how to write query to achive this task in snowflake server .
Multiple SQL statements inside the resultset are not supported.
Rather than writing the UPDATE statements like that I would create a more generic procedure and pass arguments to it, so maybe split the above one in 3 procedures since these UPDATE statements are for different tables.
Here is a sample of a generic stored procedure:
create or replace procedure find_invoice_by_id_via_execute_immediate(id varchar)
returns table (id integer, price number(12,2))
language sql
as
declare
select_statement varchar;
res resultset;
begin
select_statement := 'SELECT * FROM invoices WHERE id = ' || id;
res := (execute immediate :select_statement);
return table(res);
end;
You can read more here.

Declaring DATETIME in Stored proc MS SQL

I am trying to get System Datetime for a column when a new row is inserted or updated into a table using stored Proc in MS SQL. How can I achieve it?
I have tried below code
CREATE PROCEDUCE test_Cl_INSERT
#SRC_ID int,
#CREATED_BY datatime
AS
BEGIN
INSERT into dbo.CL_Batch(SRC_ID, Created_BY)
VALUES(#SRC_ID, CURRENT_TIMESTAMP)
END
EXEC dbo.test_Cl_INSERT
#SRC_ID=44
ERROR : #CREATED_BY parameter missing
This will work:
CREATE PROCEDURE test_Cl_INSERT
#SRC_ID int
AS
BEGIN
INSERT into dbo.CL_Batch(SRC_ID, Created_BY)
VALUES(#SRC_ID, CURRENT_TIMESTAMP)
END
EXEC dbo.test_Cl_INSERT
#SRC_ID=44
Your procedure signature is:
CREATE PROCEDUCE test_Cl_INSERT
#SRC_ID int,
#CREATED_BY datatime
You attempt to execute as:
EXEC dbo.test_Cl_INSERT #SRC_ID=44
Do you see something missing? You should. Your procedure has 2 parameters but you provide only 1 when you attempt to execute it. That is your problem. As already noted, you don't use that paramter within the logic of the procedure so why does it exist at all?
You must execute your procedure like this:
EXEC dbo.test_Cl_INSERT #SRC_ID=44, #CREATED_BY = '20201124 12:49';
Notice I just assigned a random value to the parameter since it (the parameter) is not used within your procedure code. That solves the question you ask. However, you have more important issues to consider.

How to pass "type" as input parameter to func in Postgresql

Looking forward for PostgreSQL equivalent code. Please help. Problem while doing database migration from SQL Server to Postgresql.
SQL Server code:
CREATE TYPE [InactiveOwnDetails] AS TABLE
(
[EntType] [nvarchar](10) NULL,
[EntName] [nvarchar](400) NULL,
)
CREATE PROCEDURE [dbo].[SP_GenerateInactiveOwnEmail]
AS
DECLARE #InactiveOwnDetails InactiveOwnDetails
INSERT INTO InactiveOwnEmailActivity (Subject_Email)
VALUES (
SELECT **Fn_GetInactivePpMailBodyContent**(#InactiveOwnDetails)
)
CREATE FUNCTION [dbo].[**Fn_GetInactivePpMailBodyContent**]
(#InactiveOwnDetails InactiveOwnDetails READONLY)
RETURNS NVARCHAR(MAX)
AS
BEGIN
SET #ResultString = '<p> Dear'+CAST(12 AS NVARCHAR)+', '
RETURN #ResultString
END
Please help!
To answer the direct question, you can pass a (record) type to a function:
CREATE TYPE inactive_own_details as (ent_type varchar(10), ent_name varchar(400));
You can create a function that receives that type and returns something:
CREATE FUNCTION fn_GetInactivePpMailBodyContent(p_details inactive_own_details)
RETURNS text
AS
$$
select concat('<p> Dear', p_details.ent_name, '</p>');
$$
language sql;
The function in the question doesn't make sense to me as it doesn't use the passed type at all.
In the procedure you can use it like this:
CREATE PROCEDURE sp_generateinactiveownemail()
AS
$$
declare
l_details inactive_own_details;
begin
l_details := ('type', 'Arthur'); -- initialize the variable
INSERT INTO inactiveownemailactivity (subject_email)
VALUES (SELECT fn_getinactiveppmailbodycontent(l_details));
end;
$$
language plpgsql;
Note: create procedure requires Postgres 11 or later. You have tagged your question with Postres 9.5 - which is about to be deprecated in about 6 months. A new migration project should definitely not use that version in 2020. You should migrate to Postgres 12 instead.

SQL Server stored procedure: Must declare the scalar variable

DECLARE #occurrences TABLE (Occurrences int)
BEGIN
SET #occurrences = (SELECT Occurrences FROM [Data])
END
Why this is not possible to execute? I want to read into a table all the columns of a given table within my stored procedure so I can update later another table.
Is this fundamentally wrong?
The exact error that SQL Server throws is:
Must declare the scalar variable "#occurrences"
Table variables are different than scalar variables. So you need
DECLARE #occurrences TABLE (Occurrences int)
BEGIN
insert #occurrences
SELECT Occurrences FROM [Data]
END

SQL Server stored procedure only works with locally re-declared variables; not variables passed to the procedure

I have edited my SQL code blocks to more accurately show what is going on
Say I have a simple stored procedure:
CREATE PROCEDURE [DBO].[FOO]
(#VARIABLE VARCHAR(500))
AS
BEGIN
SELECT AVG(BAR)
FROM MYTABLE
WHERE THING = #VARIABLE AND RTRIM(LTRIM(THING)) <> ''
END
When I call this stored procedure from my classic ASP page; which in this case would be with:
Set foo = Server.CreateObject("ADODB.RecordSet")
curCmd = "Foo 'MYVARIABLE'"
foo.Open curCmd, connectionString
I get this error (on the same line as the page opens the foo object):
Arithmetic overflow error converting varchar to data type numeric.
If I call the stored procedure manually in the terminal (IDE?); then it works fine.
Also if I recreate the stored procedure as the following:
CREATE PROCEDURE [DBO].[FOO]
(#VARIABLE VARCHAR(500))
AS
BEGIN
DECLARE #VARIABLE2 VARCHAR(500) = #VARIABLE
SELECT AVG(BAR)
FROM MYTABLE
WHERE THING = #VARIABLE2 AND RTRIM(LTRIM(THING)) <> ''
END
Then the stored procedure runs fine.
I have tried dropping and recreating the stored procedure (without using the re-declaration trick), but it does not fix the issue.
*As an aside; there is validation on the data being inserted into the table to ensure that only numbers (integers) are being entered for the THING field. The THING field can also be blank; hence the where clause.
I basically have two questions:
Why does re-declaring the same variable type with the same data fix the issue?
Is there a way I can fix my problem without using this silly "re-declaration" trick?
Thanks in advance for any help with this.
I think you can get the same error if you use begin/end:
CREATE PROCEDURE [DBO].[FOO] (
#VARIABLE VARCHAR(500)
)
AS
BEGIN
DECLARE #VARIABLE2 VARCHAR(500) = #VARIABLE;
SELECT AVG(BAR) FROM MYTABLE WHERE THING = #VARIABLE2;
END;
Then, both statements will be part of the stored procedure body and you can work on fixing the data so it will work.

Resources