In this procedure, I want to delete those number which coming in #msisdn from Master Table and insert into tblDeactive:
ALTER PROCEDURE [dbo].[msisdn_deactivition](#msisdn varchar(1024))
AS
BEGIN
SET NOCOUNT ON;
insert into tblDeactive SELECT * from msisdn_master where msisdn in (#msisdn);
delete from msisdn_master where msisdn in (#msisdn);
END
...but it does not work?
You can't use a single query parameter in place of a list of values. One parameter = one value.
See Parameterize an SQL IN clause for several solutions and lots of discussion about using parameters with the IN( ) predicate.
You need to use a split function, that will split your delimitted #msisdn into a table to select from.
Have a look at this link
How to pass a list of values or array to SQL Server stored procedure?
IN in TSQL needs to take multiple arguments per item. At the moment, if you pass it "123,456,789", it is looking for the single row with value "123,456,789". It isn't looking for "123", "456" or "789".
Look for something like a split udf - plenty on the internet. This takes your delimited string and returns a column of values. Typically you then join the the udf results (rather than use IN).
DON'T use EXEC here, as you shouldn't trust the input.
Related
I have a SSRS Report which is using a dynamic SQL Server stored procedure with one parameter only and it works fine.
I want to create a report which whenever I run it, it loop through multiple values for that parameter and creates multiple results, instead of doing that manually.
I found below links from Stack Overflow, but none of them help a lot.
Link1
Link2
I also read some I can use List in SSRS, but I am not sure how to do it in my case.
Any idea?
This might not be an answer as you have not provided enough detail, but I'm sure this idea will help you.
I think you'd better to change your stored procedure to accept multiple values and in your procedure return multiple result sets or combine record sets for each parameter value.
For example, assume you have procedure Proc1, which gets a number as parameter.
create procedure Proc1 (#aYear int)
as
begin
select *
from Orders
where OrderYear = #aYear
end
Now, what you need to do is changing your procedure to accept multiple years (for instance as a comma separated value)
create procedure Proc1 (#csv_years varchar(100))
as
begin
-- use some function or techniques to split the #csv_years
-- and store it into a temp table #years ([Year] int)
-- now, join your main data with this #years table
select #years.[Year], Orders.*
from Orders
inner join #years on #years.Year = Orders.OrderYear
end
Now, your are returning the result for multiple years and you can show that in your report by grouping on [Year] column
You need to use data driven subscription. I had cases with dynamic parameters and the only solution was data driven subscription.
I am building an application using Microsoft Access as a front-end and SQL Server as the back end.
I have a Stored Procedure that inserts customer information. One of the pieces of information that will be inserted for each customer are their Credit Card numbers. The number of credit cards for each customer could be anywhere from 1-50.
I am planning on using a Dynamic array in VBA to add the credit card numbers. The trouble I am having is I am not quite sure how to pass the values to the stored procedure.
My first thought was to create a ton of parameters (CC Number 1, CC Number 2, CC Number 3,etc) but obviously this isn't the correct way to do it.
After the credit card numbers have been added to the Dynamic Array, I can ReDim it to get the count of how many credit card numbers I will need to insert.
What would be the best way to pass lets say, 14 credit card values to one parameter and insert each value as a new row?
Unfortunately, AFAIK, VBA doesn't support table valued parameters (ADO.NET does, but not the vanilla VB6 implementation that we have to use in Access).
You could send a stream of function calls to the server by looping through a recordset or something, but that's going to be painfully slow. If you don't mind repeating yourself, though, you could send one big command that contains a bunch of EXEC statements chained one after the other (if you're using DAO, be sure to specify SET NOCOUNT ON at the start of the query).
If you're looking for a pure-SQL solution, here's the strategy I take for these sorts of problems:
Concatenate the array of values into a string with some sort of separator (e.g. "," or "|").
Pass the string to a function or query that converts it to a table of values.
INSERT or MERGE the table of values into the final target table.
Here's an example of how you can do it:
SET NOCOUNT ON
DECLARE #x XML;
DECLARE #CreditCards AS TABLE (CreditCardNumber VARCHAR(16));
DECLARE #FinalTable AS TABLE (CreditCardNumber VARCHAR(16));
DECLARE #CreditCardList AS VARCHAR(8000);
DECLARE #Divider AS Varchar(10);
SET #Divider=',';
SET #CreditCardList='1234567890123456,1111111111111111,2222222222222222,123456789012345';
IF NOT #CreditCardList IS NULL
BEGIN
SELECT #x = CAST('<A>'+ REPLACE(#CreditCardList,#Divider,'</A><A>')+ '</A>' AS XML);
INSERT INTO
#CreditCards
SELECT
t.value('.', 'varchar(16)') AS inVal
FROM
#x.nodes('/A') AS x(t) ;
END
INSERT INTO
#FinalTable
SELECT
CreditCardNumber
FROM
#CreditCards
SELECT * FROM #FinaLTable
XML isn't the fastest way to do the conversion, but it has the benefit of being relatively straightforward. Jeff Moden provides several pretty inspired approaches to the problem in his blog post Tally OH! An Improved SQL 8K “CSV Splitter” Function.
Hope that helps!
Use XML to pass all customer information in one document. This way you can pass any number of parameters and query it on server as a table.
I have stored procedure which returns multiple data sets and I need to create tables based on that data sets to get data types. Found this code
SELECT *
INTO newTable
FROM OPENROWSET ('SQLNCLI', 'Server=localhost;Trusted_Connection=yes;',
'EXEC ISS.dbo.sp')
but it works only for first result set and I need tables for all results
As far as I know, cleaner way of using stored procedure output to populate data to a table is a much required solution. There are many ways including the ones you have shown above, but every technique has its own plus and minus.
The solution I have used is create global temporary table
I don't know if it suits for our need.
Once OpenTable is created you can do this over and over again:
Insert into OpenTable
Exec dbo.proc55
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 Stored Procedure that rolls-back a series of operations. I want to call this from within another SP.
The problem is that the inner SP returns a record set with a single value that indicates the degree of success.
This approach worked well and has some advantages in our context, but in retrospect, I would have done it the conventional way with a Return value or an Output parameter.
I could always change this SP to use this approach and modify the calling code, but a) I don't want to dabble with any more code than I have to, and b) at an intellectual level, I'm curious to see what alternative solution there may be, if any.
How (if at all) can I call this SP and determine the value of the singleton recordset returned?
Thanks
A stored procedure returns a record set like any other, so you can actually do this:
INSERT INTO MyTable (
MyValue
)
EXEC dbo.MyStoredProcedure
The EXEC takes the place of a SELECT statement. To get the value, just SELECT from the table you inserted into. Typically, this would be a temp table.
The other option is to convert the stored procedure that returns a recordset into a function that returns a table.
Ant's approach is probably best if you want to minimize the changes to your system.
Normally you would use a temporary table for that approach since you can't use an exec statement to insert into a table variable.
Here's a variation which will work well if you need to use this for MULTIPLE recordsets.
CREATE TABLE #outsidetable (...)
exec spInsideProcedure
SELECT * FROM #outsidetable
inside spInsideProcedure
INSERT INTO #outsidetable SELECT <blah blah blah>
I tried Ant's approach and it worked a treat:
Declare #Success tinyint
Declare #Response Table (Success int)
Insert into #Response(Success)
Exec Fix_RollbackReturn 12345, 15
Select #Success=Success from #Response
As you can see I used a Table Variable rather than a temporary table because slightly more efficient than a temporary table.
Thanks for all your help guys.
EDIT: It appears that Dave was right after all. That is, my Exec-into-Table-variable approach worked on my SQL2005 development machine, but when moved to the Live (SQL2000) machine it objected, so I had to change to the temporary table approach.
It's a little annoying, especially since in a couple of weeks we are upgrading to SQL2005 across the board(!).