I wrote a stored procedure to insert values into a table-valued parameter.
CREATE PROCEDURE insert_timezone_table
#TZ NVARCHAR(10)
AS
BEGIN
DECLARE #Table CT_sp;
IF type_id('[dbo].[COUNTRY_TIMEZONE_sp]') IS NOT NULL
DROP TYPE [dbo].[COUNTRY_TIMEZONE_sp];
CREATE TYPE COUNTRY_TIMEZONE_sp as TABLE (country_code NVARCHAR(2))
INSERT #Table (country_code)
SELECT country_code
FROM Timezones
WHERE fo_timezone = #TZ
END
Then I want to pass this as input for another stored procedure, using in the end in the WHERE clause like this:
WHERE country_code IN (SELECT country_code FROM #TimezoneTable)
This is not yielding what I want, so I have two questions:
Is it possible to make a simple select on the table-valued parameter to see exactly what fell inside there on the 1st procedure?
I reckon this can be a problem of missing quotes on the strings being passed in the IN clause.. How can I solve this problem? Anyway I can in the first stored procedure add the results of the other table concatenated with '' ?
WHERE country_code IN (SELECT country_code FROM #TimezoneTable)
I guess it is doing something like IN ( DE,PL) so it retrieves blanks, and it should be doing IN ('DE','PL') but I do not know how to put the country_codes in quotations
Thank you!
Related
I am trying to pass a multiple value string parameter to a table type parameter in a SQL Server 2012 stored procedure. I paste this code in the dataset of SSRS:
DECLARE #mylist clinic_list_tbltype
INSERT #mylist(n) VALUES (#pm_ChooseClinics)
EXEC sp_Skillset_Summary_With_Callbacks_Report #mylist, #pm_ChooseInterval, #pm_StartDateTime, #pm_EndDateTime
clinic_list_tbltype is a table type I created with one varchar(50) field named "n". I can call this stored procedure from SSMS o.k. like this (and it comes back very fast):
DECLARE #mylist clinic_list_tbltype
INSERT #mylist(n) VALUES ('clinicA'), ('clinicB')
EXEC sp_Skillset_Summary_With_Callbacks_Report #mylist, 'Daily', '6/3/2014', '6/9/2014'
I can run in SSRS for only one clinic (but very slow), but if I try more than one it gives an error saying that
there are fewer columns in the INSERT statement than values specified
in the Values clause
. Even running for one clnic it works, but it takes a very very long time compared to running the query in SSMS. Like 2 minutes vs. 1 second. Must be because I'm passing ('clinicA', 'clinicB') instead of ('clinicA'), ('clinicB').
How to do?
Right I need to give you some back ground 1st.
When you allow SSRS parameter to select multiple values, The selection of multiple values creates a comma deliminated string of value as one string
'value1,value2,value3'
To check values in a string using IN operator we need strings concatenated with commas something like this ....
'value1','value2','value3'
Your Proc
Now in your proc when you insert values explicitly it inserts multiple values into your table.
INSERT INTO Table_Value_Param
VALUES ('value1'), --<-- 1st value/Row
('value2'), --<-- 2nd Value/Row
('value3') --<-- 3rd Value/Row
and this gives you back the expected results as when inside your procedure you execute a statement like
SELECT *
FROM Table_Name
WHERE ColumnName IN (SELECT ColumnName
FROM Table_Value_Param)
On the other hand when you try to insert into table using SSRS report Parameter you table inserts value like
INSERT INTO Table_Value_Param
VALUES ('value1,value2,value3') --<-- One Row/Value containing all the values comma separated
Solution
Creating TVP in this situation doesnt really help, What I do is make use of dbo.Split() function inside my procedure.
You can find many definitions for split function online, for a some cool ones have a look here Split Function equivalent in tsql?
Once you have created this split function just use this function inside your procedure definition you dont even need the Table valued parameters then.
Something like this...
SELECT *
FROM Table_Name
WHERE ColumnName IN (
SELECT Value
FROM dbo.Split(#Report_Param, ',')
)
declare #Vendors_Filter nvarchar(max) = 'a,b,c'
declare #Vendors nvarchar(max)
set #Vendors =''''+replace(#Vendors_Filter,',',''',''')+''''
select #Vendors
I have a problem when I want to select more then one value in SQL Server. I found a lot of examples with SQL Server Reporting Services but I want to use this stored procedure in a Windows form application.
I have one parameter
#emp nvarchar(50)
select * from table
where crdname = #emp
This one returns table for a single crdname, but I have a situation when I need the table with all crdname.
I have a solution using C# and 2 stored procedures, one procedure for all crdname and one procedure for a single emp, but it's a lot of code for something that I'm missing.
This depends on the scope of the requirements. Do you want it to be one or all? Do you want to be able to do multiple values? For the one or all scenario:
Have a way to pass NULL to the stored procedure then change the WHERE to WHERE (#emp is NULL OR crdname = #emp).
When the parameter is NULL, the WHERE will evaluate to true and you will get all records. When the parameter is not NULL, you will pull the single value you are looking for.
For the multiple values scenario:
Change the = to IN. You might have to create a string split function since you are passing in nvarchar for the parameter.
Use the same stored procedure, but add a condition on the parameter:
CREATE PROCEDURE dbo.YourSP #emp INT = NULL --I assumed the data type
AS
BEGIN
SELECT *
FROM YourTable
WHERE crdname = #emp
OR #emp IS NULL
END;
Then when you want all the results, then call the sp like this:
EXEC dbo.YourSP
And when you want one, then do this:
EXEC dbo.YourSP 1234
You can combine both stored procedures into one, by passing in null for #emp
select *
from table
where #emp is null or crdname = #emp
If #emp is null, then the first condition is true and all rows are returned.
I would suggest two stored procedures, because the above approach is a bit convoluted. But that's just me :)
If you find yourself writing alot of sp's for your winform app, then maybe an ORM would help - e.g. Entity framework?
In TSQLT, I'm trying to return a result from a stored procedure and add it to a variable so that I can assert if it matches my expected result.
I've seen loads of examples of returning results from functions but none where a stored procedure is called.
Does anybody have examples that they could share?
Thanks in advance
If you want to get a variable back from a stored procedure one way to do this is to use an out parameter
CREATE PROC MyTest
(#myVar int output)
AS
BEGIN
SET #myVar = 10
END
GO
DECLARE #x int
EXEC MyTest #myVar=#x output
SELECT #x
If you are getting a result set back from the stored procedure, here is an example from a tSQLt test that I wrote. I haven't bothered with the whole test because this should give you what you need.
CREATE TABLE #Actual (SortOrder int identity(1,1),LastName varchar(100), FirstName varchar(100), OrderDate datetime, TotalQuantity int)
-- Act
INSERT #Actual (LastName, FirstName, OrderDate, TotalQuantity)
EXEC Report_BulkBuyers #CurrentDate=#CurrentDate
The trick here is that you have to create the #actual table first. It should contain the same columns as what is returned from the stored procedure.
Just as an aside, you may have noticed I have a SortOrder column in the #actual table. This is because I was interested in testing the order of the data returned for this specific report. EXEC tSQLt.AssertEqualsTable will match rows like for like, but does not match the order in which the rows appear in the expected and actual so the way to ensure the order is to add a SortOrder column (which is an identity column) to both the #expected and #actual
Have a look here:
http://technet.microsoft.com/en-us/library/ms188655.aspx
Lots of examples about returning values from a stored procedure. At the bottom of the page there is also an example about evaluating a return code.
its actually really simple.
declare #variable int
exec #variable = _Stored_Procedure
I'm trying to send and array of parameters to a stored procedure
SELECT [id_Curso] AS IDCurso
,[Cod_Estabelecimento] AS CodEstabelecimento
,[Des_Estabelecimento] AS DesEstabelecimento
,[Cod_Curso] AS CodCurso
,[Des_Curso] AS DescCurso
,[Cod_Grau] AS CodGrau
,[Des_Grau] AS DescGrau
,[Cod_Area_Educacao] AS CodAreaEducacao
FROM [BEP_DEV].[dbo].[Curso]
where [Cod_Area_Educacao] in #List
DECLARE #List VARCHAR(MAX);
SELECT #List = '(1,2,3,4)';
SELECT [id_Curso] AS IDCurso
,[Cod_Estabelecimento] AS CodEstabelecimento
,[Des_Estabelecimento] AS DesEstabelecimento
,[Cod_Curso] AS CodCurso
,[Des_Curso] AS DescCurso
,[Cod_Grau] AS CodGrau
,[Des_Grau] AS DescGrau
,[Cod_Area_Educacao] AS CodAreaEducacao
FROM [BEP_DEV].[dbo].[Curso]
where [Cod_Area_Educacao] in (1,2,3,4)
How can I transform the first case in something like the 2nd one (which works.)?
I tried also with xml but also can't make it work.
Any help?
There are a number of possibilities for that, but given the you're on SQL 2008 the number one choice would be to use the new table valued parameters, in which you can send a whole table to a query or stored procedure in a single go (in your case, a table with a single column with an arbitrary number of IDs).
First create a table type in your database:
CREATE TYPE idTable AS TABLE (id INT)
Then just declare your procedure with a parameter of that type, and use it like any other table:
CREATE PROCEDURE SelectList (#IDs idTable READONLY) AS
SELECT * FROM sometable
INNER JOIN #IDs AS idTable ON idTable.id=sometable.id
There is a great article that discusses this and other methods in detail for doing what you need http://www.sommarskog.se/arrays-in-sql.html
You can use a udf that parses the string and inserts the values into a table (containing one int column in your case), and then join your Curso table on the table resulting from calling the udf on your CSV string.
I would pass it as xml. Its easy and very performant. Here is a good post with the details. https://www.simple-talk.com/blogs/2012/01/05/using-xml-to-pass-lists-as-parameters-in-sql-server/
I want to pass multiple values in a single parameter. SQL Server 2005
You can have your sproc take an xml typed input variable, then unpack the elements and grab them. For example:
DECLARE #XMLData xml
DECLARE
#Code varchar(10),
#Description varchar(10)
SET #XMLData =
'
<SomeCollection>
<SomeItem>
<Code>ABCD1234</Code>
<Description>Widget</Description>
</SomeItem>
</SomeCollection>
'
SELECT
#Code = SomeItems.SomeItem.value('Code[1]', 'varchar(10)'),
#Description = SomeItems.SomeItem.value('Description[1]', 'varchar(100)')
FROM #XMLDATA.nodes('//SomeItem') SomeItems (SomeItem)
SELECT #Code AS Code, #Description AS Description
Result:
Code Description
========== ===========
ABCD1234 Widget
You can make a function:
ALTER FUNCTION [dbo].[CSVStringsToTable_fn] ( #array VARCHAR(8000) )
RETURNS #Table TABLE ( value VARCHAR(100) )
AS
BEGIN
DECLARE #separator_position INTEGER,
#array_value VARCHAR(8000)
SET #array = #array + ','
WHILE PATINDEX('%,%', #array) <> 0
BEGIN
SELECT #separator_position = PATINDEX('%,%', #array)
SELECT #array_value = LEFT(#array, #separator_position - 1)
INSERT #Table
VALUES ( #array_value )
SELECT #array = STUFF(#array, 1, #separator_position, '')
END
RETURN
END
and select from it:
DECLARE #LocationList VARCHAR(1000)
SET #LocationList = '1,32'
SELECT Locations
FROM table
WHERE LocationID IN ( SELECT CAST(value AS INT)
FROM dbo.CSVStringsToTable_fn(#LocationList) )
OR
SELECT Locations
FROM table loc
INNER JOIN dbo.CSVStringsToTable_fn(#LocationList) list
ON CAST(list.value AS INT) = loc.LocationID
Which is extremely helpful when you attempt to send a multi-value list from SSRS to a PROC.
Edited: to show that you may need to CAST - However be careful to control what is sent in the CSV list
Just to suggest. You can't really do so in SQL Server 2005. At least there is no a straightforward way. You have to use CSV or XML or Base 64 or JSON. However I strongly discourage you to do so since all of them are error prone and generate really big problems.
If you are capable to switch to SQL Server 2008 you can use Table valued parameters (Reference1, Reference2).
If you cannot I'd suggest you to consider the necessity of doing it in stored procedure, i.e. do you really want (should/must) to perform the sql action using SP. If you are solving a problem just use Ad hoc query. If you want to do so in education purposes, you might try don't even try the above mentioned things.
There are multiple ways you can achieve this, by:
Passing CSV list of strings as an argument to a (N)VARCHAR parameter, then parsing it inside your SP, check here.
Create a XML string first of all, then pass it as an XML datatype param. You will need to parse the XML inside the SP, you may need APPLY operator for this, check here.
Create a temp table outside the SP, insert the multiple values as multiple rows, no param needed here. Then inside the SP use the temp table, check here.
If you are in 2008 and above try TVPs (Table Valued Parameters) and pass them as params, check here.