Need to create a function in sql to find a string - sql-server

I am trying to write a function which can tell me whether there is something after second ; in the string or not.For example: the sample string is "2:00AM;3:00PM;". So the function in this case needs to return false.

Assuming that there'll always be a second ;, and no third one, this ought to work...
CREATE FUNCTION dbo.fn_Bob(#str VARCHAR(20)) RETURNS BIT
BEGIN
RETURN CASE WHEN #str LIKE '%;' THEN 0 ELSE 1 END
END

The CHARINDEX has an optional parameter to choose the start position, so find the first index of the ";" and add 1 that will start at the next character and then check for the next index and the length should be longer.
DECLARE #stringToTest nvarchar(100)
SET #stringToTest = '2:00AM;3:00PM;';
IF(LEN(#stringToTest) > CHARINDEX(';', #stringToTest, CHARINDEX(';', #stringToTest) + 1))
BEGIN
PRINT 'Yes'
END
ELSE
BEGIN
PRINT 'No'
END

create function [dbo].[udf_IsValidCheck](#Value varchar(64)) returns bit
as
begin
declare #IsValidCheck bit
select #IsValidCheck = (case when charindex( ';', #Value, charindex(';', #Value) + 1) > 0
and charindex( ';', #Value, charindex(';', #Value) + 1) < len(#Value) then 1
else 0 end)
return #IsValidCheck
end
test data:
'2:00AM;3:00PM;' --returns 0
'2:00AM;3:00PM' --returns 0
'2:00AM;3:00PM;3rdValue;4thValue;' --returns 1
'2:00AM;3:00PM;3rdValue;' --returns 1
'2:00AM;3:00PM;3rdValue' --returns 1
'2:00AM;' -- returns 0
'2:00AM;' -- returns 0

Related

Unicode (Hexadecimal) to varchar conversion

Here is the problem, the system I use can create a saved search which basically generates a 'Where' clause and saves it in the database as type Image ..
I am trying to convert the image entry to a readable format, it is saved in 2 forms (Unicode and non unicode) now I can get the non unicode entries fine and they display correctly, however when I try and convert the Unicode entries it does not display correctly an example of what I am trying to convert is
0x01000000FFFEFF00FFFEFF0001050000FFFEFF05510075006F007400650006000000060000000100000001000000000000000000000080000000000000FD00000000000000000700000001050000FFFEFF254E006F0072006700720065006E005F00470072006F007500700020004900640020003D00200030007800300030003000300030003000300030003000300030003000300030003200330004000000060000000100000002000000000000000000002380000000000022B00000000000000001000000FFFEFF5454005400490044005F003400330034005200390032003300370020005F005F00530051004C005F00440045004C0049004D005F005F002000510075006F00740065005F002E004E006F0072006700720065006E005F00470072006F00750070005F004900640020003D00200054005400490044005F00340033003400520039003200330037002E004E006F0072006700720065006E005F00470072006F00750070005F00490064000000000001050000FFFEFF0C45006D0070006C006F0079006500650020003D0020003F0004000000060000000100000002000000000000000000000080000000000001030101000000000001000000FFFEFFA754005400490044005F00320035005200310032003400350034002E0054005400490044005F0032003300520038003600340052003100320034003500340020005F005F00530051004C005F00440045004C0049004D005F005F002000510075006F00740065005F002E0053006800690070005F0054006F005F0043006F006D00700061006E0079005F004900640020003D00200054005400490044005F00320035005200310032003400350034002E0043006F006D00700061006E0079005F0049006400200041004E004400200054005400490044005F00320035005200310032003400350034002E004100630063006F0075006E0074005F004D0061006E0061006700650072005F004900640020003D00200054005400490044005F003200330052003800360034005200310032003400350034002E0045006D0070006C006F007900650065005F00490064000000000001050000FFFEFF0C45006D0070006C006F0079006500650020003D0020003F0004000000060000000100000002000000000000000000000080000000000001030101000000000001000000FFFEFFB354005400490044005F00320035005200310032003400350034002E0054005400490044005F00320033005200380037003000390052003100320034003500340020005F005F00530051004C005F00440045004C0049004D005F005F002000510075006F00740065005F002E0053006800690070005F0054006F005F0043006F006D00700061006E0079005F004900640020003D00200054005400490044005F00320035005200310032003400350034002E0043006F006D00700061006E0079005F0049006400200041004E004400200054005400490044005F00320035005200310032003400350034002E0049006E007400650072006E0061006C005F0043006F006D006D00650072006300690061006C005F00530061006C00650073005F004900640020003D00200054005400490044005F0032003300520038003700300039005200310032003400350034002E0045006D0070006C006F007900650065005F00490064000000000001050000FFFEFF13510075006F0074006500200054006F00740061006C0020003E003D00200032003000300030000400000006000000010000000200000000000000000000008000000000001847010101080000000000000000409F400000000001000000FFFEFF15510075006F00740065005F0020005F005F00530051004C005F00440045004C0049004D005F005F0020000000000001050000FFFEFF1F46006F006C006C006F007700200055007000200053007400610074007500730020003D00200054006F00200046006F006C006C006F007700200055007000040000000600000001000000020000000000000000000000800000000000392F0000000000000001000000FFFEFF15510075006F00740065005F0020005F005F00530051004C005F00440045004C0049004D005F005F0020000200000001050000FFFEFF1F46006F006C006C006F007700200055007000200053007400610074007500730020003D00200049006E00200046006F006C006C006F007700200055007000050000000600000001000000020000000000000000000000800000000000392F0000000000000001000000FFFEFF15510075006F00740065005F0020005F005F00530051004C005F00440045004C0049004D005F005F0020000000000001050000FFFEFF1F46006F006C006C006F007700200055007000200053007400610074007500730020003D0020004E006F00200046006F006C006C006F007700200055007000050000000600000001000000020000000000000000000000800000000000392F0000000000000001000000FFFEFF15510075006F00740065005F0020005F005F00530051004C005F00440045004C0049004D005F005F0020000000000001050000FFFEFF20510075006F0074006500200046006F006C006C006F00770020004500780070006900720065007300200049006E002000440061007900730020003E002000310004000000060000000100000002000000000000000000000080000000000039DD0000000000000001000000FFFEFF4854005400490044005F003700310035004C003100340034003600330020005F005F00530051004C005F00440045004C0049004D005F005F002000510075006F00740065005F002E00510075006F00740065005F005F004900640020003D00200054005400490044005F003700310035004C00310034003400360033002E00510075006F00740065005F005F00490064000000000001050000FFFEFF11510075006F00740065005F0020004900640020004E006F007400200049006E00200004000000060000000100000002000000000000000000000080000000000018F5000000040000000100000000000000000000000000000001000000FFFEFF15510075006F00740065005F0020005F005F00530051004C005F00440045004C0049004D005F005F0020000000000003000000010000000000000000002F9680000000000018F5000000000000000000000000
the SQL code I am using to convert is the following
with saved_lookups_cte as
(select
table_id,
table_name,
saved_lookups_id,
saved_lookup_name,
case
when charindex('WhereDelim',query_text) > 0 then
substring(query_text,len(query_text) - charindex(reverse('WhereDelim'),reverse(query_text)) + 3,4000)
else query_text
end query_text
, sql_tree_binary
from (select
table_id,
table_name,
saved_lookups_id,
saved_lookup_name,
case isUnicode
when 1 then [Production_ED].dbo.[RemoveNonASCII] (cast(cast(substring(sql_tree_binary, startIndex, queryLength * 2) as nvarchar(max))as varchar(max)))
else cast(substring(sql_tree_binary, startIndex, queryLength) as varchar(8000))
end query_text
, sql_tree_binary
from (
select
saved_lookup_name,
case
when substring(sql_tree_binary,1,5) = 0x0100000000 then 0
when substring(sql_tree_binary,1,5) = 0x01000000FF then 1
end isUnicode,
cast(case
when substring(sql_tree_binary,1,5) = 0x0100000000 then
case
when substring(sql_tree_binary,6,1) = 0xFF then substring(sql_tree_binary,8,1) + substring(sql_tree_binary,7,1)
else substring(sql_tree_binary,6,1)
end
when substring(sql_tree_binary,1,5) = 0x01000000FF then
case
when substring(sql_tree_binary,12,1) = 0xFF then substring(sql_tree_binary,14,1) + substring(sql_tree_binary,13,1)
else substring(sql_tree_binary,12,1)
end
end as int) queryLength,
case
when substring(sql_tree_binary,1,5) = 0x0100000000 then
case
when substring(sql_tree_binary,6,1) = 0xFF then 9
else 7
end
when substring(sql_tree_binary,1,5) = 0x01000000FF then
case
when substring(sql_tree_binary,12,1) = 0xFF then 15
else 13
end
end startIndex,
s.table_id,
t.table_name,
s.saved_lookups_id,
s.sql_tree_binary
from
Production_Ed.dbo.Saved_Lookups s inner join
tables t on s.table_id = t.tables_id
-- where substring(saved_lookups_id,1,1) <> 0x00
where saved_lookup_name = 'DE Quotes Open Account Manager >=2000'
) x
) y
)
select * from saved_lookups_cte
The part of the query that does the conversion is
when 1 then [Production_ED].dbo.[RemoveNonASCII]
(cast(cast(substring(sql_tree_binary, startIndex, queryLength * 2) as
nvarchar(max))as varchar(max)))
now this actually returns nothing, however if I set the startIndex to 17 and change the queryLength to 3000 * 2 (unicode byte = 2) I get
??Quote?????Norgren_Group Id = 0x0000000000000023???A??????????????? ????????????? ??????????????????????? ? ??????????????????????????????A?????????? ? ???A??Aa??TTID_25R12454.TTID_23R864R12454 __SQ
Returned, although I can read parts, it is not the full query ... yet even if I extend the length I get no more.
Any help would be greatly appreciated.
Code for the RemoveNonASCII function:
ALTER FUNCTION [dbo].[RemoveNonASCII]
(
#nstring nvarchar(max)
)
RETURNS varchar(max)
AS
BEGIN
DECLARE #Result varchar(max)
SET #Result = ''
DECLARE #nchar nvarchar(1)
DECLARE #position int
SET #position = 1
WHILE #position <= LEN(#nstring)
BEGIN
SET #nchar = SUBSTRING(#nstring, #position, 1)
IF ASCII(#nchar) between 32 and 255
SET #Result = #Result + #nchar
SET #position = #position + 1
END
RETURN #Result
END
GO
Ok, so I found the issue, inside the hex string there were null values, which caused the rest of the returned varchar string to become null .. So I just changed the function to:
AS
BEGIN
DECLARE #Result varchar(max)
SET #Result = ''
DECLARE #nchar nvarchar(1)
DECLARE #position int
SET #position = 1
WHILE #position <= LEN(#nstring)
BEGIN
SET #nchar = SUBSTRING(#nstring, #position, 1)
IF ASCII(#nchar) between 1 and 125
SET #Result = #Result + #nchar
SET #position = #position + 1
END
RETURN #Result
END
Eradicating 0 being the ASCII Null value!

How to get only number from string in SQL Server?

I have string:
010-234-336-.
and I want to return only number like:
010234336.
Does anyone know how to format this string?
Try this
Select Replace('010-234-336-', '-', '')
In case you have other string and want to only numeric portion, then try below code.
Declare #strAlphaNumeric varchar(256) = '010-abnasd234-336-'
DECLARE #intAlpha INT
SET #intAlpha = PATINDEX('%[^0-9]%', #strAlphaNumeric)
WHILE #intAlpha > 0
BEGIN
SET #strAlphaNumeric = STUFF(#strAlphaNumeric, #intAlpha, 1, '' )
SET #intAlpha = PATINDEX('%[^0-9]%', #strAlphaNumeric )
END
Select ISNULL(#strAlphaNumeric,0)
I got above solution :- Query to get only numbers from a string
SELECT CONVERT (INT,REPLACE('010-234-336-.','-',''))
SELECT Replace('010-234-336-', '-', '')
You can also cast or convert to integer if desired too.
SELECT CAST(Replace('010-234-336-', '-', '') AS INT) as value
SELECT CONVERT(INT, Replace('010-234-336-', '-', '')) as value
Here's a function I had made to let me remove all non-numeric characters from a string, but leave the result as a string. This was so I didn't lose any zeros from the beginning of the entry.
CREATE FUNCTION dbo.fnsStripToNumber
(
#inString varchar(500) = NULL
)
RETURNS varchar(500) AS
BEGIN
/***********************************************************************
Object : User Defined Scalar Function [dbo].[fnsStripToNumber]
Script Date : <date: 2016-04-20>
Author : Just Me
Description : Remove all non-numeric characters from a string.
Updates : 2016-04-20 - JustMe
Updated the script for speed.
Moved the function to follow coding standards.
Test Script :
SELECT
ODS.dbo.fnsStripToNumber('ts45my12fnc098. ') AS strNumber
***********************************************************************/
DECLARE
#strReturn varchar(500) = '',
#intEnPos int = 1
--
-- Loop through the string from beginning to end looking for any numbers.
--
WHILE #intEnPos > 0
BEGIN
--
-- This is like a progressive update SELECT statement.
-- The position of the next space is first found.
-- This updated value is used in the next variable assignment to parse the
-- string unit.
-- The starting position for the next string unit is updated.
-- Modify the string unit and update the return string.
--
SELECT
#intEnPos = PATINDEX('%[0-9]%', #inString),
#strReturn += (
CASE
WHEN #intEnPos > 0 THEN SUBSTRING(#inString, #intEnPos, 1)
ELSE ''
END
),
#inString = RIGHT(#inString, DATALENGTH(#inString) - #intEnPos)
END
--
-- Return the proper cased string.
--
RETURN #strReturn
END;
GO

SQL Server order by part of string

One of my tables have values like this..
Year 1
Year 9
Year 4
Kindy [can be any word without numbers]
Pre-School [can be any word without numbers]
Year 8
Year 22
Year 15....
How can I select Them in alphabetically first and then by numerically in ascending order like this..
Kindy [can be any word without numbers]
Pre-School [can be any word without numbers]
Year 1
Year 4
Year 8
Year 9
Year 15
Year 22
I could not extract the integer and order in this case as some of the years don't have it..
UPDATE
MY ANSWER -- MISSING DISTINCT
SELECT YearLevel FROM Student
ORDER BY
CASE WHEN YearLevel NOT LIKE '%[0-9]%' THEN 0
ELSE CAST(RIGHT(YearLevel, LEN(YearLevel) - 5) AS int)
END
Try this in the ORDER BY clause:
ORDER BY
CASE WHEN col = 'Kindy' then 0
WHEN col = 'Pre-School' then 1
ELSE CAST(SUBSTRING(col,6,LEN(col)) AS INT) + 1
END
In first you must create following function for get text part and number part of your string :
CREATE FUNCTION [dbo].[GetNumbersFromText](#String varchar(2000))
RETURNS INT
AS BEGIN
DECLARE #Count INT = 0,
#IntNumbers VARCHAR(1000) = '',
#FindNumber BIT = 0
WHILE #Count <= LEN(#String) BEGIN
IF SUBSTRING(#String,#Count,1) >= '0' AND SUBSTRING(#String,#Count,1) <= '9' BEGIN
SET #IntNumbers = #IntNumbers + SUBSTRING(#String,#Count,1)
SET #FindNumber = 1
END ELSE IF (#FindNumber = 1) BEGIN
BREAK
END
SET #Count = #Count + 1
END
RETURN CAST(#IntNumbers AS INT)
END
CREATE FUNCTION [dbo].[GetTextPartOfText](#String varchar(2000))
RETURNS INT
AS BEGIN
DECLARE #Count INT = 0,
#Text VARCHAR(1000) = '',
WHILE #Count <= LEN(#String) BEGIN
IF SUBSTRING(#String,#Count,1) >= '0' AND SUBSTRING(#String,#Count,1) <= '9' BEGIN
BREAK
END ELSE BEGIN
SET #Text = #Text + SUBSTRING(#String,#Count,1)
END
SET #Count = #Count + 1
END
RETURN #Text
END
In second you use following query for your sort:
SELECT *
FROM YourTable
ORDER BY [dbo].[GetTextPartOfText](TextColumn),[dbo].[GetNumbersFromText](TextColumn), TextColumn
SELECT YearLevel FROM student
GROUP BY YearLevel
ORDER BY
(CASE
WHEN YearLevel LIKE 'Year%'
THEN 'Year' + CONVERT(varchar,LEN(YearLevel)) + YearLevel
ELSE YearLevel
END)

String.IsNullOrEmpty like function for VARCHARs in SQL?

Say I've got a function or stored procedure that takes in several VARCHAR parameters. I've gotten tired of writing SQL like this to test if these parameters have a value:
IF #SomeVarcharParm IS NOT NULL AND LEN(#SomeVarcharParm) > 0
BEGIN
-- do stuff
END
There's gotta be a better way to do this. Isn't there?
You can do ISNULL(#SomeVarcharParam, '') <> '' or you can create a UDF that returns a bit:
create function dbo.IsNullOrEmpty(#x varchar(max)) returns bit as
BEGIN
IF #SomeVarcharParm IS NOT NULL AND LEN(#SomeVarcharParm) > 0
RETURN 0
ELSE
RETURN 1
END
And call that using IF NOT dbo.IsNullOrEmpty(#SomeVarcharParam) BEGIN ...
Keep in mind that when calling a UDF, you MUST prefix the owner of it (here, dbo.)
IF COALESCE(#SomeVarcharParm, '') <> ''
BEGIN
-- do stuff
END
If I'm concatenating or coalescing a string inline (within a select statement), and I want to check if the column is NULL or Empty, I do this:
ISNULL('starting to build string '
+ NULLIF(some_table..some_col_that_might_be_null_or_empty, '')
, 'string to append if the resulting concatenation is null')
The NULLIF on the inner part of the expression will force the column to be NULL if it's empty, then the outer ISNULL expression can depend on consistent input and react accordingly.
Here is my function that "extends" ISNULL and checks for empty as well. The test value is checked for null and if it is not null it is trimmed and then checked for length.
The function returns the test string if it is NOT Null or Empty, otherwise the second string is returned.
CREATE FUNCTION [dbo].[ISNULLOREMPTY]
(
#value NVARCHAR(max),
#return NVARCHAR(max)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
IF (#value IS NULL)
BEGIN
RETURN #return
END
ELSE
BEGIN
IF (LEN(LTRIM(#value)) = 0)
BEGIN
RETURN #return
END
END
RETURN #value;
END
GO
I upvoted Atron's answer though he technically implemented IfNullOrWhiteSpace.
Here's my implementation of IfNullOrEmpty():
IF EXISTS (SELECT * FROM sys .objects WHERE object_id = OBJECT_ID(N'[dbo].[IfNullOrEmpty]' ) and type in ( N'FN'))
DROP FUNCTION dbo.IfNullOrEmpty
go
CREATE FUNCTION dbo.IfNullOrEmpty(#value varchar(max), #substitute varchar(max)) returns varchar(max) as
BEGIN
IF #value IS NOT NULL AND LEN(#value) > 0
RETURN #value
RETURN #substitute
END
I realize this is an old question, but this is what I use in MSSQL:
LEN(ISNULL(#asdf, ''))>0
Example:
DECLARE #asdf varchar(10)
SET #asdf = NULL --You can change this value to test different outputs
BEGIN IF LEN(ISNULL(#asdf, '')) > 0
PRINT #asdf
ELSE
PRINT 'IS NullOrEmpty'
END
--You can use it inline like this:
PRINT CASE LEN(ISNULL(#asdf, '')) WHEN 0 THEN 'IS NullOrEmpty' ELSE #asdf END
I think this is simpler and more straight forward than the other solutions because it is literally checking if the string is null or has a length of 0.
You don't need to check for null before calling LEN. You can just use LEN(#SomeVarcharParm) > 0. This will return false if the value is NULL, '', or ' '. This is because NULL > 0 returns false. See for yourself run:
SELECT
CASE WHEN NULL > 0 THEN 'NULL > 0 = true' ELSE 'NULL > 0 = false' END,
CASE WHEN LEN(NULL) > 0 THEN 'LEN(NULL) = true' ELSE 'LEN(NULL) = false' END,
CASE WHEN LEN('') > 0 THEN 'LEN('''') > 0 = true' ELSE 'LEN('''') > 0 = false' END,
CASE WHEN LEN(' ') > 0 THEN 'LEN('' '') > 0 = true' ELSE 'LEN('' '') > 0 = false' END,
CASE WHEN LEN(' test ') > 0 THEN 'LEN('' test '') > 0 = true' ELSE 'LEN('' test '') > 0 = false' END
You can just do IF #SomeVarcharParam <> '' since the condition will evaluate to NULL and the branch won't be taken if the parameter is null
Use this function (based on Derek's):
CREATE FUNCTION dbo.isNullOrEmpty(#x varchar(max)) RETURNS BIT AS
BEGIN
IF #x IS NOT NULL AND LEN(#x) > 0
RETURN 0
RETURN 1
END
as
dbo.isNullOrEmpty(#someVar)
or
WHERE dbo.isNullOrEmpty(#someVar) = 1
in a stored procedure or query.
please use case command.case structure is:
case when condition then 'some value' else 'some other value' end
some example:
declare #SomeVarcharParm as nvarchar(20)=''
declare #SomeVarcharParm2 as nvarchar(20)=''
--select 1 or 2
select case when #SomeVarcharParm is null or #SomeVarcharParm='' then 1 else 2 end
--if null or empty set 'empty' value else set #SomeVarcharParm value
select #SomeVarcharParm2=case when #SomeVarcharParm is null or #SomeVarcharParm='' then 'empty' else #SomeVarcharParm end
--use null or empty in update command
update tbl1
set field1=case when field1 is null or field1='' then #SomeVarcharParm2 else field1 end
where id=1

CHARINDEX keep returning 0

does any one see why i am still getting 0 as a result of:
SELECT [KnowItAll].[dbo].[VSM_CanculateTermFrequency] (
'hello hi hello by hello why'
,'hi')
GO
Where VSM_CanculateTermFrequency:
CREATE FUNCTION [dbo].[VSM_CanculateTermFrequency]
(
#i_Document NCHAR(4000),
#i_Term NCHAR(30)
)
RETURNS SMALLINT
AS
BEGIN
-- Declare the return variable here
DECLARE #TermFrequency SMALLINT
DECLARE #pos INT
DECLARE #nextpos INT
SELECT #pos = 0, #nextpos = 1, #TermFrequency = 0
WHILE #nextpos > 0
BEGIN
SELECT #nextpos = CHARINDEX(#i_Term,#i_Document)
SELECT #TermFrequency = CASE
WHEN #nextpos > 0 THEN #TermFrequency + 1
ELSE #TermFrequency
END
SELECT #pos = #nextpos
END
RETURN #TermFrequency
END
The problem is your use of nchar. In effect, you are not searching for 'hi', you are searching for 'hi ' You should change the datatype on your two parameters to nvarchar. By using nchar, the system pads the value with spaces so that it becomes 30 or 4000 characters.
Btw, another problem I see unrelated to CharIndex always returning zero issue (which is due to the padding), is that you are not telling CharIndex to search after the last found term. You should change your call to CharIndex to be:
CHARINDEX(#i_Term,#i_Document,#pos + 1)
(Btw, I see that Gabe found this first)
Once you change your datatype to nvarchar, you will discover that you have an infinite loop because it always starts searching from the beginning of the document. Your line should read:
SELECT #nextpos = CHARINDEX(#i_Term,#i_Document, #pos + 1)

Resources