How to use Split function in stored procedure? - asp.net

I am selecting the values like below:
select browser, firstname, lastname from details
Here the browser value will be like this:
33243#Firefox#dsfsd
34234#google#dfsd
And separately I have used split function for single value as below:
select * from dbo.split('33243#Firefox#dsfsd','#')
Result is:
items
===========
33243
firefox
dsfsd
So I have used split function like below
select split(browser, '#'), firstname, lastname from details
but its not working...
What I need is
33243#Firefox#dsfsd
instead of displaying the value like this into the grid,
have to display only Firefox into the grid.

Since you know you want the second element each time, you could write a function like this:
CREATE FUNCTION [dbo].[fn_SplitElement]
(
#inputString nvarchar(2000), --The input string
#elem int, --The 1-based element index to return,
#delimiter nvarchar(1) --The delimiter char
)
RETURNS nvarchar(2000)
AS
BEGIN
-- Declare the return variable here
DECLARE #result nvarchar(2000)
-- Add the T-SQL statements to compute the return value here
SELECT #result = value
FROM
(
SELECT *,ROW_NUMBER() OVER(ORDER By Position) as rownum FROM dbo.split(#inputString,#delimiter)
) as t
WHERE rownum=#elem
-- Return the result of the function
RETURN #result
END
GO
Then you can call:
select [dbo].[fn_SplitElement](browser,2,'#') as 'BrowserName', firstname, lastname from details

You do not state which version of SQL Server you are using or which split function. However, most split functions return a table rather than rows so you'll need to use a JOIN to join the two tables (the first is the split, the second is the rest of the fields).
For more information in SQL split functions, see Erland Sommarskog's page at http://www.sommarskog.se/arrays-in-sql.html .

You can Create a Split function and that will be use when you want.
CREATE FUNCTION [dbo].[Split]
(
#List nvarchar(max),
#SplitOn nvarchar(1)
)
RETURNS #RtnValue table (
Id int identity(1,1),
Value nvarchar(max)
)
AS
BEGIN
While (Charindex(#SplitOn,#List)>0)
Begin
Insert Into #RtnValue (value)
Select
Value = ltrim(rtrim(Substring(#List,1,Charindex(#SplitOn,#List)-1)))
Set #List = Substring(#List,Charindex(#SplitOn,#List)+len(#SplitOn),len(#List))
End
Insert Into #RtnValue (Value)
Select Value = ltrim(rtrim(#List))
Return
END
after that you can call the function in your query as below.
SELECT * FROM anotherTable WHERE user_id IN(dbo.split(#user_list,','))

I Have used below query instead of using split function.. its working perfectly..
select
SUBSTRING(SUBSTRING(browser, CHARINDEX ('#', browser)+1,LEN(browser)-charindex('#', browser)),
0,
CHARINDEX('#',SUBSTRING(browser, CHARINDEX ('#', browser)+1,LEN(browser)-CHARINDEX('#', browser)))),
firstname, lastname from details

Related

Using a CASE with the IN clause in T-SQL

In My WHERE Clause I am using a CASE that will return all rows if parameter is blank or null. This works fine with single valuses. However not so well when using the IN clause. For example:
This works very well, if there is not match then ALL records are returned!
AND
Name = CASE WHEN #Name_ != '' THEN #Name_ ELSE Name END
AND
This works also, but there is no way to use the CASE expression, so if i do not provide some value i will not see any records:
AND
Name IN (Select Names FROM Person Where Names like #Name_)
AND
Can I use a CASE with the 2nd example? So if there is not a match all Names will be returned?
Maybe coalesce will resolve your problem
AND
Name IN (Select Names FROM Person Where Names like coalesce(#Name,Name))
AND
As Mattfew Lake said and used, you can also use isnull function
Name IN (Select Names FROM Person Where Names like isnull(#Name,Name))
No need for a CASE statement, just use a nested OR condition.
AND ( Name IN (Select Names FROM Person Where Names like #Name_)
OR
#Name_ IS NULL
)
AND
Perhaps something like this?
AND
Name IN (Select Names FROM Person Where Names LIKE
CASE WHEN #Name_ = '' OR #Name_ IS NULL THEN '%' ELSE #Name_ END)
AND
This will use the pattern '%' (which will match everything) only when a null or blank #Name_ parameter is provided, otherwise it will use the pattern specified by #Name_.
Alternatively, something like this should work:
AND
Name IN (Select Names FROM Person Where Names LIKE
ISNULL( NULLIF( #Name_, '' ), '%' ))
AND
This works
DECLARE #Name NVARCHAR(100)
SET #Name = ''
DECLARE #Person TABLE ( NAME NVARCHAR(100) )
INSERT INTO #Person VALUES ( 'fred' )
INSERT INTO #Person VALUES ( 'jo' )
DECLARE #Temp TABLE
(
id INT ,
NAME NVARCHAR(100)
)
INSERT INTO #Temp ( id, NAME ) VALUES ( 1, N'' )
INSERT INTO #Temp ( id, NAME ) VALUES ( 5, N'jo' )
INSERT INTO #Temp ( id, NAME ) VALUES ( 2, N'fred' )
INSERT INTO #Temp ( id, NAME ) VALUES ( 3, N'bob' )
INSERT INTO #Temp ( id, NAME ) VALUES ( 4, N'' )
SELECT * FROM #Temp
WHERE name IN ( SELECT name
FROM #Person
WHERE name = CASE WHEN #name != '' THEN #Name
ELSE name
END )
You should almost definitely use an IF statement with two selects. e.g.
IF #Name IS NULL
BEGIN
SELECT *
FROM Person
END
ELSE
BEGIN
SELECT *
FROM Person
--WHERE Name LIKE '%' + #Name + '%'
WHERE Name = #Name
END
N.B. I've changed like to equals since LIKE without wildcards it is no different to equals,
, it shouldn't make any difference in terms of performance, but it stops ambiguity for the next person that will read your query. If you do want non exact
matches then use the commented out WHERE and remove wildcards as required.
The reason for the IF is that the two queries may have very different execution plans, but by combining them into one query you are forcing the optimiser to pick one plan or the other. Imagine this schema:
CREATE TABLE Person
( PersonID INT IDENTITY(1, 1) NOT NULL,
Name VARCHAR(255) NOT NULL,
DateOfBirth DATE NULL
CONSTRAINT PK_Person_PersonID PRIMARY KEY (PersonID)
);
GO
CREATE NONCLUSTERED INDEX IX_Person_Name ON Person (Name) INCLUDE (DateOfBirth);
GO
INSERT Person (Name)
SELECT DISTINCT LEFT(Name, 50)
FROM sys.all_objects;
GO
CREATE PROCEDURE GetPeopleByName1 #Name VARCHAR(50)
AS
SELECT PersonID, Name, DateOfBirth
FROM Person
WHERE Name IN (SELECT Name FROM Person WHERE Name LIKE ISNULL(#Name, Name));
GO
CREATE PROCEDURE GetPeopleByName2 #Name VARCHAR(50)
AS
IF #Name IS NULL
SELECT PersonID, Name, DateOfBirth
FROM Person
ELSE
SELECT PersonID, Name, DateOfBirth
FROM Person
WHERE Name = #Name;
GO
Now If I run the both procedures both with a value and without:
EXECUTE GetPeopleByName1 'asymmetric_keys';
EXECUTE GetPeopleByName1 NULL;
EXECUTE GetPeopleByName2 'asymmetric_keys';
EXECUTE GetPeopleByName2 NULL;
The results are the same for both procedures, however, I get the same plan each time for the first procedure, but two different plans for the second, both of which are much more efficient that the first.
If you can't use an IF (e.g if you are using an inline table valued function) then you can get a similar result by using UNION ALL:
SELECT PersonID, Name, DateOfBirth
FROM Person
WHERE #Name IS NULL
UNION ALL
SELECT PersonID, Name, DateOfBirth
FROM Person
WHERE Name = #Name;
This is not as efficient as using IF, but still more efficient than your first query. The bottom line is that less is not always more, yes using IF is more verbose and may look like it is doing more work, but it is in fact doing a lot less work, and can be much more efficient.

Invalid Object Name Error in Function in SQL

I have following function defined
alter FUNCTION [dbo].[GetXMLValues](#business_id int, #id varchar(30))
RETURNS varchar(30)
AS
BEGIN
declare #xmlValue varchar(30)
set #xmlValue = (SELECT top 1000 T.Content.value('(/XmlDataPairDocument/dataitem[#id=sql:variable("#id")]/#value)[1]', 'VARCHAR(100)')
FROM tblApplications T where t.business_id =#business_id)
return #xmlValue
END
WHen i hit F5 command Executes Successfully/...
but when i try to execute it using following query :
select * from [GetXMLValues](1,'sadfj')
it shows an error saying : Invalid object name 'GetXMLValues'.
what is the reason ? and what is error??
This is a Scalar function, not a Table-Valued function.
select dbo.[GetXMLValues](1,'sadfj')
should work.
You can't treat this like a table, i.e. select * ..., you need to just select the result directly as above.
See Types of Functions for more details.
As mentioned by t-clausen.dk and Ian Preston, it's because you have a Scalar function and not a table valued function.
I just wanted to extend on t-clausen.dk's post which switches your function to a multi-statement table valued function. I would take this a step further and actually use an inline table valued function:
ALTER FUNCTION [dbo].[GetXMLValues](#business_id int, #id varchar(30))
RETURNS TABLE
AS
RETURN (
SELECT top 1000 T.Content.value('(/XmlDataPairDocument/dataitem[#id=sql:variable("#id")]/#value)[1]', 'VARCHAR(100)')
FROM tblApplications T where t.business_id =#business_id
)
Which you then use in the same way:
select xmlValue from dbo.[GetXMLValues](1,'sadfj')
Check out:
Query performance and multi-statement table valued functions
your function is not returning a table, it is returning a varchar(30). The correct syntax to use your function would be:
select [dbo].[GetXMLValues](1,'sadfj')
Try function this instead:
ALTER FUNCTION [dbo].[GetXMLValues](#business_id int, #id varchar(30))
RETURNS #t table (xmlValue varchar(30))
AS
BEGIN
insert #t (xmlValue)
SELECT top 1000 T.Content.value('(/XmlDataPairDocument/dataitem[#id=sql:variable("#id")]/#value)[1]', 'VARCHAR(100)')
FROM tblApplications T where t.business_id =#business_id
return
end
Then you can call your function this way:
select xmlValue from dbo.[GetXMLValues](1,'sadfj')
Or if you do want a table function, try changing your function to be something like this - then you can use select * from...
ALTER FUNCTION [dbo].[GetXMLValues](#business_id int, #id varchar(30))
RETURNS
#outputTbl_xmlValue table
(
xmlValue varchar(30)
)
AS
BEGIN
INSERT #outputTbl_xmlValue SELECT top 1000 T.Content.value('(/XmlDataPairDocument/dataitem[#id=sql:variable("#id")]/#value)[1]', 'VARCHAR(100)')
FROM tblApplications T where t.business_id =#business_id)
return
END
GO
ALTER FUNCTION Isnulldate(#maxdate1 DATETIME,
#maxdate2 DATETIME,
#maxdate3 DATETIME)
returns DATETIME
AS
BEGIN
DECLARE #date DATETIME
IF #maxdate3 IS NOT NULL
BEGIN
SET #date=#maxdate3
RETURN #date
END
IF #maxdate2 IS NOT NULL
BEGIN
SET #date=#maxdate2
RETURN #date
END
IF #maxdate1 IS NOT NULL
BEGIN
SET #date=#maxdate1
RETURN #date
END
RETURN #date
END
## Execution ##
DECLARE #dateim DATETIME=Getdate()
SELECT dbo.Isnulldate(NULL, NULL, #dateim)

Ordering SQL Server results by IN clause

I have a stored procedure which uses the IN clause. In my ASP.NET application, I have a multiline textbox that supplies values to the stored procedure. I want to be able to order by the values as they were entered in the textbox. I found out how to do this easily in mySQL (using FIELD function), but not a SQL Server equivalent.
So my query looks like:
Select * from myTable where item in #item
So I would be passing in values from my application like '113113','112112','114114' (in an arbitrary order). I want to order the results by that list.
Would a CASE statement be feasible? I wouldn't know how many items are coming in the textbox data.
How are you parameterising the IN clause?
As you are on SQL Server 2008 I would pass in a Table Valued Parameter with two columns item and sort_order and join on that instead. Then you can just add an ORDER BY sort_order onto the end.
From KM's comment above...
I know you didn't state it is comma seperated, but if it was a CSV or even if you have it space seperated you could do the following.
DECLARE #SomeTest varchar(100) --used to hold your values
SET #SomeTest = (SELECT '68,72,103') --just some test data
SELECT
LoginID --change to your column names
FROM
Login --change to your source table name
INNER JOIN
( SELECT
*
FROM fn_IntegerInList(#SomeTest)
) n
ON
n.InListID = Login.LoginID
ORDER BY
n.SortOrder
And then create fn_IntegerInList():
CREATE FUNCTION [dbo].[fn_IntegerInList] (#InListString ntext)
RETURNS #tblINList TABLE (InListID int, SortOrder int)
AS
BEGIN
declare #length int
declare #startpos int
declare #ctr int
declare #val nvarchar(50)
declare #subs nvarchar(50)
declare #sort int
set #sort=1
set #startpos = 1
set #ctr = 1
select #length = datalength(#InListString)
while (#ctr <= #length)
begin
select #val = substring(#InListString,#ctr,1)
if #val = N','
begin
select #subs = substring(#InListString,#startpos,#ctr-#startpos)
insert into #tblINList values (#subs, #sort)
set #startpos = #ctr+1
end
if #ctr = #length
begin
select #subs = substring(#InListString,#startpos,#ctr-#startpos)
insert into #tblINList values (#subs, #sort)
end
set #ctr = #ctr +1
set #sort = #sort + 1
end
RETURN
END
This way your function creates a table that holds a sort order namely, SortOrder and the ID or number you are passing in. You can of course modify this so that you are looking for space rather then , values. Otherwise Martin has the right idea in his answer. Please note in my example I am using one of my tables, so you will need to change the name Login to whatever you are dealing with.
the same way you concatenate ('113113','112112','114114') to pass to the sql sentence in the where clausule you can concatenate
order by
case item
when '113113' then 1
when '112112' then 2
when '114114' then 3
end
to pass to your order by clausule

How to have a MySQL procedure return a boolean?

I want to create a procedure that takes in a string, searches the table and the specified column for that string, and returns a 1 if it finds it and a zero if it does not. I am relatively new to SQL and do not know the syntax or commands very well. I want something like this:
CREATE PROCEDURE dbo.GetUsername
(
#Username NCHAR(10)
)
AS
#boolVariable
SELECT #Username FROM Accounts
RETURN #boolVariable
You don't return a value, but instead supply that in a result set.
CREATE PROCEDURE GetUsername
(
#Username NCHAR(10)
)
AS
SELECT Username FROM Accounts WHERE Username = #UserName;
In your calling code, simply check for the existence of a row in the result set.
I'm not sure if you're looking for mysql or mssql solution.
delimiter //
drop procedure if exists search_string //
create procedure search_string (in str varchar(100))
begin
declare b,r bool;
select count(*) into r from your_table where your_field = str;
if r > 0 then
set b = 1;
else
set b = 0;
end if;
select b;
end; //
delimiter //
call search_string('searched_string');

Passing comma-separated value from .NET to stored procedure using the value in "IN" SQL function

I have an SQL query similar to the following:
create procedure test
(
#param1 nvarchar(max)
)
as
begin
select * from table where column1 in (#param1)
end
Now I need to pass the value of #param1 from my .net application in such a way that the above query works.
Can some one please advise me on how to pass from my VB.NET code a value which is similiar to below:
'1','2','3'
My main question is how do I structure value of parameter like above example from my .NET application?
quickly like that, I would create a table valued function that would parse it so you can do
select *
from table
where field in (select field from dbo.myfunction(#param1))
For this type of thing, I use this function and use it as follows:
select Column1, column2 from my table where ID in (select item from fnSplit('1,2,3,4,5,6',','))
create FUNCTION [dbo].[fnSplit](
#sInputList VARCHAR(8000) -- List of delimited items
, #sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items
)
RETURNS #List TABLE (item VARCHAR(8000))
BEGIN
DECLARE #sItem VARCHAR(8000)
WHILE CHARINDEX(#sDelimiter,#sInputList,0) <> 0
BEGIN
SELECT
#sItem=RTRIM(LTRIM(SUBSTRING(#sInputList,1,CHARINDEX(#sDelimiter,#sInputList,0)-1))),
#sInputList=RTRIM(LTRIM(SUBSTRING(#sInputList,CHARINDEX(#sDelimiter,#sInputList,0)+LEN(#sDelimiter),LEN(#sInputList))))
IF LEN(#sItem) > 0
INSERT INTO #List SELECT #sItem
END
IF LEN(#sInputList) > 0
INSERT INTO #List SELECT #sInputList -- Put the last item in
RETURN
END
I don't think the problem is in the values you are passing. #param1 is just a string.
You need to address this in your procedure. Your select statement will not be able to recognize the values in you IN clause. One solution is to take the comma-separated string and insert each record into a table variable Explained Here
If your table variable is table #param_list, you procedure test looks like:
create procedure test ( #param1 nvarchar(max) )
as begin
select * from table where column1 in (Select thefield from #param_list);
end

Resources