Use array as bind variable Snowflake - snowflake-cloud-data-platform

Using Snowflake scripting I need to bind the input parameter of the stored procedure which is an array and it will be part of array_contains function in dynamic sql however its throwing bind error

It is possible to use ARRAY data type as a bind argument inside Snowflake Scripting:
Sample data:
CREATE OR REPLACE TABLE t(i INT, j TEXT);
INSERT INTO t(i, j) VALUES (1,'a'), (2, 'b'), (3, 'c'), (4, 'd');
Stored procedure:
CREATE OR REPLACE PROCEDURE sp_array_arg(ARG ARRAY)
RETURNS TABLE(i INT, j TEXT)
LANGUAGE SQL
AS
$$
DECLARE
res RESULTSET default (SELECT i, j
FROM t
WHERE ARRAY_CONTAINS(t.i::VARIANT, :ARG));
BEGIN
RETURN TABLE(res);
END;
$$;
Procedure call:
CALL sp_array_arg([1,3]);
/*
I J
1 a
3 c
*/

Related

Declare and Valued Table Functions

I need to put my Declare Section into a Table-valued function.
CREATE FUNCTION [Manual_COUNTRIES_2019](
#risk_1,
#risk_2,
#risk_3,
#risk_4,
#risk_5)
RETURNS (#risk_1, #risk_2,#risk_3,#risk_4,#risk_5) TABLE (Code VARCHAR(100))
AS
BEGIN
DECLARE #risk_1 TABLE (Code VARCHAR(100));
INSERT INTO #risk_1 (Code) VALUES ('AA'),('AB'),('AC');
DECLARE #risk_2 TABLE (Code VARCHAR(100));
INSERT INTO #risk_2 (Code) VALUES ('AX'),('AY'),('AZ');
DECLARE #risk_3 TABLE (Code VARCHAR(100));
INSERT INTO #risk_3 (Code) VALUES ('BB'),('BC'),('BD'),('BE');
DECLARE #risk_4 TABLE (Code VARCHAR(100));
INSERT INTO #risk_4 (Code) VALUES ('DA'),('DB'),('DC');
DECLARE #risk_5 TABLE (Code VARCHAR(100));
INSERT INTO #risk_5 (Code) VALUES ('YY'),('XZ');
RETURN
END
I took this as a template: Declare variable in table valued function
However, it is not happy with my table suggestion, nor with the list of #risks.
What am I missing?
As you can't return multiple tables, I suggest adding another column which specifies the table you wanted to add it to, which can then be used to filter it on when you call it.
CREATE FUNCTION [Manual_COUNTRIES_2019]()
RETURNS #Risk TABLE (RiskNum int, Code VARCHAR(100))
AS
BEGIN
INSERT INTO #risk (RiskNum, Code)
VALUES (1, 'AA'),(1, 'AB'),(1, 'AC'),
(2, 'AX'),(2, 'AY'),(2, 'AZ'),
(3, 'BB'),(3, 'BC'),(3, 'BD'),(3, 'BE'),
(4, 'DA'),(4, 'DB'),(4, 'DC'),
(5, 'YY'),(4, 'XZ');
RETURN;
END;
However as you now don't need the variables I would suggest using an Inline Table Valued Function e.g.
CREATE FUNCTION [Manual_COUNTRIES_2019]()
RETURNS TABLE
RETURN
SELECT *
FROM (
VALUES (1, 'AA'),(1, 'AB'),(1, 'AC'),
(2, 'AX'),(2, 'AY'),(2, 'AZ'),
(3, 'BB'),(3, 'BC'),(3, 'BD'),(3, 'BE'),
(4, 'DA'),(4, 'DB'),(4, 'DC'),
(5, 'YY'),(4, 'XZ')
) AS X (RiskNum, Code);
You then pull the values you want as follows:
select Code from dbo.Manual_COUNTRIES_2019() where RiskNum = 1; -- For the first table, change the number to change the table.

Is there a way to return a value from a stored procedure inside a case?

I want to return a value from a stored procedure and then call this stored procedure inside another procedure that will be evaluated in a CASE WHEN statement. With the code below it will be more clear I hope.
First stored procedure that will insert a row
CREATE PROCEDURE [dbo].[InsertBook]
#bookName VARCHAR(50)
AS
INSERT INTO [dbo].[Book] (bookName)
VALUES (#bookName)
Second stored procedure that will return a value based on a if/else condition
CREATE PROCEDURE [dbo].[verifyBook]
#bookName VARCHAR(50)
IF (#bookName = 'A')
BEGIN
EXEC [dbo].[InsertBook] #bookName = 'A'
SELECT 1
END
ELSE IF (#bookName = 'B')
BEGIN
SELECT 0
END
Third stored procedure that will verify the value returned by the second stored procedure:
CREATE PROCEDURE [dbo].[selectBook]
#bookName VARCHAR(50)
SELECT
id, name,
CASE
WHEN [dbo].[verifyBook] #bookName = 1
THEN TRUE
ELSE FALSE
END AS Status
FROM Books
But i have an error in my third stored procedure :
An expression of non-boolean type specified in a context where a condition is expected
With a function I don't have the problem but I will need a stored procedure to insert data.
How to verify the value returned by a stored procedure in a CASE WHEN?
Thanks
A SELECT inside a stored procedure outputs a Resultset, not a return value or an output parameter. You can INSERT … EXEC to load the results into a table variable or temp table.
EG
CREATE OR ALTER PROCEDURE dbo.selectBook
#bookName VARCHAR(50)
as
begin
declare #v table(status bit);
insert into #v exec dbo.verifyBook #bookName;
select status from #v;
end

Stored procedure to update table in SQL

I have a following issue...
I have three variable, v1,v2,v2 (All are of type java.util.ArrayList). I want to write a stored procedure that will take this variable as an input and update the one table.
How can I loop throw the array list of the variable in sql and update the table?
For instance, the values for v1 (10,11,12), v2(21,22,23), v3(31,32,33). The sql update of the table should happen as follows
Table1:
Row1: 10,21,31
Row2: 11,22,32
Row3: 12,23,33
I will be thankful if someone could get back to me on how to write the store procedure for this.
I have used this approach and it works for me perfectly fine.
Have your stored procedure receive the three variables, each as varchar(max) -- if you know the size you can write the number instead of max. For example:
create procedure usp_testSP
#v1 varchar(max),
#v2 varchar(max),
#v3 varchar(max)
as
begin
declare #v1Values table (number int);
insert into #v1values
select * from dbo.fnSplit(#v1,','); -- the fnSplit function is given below
-- this way you can retrieve all values for other two variables
-- then you can use the corresponding tables, i.e.: #v1Values to complete the steps you need to.
end
Here's the code for dbo.fnSplit(#inputList, #delimiter):
CREATE FUNCTION [dbo].[fnSplit](#sInputList VARCHAR(max), #sDelimiter VARCHAR(10) = ',')
RETURNS #List TABLE (item varchar(100))
BEGIN
DECLARE #sItem varchar(100)
WHILE CHARINDEX(#sDelimiter, #sInputList, 0) <> 0
BEGIN
SELECT #sItem = RTRIM(LTRIM(SUBSTRING(#sInputList, 1, CHARINDEX(#sDelimiter, #sInputList,0) - 1))),
#sInputList = RTRIM(LTRIM(SUBSTRING(#sInputList, CHARINDEX(#sDelimiter, #sInputList, 0) + LEN(#sDelimiter),LEN(#sInputList))))
IF LEN(#sItem) > 0
INSERT INTO #List SELECT #sItem
END
IF LEN(#sInputList) > 0
BEGIN
INSERT INTO #List SELECT #sInputList
END
RETURN
END
And finally, in your java code, you can convert the list to a string and pass it on to the stored procedure call.
List<Integer> v1; //suppose this is the list that contains the values.
String s = String.join("," /*this is the delimiter. It should be the same as the one you use when you call the dbo.fnSplit() function.*/, v1);

insert a field value into a table from c# Form application

I want to Insert a DateTime variable into a table by " Insert into " , I mean by using from coding not wizard.
fro example I have a table which has a some field and one of them is Time_1 and I've write a procedure which its duty is filling Information to my table and in my procedure I've used from :
Insert into my_table
values
('#name','#last_Name',#ID,#Time)
but SQL show error when I enter 12:45:00 for #Time
so please tell me how to enter times into my filed .
Thanks in advance
create procedure Insert_List
#code int, #name nvarchar(20),#lastname nvarchar(40),#time1 datetime,#time2 datetime,
#time3 datetime,#price1 int,#price2 int, #B1 int , #V1 int , #M1 int
as
begin
insert into Employee
values
(#code,#name,#lastname,#time1,#time2,#time3,#price1,#price2,#B1,#V1,#M1)
end
//and I try to execute my procedure by these information
execute Insert_List 1,'Keyvan','Fardi',10:00:00,18:15:00,19:10:00,10,10,10,10
select * from employee
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ':'.
Insert into my_table values ('#name','#last_Name',#ID,#Time)
Since you are using a parameterized SQL statement, do not enclose the parameters in quotes. Instead:
INSERT INTO my_table VALUES (#name, #last_Name, #ID, #Time);
If you are still getting an error, post the error message and all proc code.

T-SQL Stored Procedure, how to reuse the same insert multiple times - alternatives to sp_execute?

I've spent the last few hours looking for a solution to this, but still haven't found a good one.
My problem is pretty straightforward. I'm writing some very large stored procedures in T SQL (SQL Server 2008 R2) where I have to reuse the same INSERT quite a few times within the same stored procedure. The target table has a huge number of columns.
I tried defining a dynamic query into a varchar variable. Then executing it with sp_execute, specifying all the parameters and it works. But it's not the ideal solution, since whenever I need to call it, I have to duplicate the call with the same huge number of parameters every time.
What I'm looking for is a way to define the INSERT to be executed, specifying the variables to be used and then be able to call it with just one line of code, without the need to specify the parameters again.
I was wondering if someone can point me to a more efficient solution in terms of code reuse and readability.
Thanks in advance
A CLR user defined type may be a good answer: http://msdn.microsoft.com/en-us/library/ms131120.aspx
You would define a UDT with properties that correspond to your parameters, then you would create a stored procedure (a regular T-SQL proc will work) that takes an instance of your UDT as a parameter and then does the insert, like so:
CREATE PROCEDURE dbo.InsertProc(#params MyUDT)
AS
INSERT INTO dbo.T1 (a, b, c, d, e, f)
VALUES (#params.a, #params.b, #params.c, #params.d, #params.e, #params.f);
Then you main procedure would do something like this:
DECLARE #myParams AS MyUDT
-- call insert with initial parameters
SELECT #myParams.a = 1, #myParams.b = 2, #myParams.c = 3, #myParams.d = 4, #myParams.e = 5, #myParams.f = 6
EXEC dbo.InsertProc #myParams
-- change parameters a and b and call again
SELECT #myParams.a = 10, #myParams.b = 20
EXEC dbo.InsertProc #myParams
You can create a temporary stored procedure that is tailored to what you need. I think you need to use dynamic SQL to generate the temporary stored procedure. Here's an example sqlfiddle:
create table T (a int, b int, c int, d int, e int);
create proc InsertIntoT
#a int,
#b int,
#c int,
#d int
as begin
declare #procedureContents varchar(max) = '
create proc #TempInsert
#e int
as
insert T values (' + cast(#a as varchar(max))
+ ', ' + cast(#b as varchar(max))
+ ', ' + cast(#c as varchar(max))
+ ', ' + cast(#d as varchar(max))
+ ', #e)'
exec( #procedureContents)
exec #TempInsert 1
exec #TempInsert 2
exec('drop proc #TempInsert')
end;
exec InsertIntoT 2, 3, 4, 5;
exec InsertIntoT 3, 3, 3, 3;
select * from T

Resources