How do I use collection as a parameter in SQL Server (2008) SP? - sql

So, I have this stored procedure (let's call it SP1) that gets as parameters two strings (say string1 and string2)
However, I need to call this stored procedure a lot from my code, so in order to make things faster, I was thinking of doing it in bulk. Collecting all of the parameters into a collection of some sort, and then send this.
From what I understand I need to use a DataTable on the code side, and a custom table type as the parameter on the SQL Server side - ok, cool. But...now what?
But... how do I get from there to the point where I actually go
EXEC SP1 string1, string2 or something along those lines?

Not sure whether this is what you like to achieve, instead of parsing those two string parameters, you would like to get a table holding all of the string row?
If so, you could you use UDF within SP,
Check here:
CREATE FUNCTION [dbo].[Name]
(
#parameter
)
RETURNS #Table TABLE
(
col1 varchar(50),
col2 varchar(50)
)
AS
BEGIN
**the query that inserts each records to TABLE**
END
Then using this [Name] UDF in your SP

Create a table type
CREATE TYPE Strings AS TABLE ( String1 VARCHAR(50), String2 VARCHAR(50) )
Alter your procedure to accept table type as input
ALTER PROCEDURE Usp_procname (#strings STRINGS Readonly)
AS
..
To call the procedure
DECLARE #strings STRINGS
INSERT INTO #strings
(String1,String2)
SELECT 'String1','String2'
UNION ALL
SELECT 'String3','String4'
UNION ALL
SELECT 'String5','String6'
EXEC Usp_procname #strings
By this way you can pass more than one string in a single call. Make sure you update the logic inside the procedure to handle more than one string

In a case like this one, I usually concatenate strings and split them on the server side or pass even an xml if I have multiple columns. Sql it's very fast when processing xml. You can try all the methods and check the processing time and after that choose the best method.

Related

Table Variable in SQL Server Function from Input Columns

I would like to create a function that returns a column based on input from three other columns. As temporary tables are not allowed within functions, is it possible to create a table variable from three input columns?
CREATE FUNCTION dbo.convert_value(
#CustomerID VARCHAR(MAX),
#CustomerValue VARCHAR(MAX),
#CustomerDescription VARCHAR(MAX)
)
RETURNS FLOAT
AS BEGIN
DECLARE #CustomerTable TABLE (
UniquePatientUID VARCHAR(MAX),
ResultValue VARCHAR(MAX),
PracticeDescription VARCHAR(MAX)
);
-- How can I insert #UniquePatientUID, #ResultValue and #PracticeDescription into #CustomerTable
END
The context of this question is that I have a SQL script that uses temporary tables and many UPDATE and ALTER TABLE statements, that I need to convert into a function. That script begins with the three columns mentioned, and adds a fourth column, Converted_Value, which is calculated with several hundred lines of code and manipulating temporary tables. Is there any hope here?
A table variable insert is really not different than a regular insert. Don't use temp tables. You can alter the table as well, or just declare it initially with that fourth column and allow it to be NULL.
INSERT INTO #CustomerTable (UniquePatientUID, ResultValue, PracticeDescription)
VALUES(#CustomerID, #CustomerValue, #CustomerDescription);
Don't forget to return the FLOAT.
Table Variable is a table so, you can just use INSERT INTO ... VALUES....
INSERT INTO #CustomerTable (UniquePatientUID,ResultValue,PracticeDescription )
VALUES
(#UniquePatientUID, #ResultValue , #PracticeDescription)
Unless you need a table variable for some specific reason, why not just work with the variables as a derived table expression? i.e.
;with inputs (UniquePatientUID, ResultValue, PracticeDescription) as
(
select #UniquePatientUID, #ResultValue, #PracticeDescription
)
select *
from inputs
Table variables fall out of scope after the function call, and you can't pass table types in or out of functions either. So really all a table variable does here is serve as a means of place keeping that's more familiar to SQL developers. But they're not free, which is the only reason I'm curious what your use case is.
If you don't need to return them as a set or something similar, you can just interact with the variables directly too.

FnSplit not working for SQL stored procedure to take multiple parameters

I have a stored procedure that currently takes in one value(ChainId) for a parameter. I am trying to allow the user to select multiple values of(ChainId). My where statement is below. Could someone help point me in a better direction than I am going now. Currently the query will run and return no data if I select multiple values for the parameter.
WHERE EndAuth is null AND CL.CHIND in(
SELECT [Value] FROM dbo.FnSplit(#ChainId, ','))
ORDER BY CL.CHIND
This is a popular function in SQL Server, so I'll assume you're working with that. Make sure your parameter is of type Varchar(MAX). #ChainId is passed as your string (ideally for SSRS) and ',' is passed as your delimiter. In SSRS, if you have a text box for your users to manually enter multiple values, they will enter something like 'value1, value2, value3'.
Test this out:
Declare #Yes_No Varchar(Max)
Set #Yes_No = 'y,n'
Select #yes_no
Select * from SplitString('y,n',',')
Select * from SplitString(#Yes_No,',')
Your results will be
y,n
----
y
n
----
y
n
Why I say to use Varchar(Max) and not int, or Varchar(10) for example, is because that would stop the function from reading all the values prematurely.
Try this:
Declare #Yes_No Varchar(1)
Set #Yes_No = 'y,n'
Select * from SplitString(#Yes_No,',')
The result will be:
y
The reason is because the function only accepts a value of 1 character in length, and splits that. As you can see, there isn't much to split.
This is just the way SSRS accepts parameters. FN_Split isn't necessarily a built-in function, but a widely popular one designed to allow you to pass multiple values to a string, with a pre-specified delimiter. So make sure you also go to your parameter in the report and specify that it will allow for multiple values. You will also want to supply a list of potential values for your users to select from. You'll either do this by manually populating a small list or providing another data source in the form of a stored procedure or table.

How to pass multiply values parameter to a procedure

I want to pass multiply values parameter to my procedure and use it as a filter. My parameter is called #Month and it's datatype is NVARCHAR(MAX) in the procedure.
I have used filter as
WHERE (cal.CalendarYear = #Year) AND (cal.MonthId IN (#Month))
and also tried STRING_SPLIT function.
However, when I run my report, it return an error
Conversion failed when converting the nvarchar value '1,2,3,4,5,6,7,8,9,10,11,12' to data type int.
you cannot give a varchar string with comma separated values, and expect the query to process it as a 'in' list.
The way that would work is when you would concatenate your sql statement in the stored procedure, and then execute the sql string with sp_executesql.
Using string_split is one way of doing it, but you have to be aware that it gives you a table with varchars, not integers.
For completeness I should mention that the most 'robust' way of doing this is passing a table type variable to your stored procedure, as described here: How to pass table value parameters to stored procedure from .net code.
With the split_string, you could try something like this:
select
-- your fields
from
manytables mt
join string_split(#Month,',') months on cast(months.value as int) = cal.monthId
where
cal.Calenderyear = #year

How do you pass values for a parameter by position when you need to check multiple values?

I created a stored procedure (spBalanceRange) with 2 optional parameters. They've been set to a default value and the sp works fine when I pass only 1 value per parameter by position. However, I have a situation where I'm trying to pass, by position, two strings immediately followed by a wildcard. I want the user to be able to search for Vendor names that start with either 'C%' or 'F%'. Here's the gist of the CREATE PROC statement:
CREATE PROC spBalanceRange
#VendorVar varchar(40) = '%',
#BalanceMin money = 1.0
...
Here's what I've tried so far, but doesn't work:
EXEC spBalanceRange '(C%|F%)', 200.00;
EXEC spBalanceRange 'C%|F%', 200.00;
Is there a way to check for 2 or more string values with a wildcard when passed by position? Thanks.
EDIT: According to your comments you are looking for the first letter of a vendor's name only.
In this special case I could suggest an easy, not well performing but really simple approach. CHARINDEX returns a number greater than zero, if a character appears within a string. So you just have to pass in all your lookup-first-characters as a simple "chain":
DECLARE #DummyVendors TABLE(VendorName VARCHAR(100));
INSERT INTO #DummyVendors VALUES
('Camel Industries')
,('Fritz and Fox')
,('some other');
DECLARE #ListOfFirstLetters VARCHAR(100)='CF';
SELECT VendorName
FROM #DummyVendors AS dv
WHERE CHARINDEX(LEFT(dv.VendorName,1),#ListOfFirstLetters)>0
This was the former answer
Checking against more than one value needs either a dedicated list of compares
WHERE val=#prm1 OR val=#prm2 OR ... (you know the count before)
...or you use the IN-clause
WHERE LEFT(VenoderName,1) IN ('C','F', ...)
...but you cannot pass the IN-list with a parameter like ... IN(#allValues)
You might think about a created TYPE to pass in all your values like a table and use an INNER JOIN as filter: https://stackoverflow.com/a/337864/5089204 (and a lot of other examples there...)
Or you might think of dynamic SQL: https://stackoverflow.com/a/5192765/5089204
And last but not least you might think of one of the many split string approaches. This is one of my own answers, section "dynamic IN-statement": https://stackoverflow.com/a/33658220/5089204
I'm answering my own question, and maybe other solutions exist but here is what had to happen with my stored procedure in order to pass variables by position:
CREATE PROC spBalanceRange
#VendorVar varchar(40) = '%',
#BalanceMin money = 1.0
AS
IF (#VendorVar = '%' AND #BalanceMin IS NULL OR #BalanceMin = '')
BEGIN
PRINT 'BalanceMin cannot be null.';
END
IF (#VendorVar = % AND #BalanceMin IS NOT NULL)
BEGIN
(sql statement using parameters)
END
EXEC spBalanceRange '[C,F]%', 200.00;
That's what I know.

Passing parameters from Stored Procedure to Function (inside Stored Procedure)

I have a problem and I have researched Stackoverflow for answers without any luck. I have manage to build a Stored Procedure that uses a function called GetSubtree_relvalue within it. The stored procedure and its function works just fine when the function has its parameters hard coded. But now I want the function to inherent the parameters that is sent in with the Stored procedure when it is executed.
When I replace XX and USA with #attribute_id and USA with #Client it doesn't return anything. I have debugged it so far so that I can conclude that the function doesn't get any values with it when it runs. This, even though these parameters in the Stored Procedure carries exactly the same value as the one that I have hard coded . (I checked with a regular select #client within the Procedure and it returns USA.)
Am I parametrizing the function wrongly? Do I need to initiate the functions parameter to be able to send it/pass it on to the function? How do get functions to inhere parameters?
I would be glad for all input regarding passing parameters forward from SP to functions.
Using SQL server 2008
Thanks
/Daniel
Function values hard coded
Insert into att_value_lookup (t.attribute_ID, t.att_value)
Select
t.attribute_ID, t.att_value
From
(Select attribute_id, att_value from relvalue
where attribute_id in (
Select attribute_id from (
select attribute_id
from dbo.GetSubtree_relvalue('XX','USA'))
) as t
Function values parameterized
Insert into att_value_lookup (t.attribute_ID, t.att_value)
Select
t.attribute_ID, t.att_value
From
(Select attribute_id, att_value from relvalue
where attribute_id in (
Select attribute_id from (
select attribute_id
from dbo.GetSubtree_relvalue('#attribute_id','#client'))
) as t
remove the quotes!!
dbo.GetSubtree_relvalue('#attribute_id','#client')
should be:
dbo.GetSubtree_relvalue(#attribute_id,#client)
you only need them when passing in literal string values like 'XX' and 'USA', not when passing in variables. You were actually passing in strings that contained the variable names: '#attribute_id', '#client' and not the values contained within the variables.
you can check it out:
DECLARE #x varchar(10)
SET #x='wow wee!!'
print '#x'
print #x
Remove the quotes from around your parameters. You're currently passing strings that happen to be the names of the parameters, but not passing the parameters themselves.
from dbo.GetSubtree_relvalue(#attribute_id,#client)