C# SQL parameter limitations? - c#

I have the following SQL command in my .Net application:
sqlCommand.Text = "DECLARE #method NVARCHAR(MAX);
SET #method = ' WITH selectRows AS (SELECT *, row=ROW_NUMBER() OVER(ORDER BY(SELECT 1)) FROM [' + #param + ']) SELECT ' + #param_2 + ' FROM selectRows WHERE row BETWEEN 0 AND 30;'
EXEC(#method);";
sqlCommand.Parameters.AddWithValue("#param", tableName);
sqlCommand.Parameters.AddWithValue("#param_2", columnString);
Whenever '#param_2' is long the query won't execute. Lets say the column string looks like this:
[class],[partnr],[accessoriesidentifier],[canbelinedup],[certificate],[certificate_ce],[certificate_ul],[certificate_vde],[codeletter],[construction],[craftcooling],[craftelectro],[craftfluid],[crafthydraulic],[craftlubrication],[craftmechanic],[craftpneumatic],[craftprocess],[create],[depth],[depthspacingfront],[depthspacingrear],[description1],[description2],[description3],[discount],[ecabinetmacro],[erpnr],[externaldocument1],[externaldocument2],[externaldocument3],[externalplacement],[functiongroup],[graphicmacro],[groupnumber],[groupsymbolmacro],[height],[heightspacingabove],[heightspacingbelow],[identcode],[identtype],[isaccessory],[lastchange],[lifetime],[macro3d],[maintenance],[manufacturer],[mountinglocation],[mountingspace],[note],[ordernr],[packagingprice1],[packagingprice2],[packagingquantity],[picturefile],[piecetype],[priceunit],[productgroup],[productsubgroup],[producttopgroup],[purchaseprice1],[purchaseprice2],[quantityunit],[reportid],[salesprice1],[salesprice2],[snapheight],[snapheightmiddleoffset],[spare],[stress],[supplier],[terminal],[typenr],[uniqueid],[usage],[wear],[weight],[width],[widthspacingleft],[widthspacingright],[barcount],[bardistance],[bargeometry],[barmountingplatedistance],[bottompaneldepth],[bottompaneldistance],[bottompanelprojectionback],[bottompanelprojectionfront],[bottompanelprojectionleft],[bottompanelprojectionright],[busbarholderpartnr],[busbarholdervariant],[busbarrailpartnr],[busbarrailvariant],[deliverylength],[dooroffsetright],[dooroffsettop],[doorthickness],[doortrabbet],[doortype],[hingeposition],[insertpointoffsetx],[profiledepth],[profiledistance],[profileheight],[rearpaneldistance],[rearpaneldpepth],[rearpanelprojectionbottom],[rearpanelprojectionleft],[rearpanelprojectionright],[rearpanelprojectiontop],[sidepaneldepth],[sidepaneldistance],[sidepanelprojectionback],[sidepanelprojectionbottom],[sidepanelprojectionfront],[sidepanelprojectiontop],[toppaneldistance],[toppaneldpepth],[toppanelprojectionback],[toppanelprojectionfront],[toppanelprojectionleft],[toppanelprojectionright],[vprofiledepth],[vprofilewidth],[wallthickness],[widthbottom],[widthtop],[variant],[adjustrange],[adressrange],[advancecontacts],[airgap],[assemblyspreaded],[awgfrom],[awgtill],[bendingradius],[cabledesignation],[cabledisplayform],[cablelength],[cabletype],[cableweight],[coding],[color],[connection],[connectioncrosssection],[connectiondesignation],[connectionmethod],[contactarrangement],[contacttype],[coppernumber],[creepagedistance],[crosssectionfrom],[crosssectiontill],[currentcsa],[currentiec],[currentul],[degofprotection],[design],[doordepth],[doorheight],[doormountingspace],[doorwidth],[electricalcurrent],[electricalpower],[firmwareversion],[flow],[holdingpower],[innerdiameter],[intrinsicsafety],[material],[norm],[outerdiameter],[paneldepth],[panelheight],[panelmountingspace],[panelwidth],[pincount],[pipeclass],[plcdeviceid],[plcisbuscoupler],[plcisbusdistributor],[plciscpu],[plcispowersupply],[plcobjectdescription],[plctype],[powerdissipation],[pressure],[pressurelevel],[shortcircuitresistant],[standardinvers],[strokelength],[symbolfile],[symbolnr],[technicalcharacteristics],[thread],[triggercurrent],[voltage],[voltagecsa],[voltageiec],[voltagetype],[voltageul],[widthrating],[wirecount],[wirecrosssection],[wirecrosssectionanddiameter],[wirecrosssectionunit],[variant_1],[characteristics],[connectiondescription],[connectiondesignation_1],[description],[functiondefcategory],[functiondefgroup],[functiondefid],[hasled],[hasplugadapter],[idx1],[idx2],[intrinsicsafety_1],[nesteddevicetag],[pos],[safetyrelevant],[symbol],[symbolmacro],[terminalfunction],[terminalnr],[partnr_1],[variant_2],[count],[parentvariant],[pos_1],[22235.0],[22236.0],[22237.0],[22238.0],[22239.0],[22240.0],[22241.0],[22196.1],[22196.2],[22158.1],[22158.2],[22159.1],[22159.2],[22195.1],[22195.2],[22228.1],[22228.2],[22228.3],[22228.4],[22228.5],[22228.6],[22228.7],[22228.8],[22228.9],[22228.10]
The query won't execute on the server (SQL server 2005). When I remove 10 columns, the query executes without any issues. I used the sql profiler to look for any problems that the sql server receives from my application, but no problems found there. I'm really confused why it isn't working.
What I try to achieve is to get a result set of all the columns from the database table WITHOUT the row column. Because if I change the SELECT #param_2 to SELECT *, i'll get all the columns plus and extra column showing the row number. To get rid of this row number I thought I just send all the column names to the SELECT statement of the query. However I'm now running in the above problem. I hope someone knows a solution that either solves the problem from above or how to get a result set of all the columns excluding the row number with a better query than I'm using.
P.s: the size of the ('failing') column string is 3612 characters.
I do not have too much experience with SQL itself. So excuse me if I'm making silly mistakes.
EDIT:
The column names depends on the user, so they can't be hardcoded in the query.

Neither your string literals nor your passed parameters are, themselves, of type nvarchar(max). You're therefore falling foul of this remark about string concatenation:
If the result of the concatenation of strings exceeds the limit of 8,000 bytes, the result is truncated. However, if at least one of the strings concatenated is a large value type, truncation does not occur.
What I'd probably do is change the parameter to explicitly be an nvarchar(max):
sqlCommand.Parameters.Add("#param_2", SqlDbType.NVarChar,-1).Value =
columnString;
Alternatively you could fix it with:
SET #method = CONVERT(nvarchar(max),
' WITH selectRows AS (SELECT *, row=ROW_NUMBER() OVER(ORDER BY(SELECT 1)) FROM [') + ...

Maybe this doesn't answer the question directly but it might be helpful anyway. Why do you need to use dynamioc sql at all? Why can't you use this:
string sql = #"
WITH CTE AS
(
SELECT *,
row=Row_number() OVER (ORDER BY (SELECT 1))
FROM dbo.TableName
SELECT [class],[partnr],[accessoriesidentifier],[canbelinedup],[certificate],[certificate_ce],[certificate_ul],[certificate_vde],[codeletter],[construction],[craftcooling],[craftelectro],[craftfluid],[crafthydraulic],[craftlubrication],[craftmechanic],[craftpneumatic],[craftprocess],[create],[depth],[depthspacingfront],[depthspacingrear],[description1],[description2],[description3],[discount],[ecabinetmacro],[erpnr],[externaldocument1],[externaldocument2],[externaldocument3],[externalplacement],[functiongroup],[graphicmacro],[groupnumber],[groupsymbolmacro],[height],[heightspacingabove],[heightspacingbelow],[identcode],[identtype],[isaccessory],[lastchange],[lifetime],[macro3d],[maintenance],[manufacturer],[mountinglocation],[mountingspace],[note],[ordernr],[packagingprice1],[packagingprice2],[packagingquantity],[picturefile],[piecetype],[priceunit],[productgroup],[productsubgroup],[producttopgroup],[purchaseprice1],[purchaseprice2],[quantityunit],[reportid],[salesprice1],[salesprice2],[snapheight],[snapheightmiddleoffset],[spare],[stress],[supplier],[terminal],[typenr],[uniqueid],[usage],[wear],[weight],[width],[widthspacingleft],[widthspacingright],[barcount],[bardistance],[bargeometry],[barmountingplatedistance],[bottompaneldepth],[bottompaneldistance],[bottompanelprojectionback],[bottompanelprojectionfront],[bottompanelprojectionleft],[bottompanelprojectionright],[busbarholderpartnr],[busbarholdervariant],[busbarrailpartnr],[busbarrailvariant],[deliverylength],[dooroffsetright],[dooroffsettop],[doorthickness],[doortrabbet],[doortype],[hingeposition],[insertpointoffsetx],[profiledepth],[profiledistance],[profileheight],[rearpaneldistance],[rearpaneldpepth],[rearpanelprojectionbottom],[rearpanelprojectionleft],[rearpanelprojectionright],[rearpanelprojectiontop],[sidepaneldepth],[sidepaneldistance],[sidepanelprojectionback],[sidepanelprojectionbottom],[sidepanelprojectionfront],[sidepanelprojectiontop],[toppaneldistance],[toppaneldpepth],[toppanelprojectionback],[toppanelprojectionfront],[toppanelprojectionleft],[toppanelprojectionright],[vprofiledepth],[vprofilewidth],[wallthickness],[widthbottom],[widthtop],[variant],[adjustrange],[adressrange],[advancecontacts],[airgap],[assemblyspreaded],[awgfrom],[awgtill],[bendingradius],[cabledesignation],[cabledisplayform],[cablelength],[cabletype],[cableweight],[coding],[color],[connection],[connectioncrosssection],[connectiondesignation],[connectionmethod],[contactarrangement],[contacttype],[coppernumber],[creepagedistance],[crosssectionfrom],[crosssectiontill],[currentcsa],[currentiec],[currentul],[degofprotection],[design],[doordepth],[doorheight],[doormountingspace],[doorwidth],[electricalcurrent],[electricalpower],[firmwareversion],[flow],[holdingpower],[innerdiameter],[intrinsicsafety],[material],[norm],[outerdiameter],[paneldepth],[panelheight],[panelmountingspace],[panelwidth],[pincount],[pipeclass],[plcdeviceid],[plcisbuscoupler],[plcisbusdistributor],[plciscpu],[plcispowersupply],[plcobjectdescription],[plctype],[powerdissipation],[pressure],[pressurelevel],[shortcircuitresistant],[standardinvers],[strokelength],[symbolfile],[symbolnr],[technicalcharacteristics],[thread],[triggercurrent],[voltage],[voltagecsa],[voltageiec],[voltagetype],[voltageul],[widthrating],[wirecount],[wirecrosssection],[wirecrosssectionanddiameter],[wirecrosssectionunit],[variant_1],[characteristics],[connectiondescription],[connectiondesignation_1],[description],[functiondefcategory],[functiondefgroup],[functiondefid],[hasled],[hasplugadapter],[idx1],[idx2],[intrinsicsafety_1],[nesteddevicetag],[pos],[safetyrelevant],[symbol],[symbolmacro],[terminalfunction],[terminalnr],[partnr_1],[variant_2],[count],[parentvariant],[pos_1],[22235.0],[22236.0],[22237.0],[22238.0],[22239.0],[22240.0],[22241.0],[22196.1],[22196.2],[22158.1],[22158.2],[22159.1],[22159.2],[22195.1],[22195.2],[22228.1],[22228.2],[22228.3],[22228.4],[22228.5],[22228.6],[22228.7],[22228.8],[22228.9],[22228.10]
FROM CTE
WHERE row BETWEEN #StartRow AND #EndRow;";
using(var sqlCommand = new SqlCommand(sql, con))
{
sqlCommand.Parameters.Add("#StartRow", SqlDbType.int).Value = 1;
sqlCommand.Parameters.Add("#EndRow", SqlDbType.int).Value = 30;
// ...
}
Since the column-names are specified by the user you cannot add them as parameter without dynamic sql. But you know all valid column-names, so you could check if all are valid. If you don't know all columns of a the table, have a look here and use reader.GetSchemaTable to load all columns on application start.
Then you can simply add it to the sql:
string sql = #"
WITH CTE AS
(
SELECT *,
row=Row_number() OVER (ORDER BY (SELECT 1))
FROM dbo.TableName
SELECT {0}
FROM CTE
WHERE row BETWEEN #StartRow AND #EndRow;";
sql = string.Format(sql, string.Join(",", columnList));

Related

Cast uniqueidentifier to string and use in Where clause

figured out answer and edited question so it works now.
Here is my example
CustomerID column in my database is set to uniqueidentifier.
C#
string cid = ( This is a variable; it could be ANY guid the user chooses. )
Query String
" SELECT * FROM [db]
WHERE (CAST(CustomerID AS VARCHAR(100)) LIKE '%"+cid+#"%');"
The CustomerID field does not evaluate for a rows with the same cid. So the cid is having trouble being evaluated with the uniqueidentifier (CustomerID).
Don't build your query by string concatenating user input into the query. It can lead to sql injection which is a serious issue.
Instead you should use parametrized queries, where you pass the user input to the query in the form of a parameter. The underlying framework/driver/etc will then make sure that the user input is prepared in a way that cannot accidentally become sql code.
Something like this:
Guid cidAsGuid = new Guid(cid);
MySqlCommand command = new MySqlCommand("SELECT * FROM [db] WHERE CustomerId = #customerID");
command.Parameters.AddWithValue("#customerID", cidAsGuid);
And then you can use the command to execute a reader or fill an adapter or some other thing you need to do.
This has the added benefit that an index on the CustomerId column can be used to speed up the query, whereas if you search by converting the CustomerId from a Guid to a string means the database will have to scan the whole table. For small tables you won't notice much difference but for large tables the difference will be significant.
I'm seeing a few possible issues;
There's no condition defined for the ISNULL e.g. ISNULL(Column,valueifnull).
Also the actual query must specify a column to use ISNULL in that structure.
There's a missing "closing bracket" on the ISNULL.
Something such as this should work:
SELECT ISNULL(
(
SELECT Column1 FROM MyTable
WHERE (CAST(CustomerID AS VARCHAR(100)LIKE '%"+cid+#"%')
)
,'')
You don't need like if CustomerID is uniqueidentifier too.
WHERE (CAST(CustomerID AS VARCHAR(36)) = #cid)

SQL query to return from predefined data when not found in database data

I need some help wrapping my head around doing the following.
I have a predefined list if ID numbers, we'll call them Alias, which I get from a CSV file. What I'm trying to do is compare that list to my database and find which ones exist in the CSV but NOT in the SQL database.
First thing is I'm unsure as to how to define a list of say 1,2,3,4,5 as a table with the column name as Alias so that I can join / select from that.
Secondly, how would you go about writing this query? I was thinking of having to structure it something like the following:
SELECT * FROM (1,2,3,4,5) WHERE Alias NOT IN (
SELECT Alias FROM table1 WHERE Alias IN (1,2,3,4,5));
I'm aware that this query wouldn't work, think of it more like pseudo-code, but even if something like that were to work, writing out that list twice could prove to be troublesome (I can have upwards of 50K alias' in the list) and most likely horribly inefficient.
Thanks for any advice!
After a coffee and a quick break I think I have the best solution.
Considering this is going to be a stored procedure anyway, the stored procedure will take the following action.
Create TempTable IF NOT EXISTS, TRUNCATE if it does
INSERT (CSVList) INTO TempTable
SELECT Alias FROM TempTable WHERE Alias NOT IN (SELECT Alias FROM MainTable)
This way I can specify that list as a table and select from it only once :)
Suppose you have your CSV values (comma separated) in T table, and T1 is your MainTable. Then following is the code that may help you. And this SQLFiddle that I tried.
Stage 1: Make your horizontal comma separated data into column data.
SELECT
Split.a.value('.', 'VARCHAR(100)') AS data
FROM (SELECT
CAST ('<M>' + REPLACE([id], ',', '</M><M>') + '</M>' AS XML) AS String
FROM T) AS A CROSS APPLY String.nodes ('/M') AS Split(a)
Here T is your table and id is the column name that has comma separated data.
Stage 2: Now merge this query with your main table to get the result.
select * from
(SELECT
Split.a.value('.', 'VARCHAR(100)') AS data
FROM (SELECT
CAST ('<M>' + REPLACE([id], ',', '</M><M>') + '</M>' AS XML) AS String
FROM T) AS A CROSS APPLY String.nodes ('/M') AS Split(a)) as CSV
where data not in (select * from T1)
For performance and efficiency, please use NOT EXISTS in comparing the 2 table outputs.
Something like this:
SELECT * FROM Tbl1 t1 WHERE NOT EXISTS (SELECT * FROM Tbl2 t2 WHERE t2.Col1 = t1.Col1)

Building a SQL stored procedure query with list inputs

How do I pass a list of names to a SQL parameter so I can do WHERE IN (#myList)?
I'm making an "advanced search" for our webpage where the user can list, separated by commas, things they would like to find for several inputs. For example there could be 5 input's (First Name, account number, Last name, ...) and for each of those inputs they can list several and separate them by commas.
My approach so far is to take in this string for each input, and format it so I can use the "IN" clause on that string. Is this possible?
IE the user for "First Name" enters "Bob, Joe,Fred", I would transform that input into
"'Bob', 'Joe', 'Fred'"
and then send that as a parameter to a stored procedure.
Declare #firstNames
Select * from Users
where User.FirstName in firstNames
OR should I put all these names into a DataTable in C# and pass that to SQL? If I should go this route, some examples would help a lot!
Thanks!
Whenever my query gets a little complicated like this, I prefer to choose either of these ways:
Create a query dynamically in C#, based on string concatenation for better readability rather than LINQ expression trees, and send it to SQL Server, or
Create a SP, or a Table-Valued Function in SQL Server, and then call it from C#, passing arguments to it.
In case of creating the query in C#, it's not extensible, and every time you want to change the logic, you should recompile your application.
In case of SP, because it's going to be a dynamic query and where clause should be created based on input parameters, I use exec (#query)
Assuming you are using SQL Server, you can create a tabular function like to split comma seperated values into table
CREATE FUNCTION dbo.Split(#String nvarchar(4000), #Delimiter char(1))
RETURNS #Results TABLE (Items nvarchar(4000))
AS
BEGIN
DECLARE #INDEX INT
DECLARE #SLICE nvarchar(4000)
-- HAVE TO SET TO 1 SO IT DOESNT EQUAL Z
-- ERO FIRST TIME IN LOOP
SELECT #INDEX = 1
WHILE #INDEX !=0
BEGIN
-- GET THE INDEX OF THE FIRST OCCURENCE OF THE SPLIT CHARACTER
SELECT #INDEX = CHARINDEX(#Delimiter,#STRING)
-- NOW PUSH EVERYTHING TO THE LEFT OF IT INTO THE SLICE VARIABLE
IF #INDEX !=0
SELECT #SLICE = LEFT(#STRING,#INDEX - 1)
ELSE
SELECT #SLICE = #STRING
-- PUT THE ITEM INTO THE RESULTS SET
INSERT INTO #Results(Items) VALUES(#SLICE)
-- CHOP THE ITEM REMOVED OFF THE MAIN STRING
SELECT #STRING = RIGHT(#STRING,LEN(#STRING) - #INDEX)
-- BREAK OUT IF WE ARE DONE
IF LEN(#STRING) = 0 BREAK
END
RETURN
END
Then you can call the function like this in your SP
Select * from Users
where User.FirstName in (
SELECT items FROM [dbo].[Split] (#firstNames, ','))
In C# you can add a list of parameters to your SQLCommand.CommandText. Assuming customerName is a string of "'Bob', 'Joe', 'Fred'" you do something like this:
Dim command As New SqlCommand(commandText, connection)
' Add FirstName parameter for WHERE clause.
command.Parameters.Add("#FirstName", SqlDbType.nvarchar)
command.Parameters("#FirstName").Value = FirstName
In Query Analyzer you can't have a list in a #parameter, which is a nuisance, but you can pass one in from another source; for example your C# calling code. In your WHERE clause you do WHERE IN (#Name). In my testing I create a temp table and do WHERE in (SELECT FirstName FROM #MyCustomerTempTable), then when hooking it up replace the sub-query with the singleton parameter.
Source: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.parameters(v=vs.110).aspx
Another approach (which I used most frequently) to adding parameters to the command is:
' Add the input parameter and set its properties.
Dim parameter As New SqlParameter()
parameter.ParameterName = "#FirstName"
parameter.SqlDbType = SqlDbType.NVarChar
parameter.Value = firstName
' Add the parameter to the Parameters collection.
command.Parameters.Add(parameter)
Source (scroll down to the example):
http://msdn.microsoft.com/en-us/library/yy6y35y8(v=vs.110).aspx
You can also dynamically build your query in C# or do a string.replace and replace #parameter with 'my list of names', but neither of these methods are preferred to adding parameter objects to the SQL Command object. I would suggest getting a solid understanding of the SQL Command object so you can build that instead of manipulating strings.

SqlCommand shows bad performance when passing text parameter for LIKE

I've encountered quite a wierd problem:
I form SQL server command dynamically and one of its part is a group of LIKE tests, that are used as textual search on several columns and tables. It looks like:
SET #text = '%' + REPLACE(REPLACE(REPLACE(#text, '!', '!!'), '%', '!%'), '_', '!_') + '%'
INSERT INTO
#textFiltered
FROM
#documents d
LEFT JOIN docData t1 WITH (NOLOCK)
ON t1.ID = d.ID AND
(t1.Topic like #text escape '!'
OR t1.Subject like #text escape '!')
LEFT JOIN docData2 t2 WITH (NOLOCK)
ON t2.ID = d.ID AND
t2.Name like #text escape '!'
WHERE
t1.ID IS NOT NULL
OR t2.ID IS NOT NULL
(Surely, that's not the best way to do textual search, still that's not the point)
Now, when I create SQLCommand in C#, like this:
using (var cmd = new SqlCommand())
{
cmd.CommandText = cmdText;
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
cmd.Parameters.Add("text", NVarChar, 4000).Value = searchText;
var reader = cmd.ExecuteReader();
....
}
performce of executing is very poor (say, 8 seconds), while executing same query in SQL Management Studio much faster (say, 500 ms).
However, if instead of passing text as parameter, I embed it into text of SQL with:
DECLARE #text nvarchar(max)
SET #text = '<embedded-text>'
then SqlCommand also runs fast.
What's even more strange this behavior seems to be correlated with set of columns that are used in LIKE clauses (didn't figure how). Types of those columns can be nvarchar(size), nvarchar(max), ntext.
I suspect that problem is with parameter - maybe it's type is incorrect or smth else.
P.S. Tried to create parameter with size = length of searched text + 1 - didn't help.
My best guess will be that it is related to the query plan that SQL Server is choosing for you.
there is big difference between using constant varchar which the SQL server can evaluate against existing statistics, and using arbitrary variable which the server know nothing about.
you can try OPTION (RECOMPILE) hint. although this hint will cause the Stored procedure to be compiled on every call, it'll also allow the SQL Server to search for the best plan for the given values, and maybe in your case it will be good trade off.
you could also add the query plan for both option of the stored procedure, and maybe someone will be able to see the difference, and pin point the exact problem.

Creating a SQL table from a comma concatenated list

I am running SQL Server and I have a stored procedure. I want do a select statement with a WHERE IN clause. I don't know how long the list will be so right now I have tried something as follows
SELECT * FROM table1 WHERE id IN (#idList)
in this solution #idList is a varChar(max). but this doesn't work. I heard about passing in table values, but I am confused about how to do that. Any help would be great
I would suggest using a function to split the incoming list (use the link that Martin put in his comment).
Store the results of the split function in a temporary table or table variable and join it in your query instead of the WHERE clause
select * into #ids from dbo.Split(',', #idList)
select t.*
from table1 t
join #ids i
on t.id = i.s
The most efficient way would be to pass in a table valued parameter (if you're on SQL Server 2008), or an XML parameter (if you're on SQL Server 2005/2000). If your list is small (and you're on SQL Server 2005/2000), passing in your list as a comma (or otherwise) delimited list and using a split function to divide the values out into rows in a temporary table is also an option.
Whichever option you use, you would then join this table (either the table parameter, the table resulting from the XML select, or the temporary table created by the values from the split) to your main query.
Here is a table valued function that takes a nvarchar and returns a table to join on:
Create function [ReturnValues]
(
#Values nvarchar(4000)
)
Returns #ValueTable table(Value nvarchar(2000))
As
Begin
Declare #Start int
Declare #End int
Set #Start = 1
Set #End = 1
While #Start <= len(#Values)
Begin
Set #End = charindex(',', #Values, #Start)
If #End = 0
Set #End = len(#Values) + 1
Insert into #ValueTable
Select rtrim(ltrim(substring(#Values, #Start, #End - #Start)))
Set #Start = #End + 1
End
Return
End
GO
Binding an #idList parameter as you suggested is not possible with SQL.
The best would be bulk inserting the ids into a separated table and than query that table by using an subselect, or joining the IDs.
e.g.
INSERT INTO idTable (id, context) values (#idValue, 1);
INSERT INTO idTable (id, context) values (#idValue, 1);
INSERT INTO idTable (id, context) values (#idValue, 1); // as often as you like
SELECT * FROM table1, idTable WHERE table1.id == idTable.id and idTable.context = 1
The context must be a unique value that identifies the Id Range. That is important for running the stored proc parallel. Without the context information, running the stored procecure in parallel would mix the values from different selections.
If the number of parameters are reasonably small (< 100) you can use several parameters
SELECT * FROM table1 WHERE IN id IN (#id1, #id2, #id3)
If it is longer, look for a split function.

Categories