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)
Related
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.
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
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.
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.
create function Xtest
(#d1 varchar(3)=null
,#d2 varchar(3)=null)
returns table
as
return
with code_list(code_pattern)
as
(
select x.code_pattern
from (values (#d1),(#d2)) as x(code_pattern)
where x.code_pattern is not null
),y
as
(
select substring(code,1,3) as code
from tblicd
where substring(code,1,3) in
(
select * from code_list
)
)
select * from y
is my function which will make sense when it's fully finished. If I try to run this query and I don't supply two parameters, it will fail. I have the same code as a stored procedure and if I only enter one parameter, it works fine and assigns the second parameter null. Is there a way that I can pass null as a parameter value if the parameter isn't supplied, like one can do with stored procedures?
The function does compile.
You can't omit the parameters when you call a function. This isn't anything you're doing wrong in the syntax, it's just simply not supported by SQL Server. Stored procedures have optional parameters, but functions do not.
You can, however, supply default:
SELECT code FROM dbo.Xtest(default, default);
Or in this case if you know the defaults are NULL you can do:
SELECT code FROM dbo.Xtest(NULL, NULL);
Also please always use the schema prefix (in this case dbo.) when creating and referencing any object, especially functions.