Integer to string conversion function in sql - sql

I have a number as follows:
13901210
I want the output to give the following result
1390/12/10
Input function: a number of bigint
Output: a string
How do I create this function?

I wonder why no one suggested this Simple Query
declare #input bigint=13901210
select REPLACE(Convert(varchar,Convert(date,CONVERT(varchar,#input))),'-','/')
SQL Fiddle

DECLARE #integer int = 13901210;
DECLARE #part1 int = #integer / 10000;
DECLARE #part2 int = (#integer - #integer / 10000 * 10000) / 100;
DECLARE #part3 int = #integer - #integer / 100 * 100;
DECLARE #result char(10) =
CAST(#part1 AS char(4)) + '/'
+ CAST(#part2 AS char(2)) + '/'
+ CAST(#part3 AS char(2))
SELECT Part1 = #part1, Part2 = #part2, Part3 = #part3, Result = #result;
GO

You can try this query:
SELECT SUBSTRING(CAST(13901210 AS varchar(8)), 1,4) + '/' + SUBSTRING(CAST(13901210 AS varchar(8)), 5,2) + '/' + SUBSTRING(CAST(13901210 AS varchar(8)), 7,2)
Just replace the value with whatever field/variable you have with the number stored
The full function would look like this:
CREATE FUNCTION [dbo].[int_to_slashed_string] ( #value int )
RETURNS varchar(10)
AS
BEGIN
DECLARE #string varchar(8);
SET #string = CAST(#value AS varchar(8));
RETURN SUBSTRING(#string, 1,4)
+ '/' + SUBSTRING(#string, 5,2)
+ '/' + SUBSTRING(#string, 7,2);
END
This function assumes the value contains 8 digits. If there are other limitations or conditions, the function will have to be modified.

If you do not want to substring the value then you can do this:
DECLARE #nbr INT=13901210
SELECT
LEFT(#nbr,4)+'/'+
SUBSTRING(CAST(#nbr AS VARCHAR(10)),5,2)+'/'+
RIGHT(#nbr,2)
And then the function would look like this:
CREATE FUNCTION [dbo].[GetDateFormatForInt] (#nbr int)
RETURNS varchar(10)
AS
BEGIN
RETURN
LEFT(#nbr,4)+'/'+
SUBSTRING(CAST(#nbr AS VARCHAR(10)),5,2)+'/'+
RIGHT(#nbr,2);
END
This will only work if is a 10 digit number

This also works for me:
CREATE PROCEDURE getdatestr
#result nvarchar(12) output,
#info bigint
AS
BEGIN
SET #result=(SELECT LEFT(CAST(#info AS VARCHAR(8)),4)+'/'+
SUBSTRING(CAST(#info AS VARCHAR(8)),5,2)+'/'+
RIGHT(CAST(#info AS VARCHAR(8)),2))
RETURN #result
END
GO
Except that LEFT,RIGHT return nvarchar and SUBSTRING returns string :) Anyways try it...it gives the same output and if you are ok with it then it is simple to get.

Related

SQL - parametrized procedure with multiple parameters as array

I have very simple procedure:
CREATE PROCEDURE [Report]
#statusValue varchar(200) = '%'
AS
BEGIN
SELECT * FROM SomeTable
WHERE Something LIKE UPPER(#statusValue)
END
I'd like to provide user set multiple statusValue. Because there is 6 levels of statusValue in my table, I'd like to provide user to define required statusValue into procedure parameters - something like array.
I don't know, how it exactly works - I'm very new in this area - but I'm supposing to have procedure like this one:
EXEC Report #statusValue = 'statusValue1|statusValue2|statusValue3'
Do you happen to know, how can I adjust my procedure to have required output. Many thanks in advance.
Use following user defined function to return values from delimited string (say pipe):
CREATE FUNCTION [dbo].[stringlist_to_table]
(#list varchar(8000),
#delimiter nchar(1) = N',')
RETURNS #tbl TABLE (value varchar(8000)) AS
BEGIN
DECLARE #pos int,
#tmpstr varchar(8000),
#tmpval varchar(8000);
SET #tmpstr = #list;
SET #pos = charindex(#delimiter , #tmpstr);
WHILE #pos > 0
BEGIN
SET #tmpval = ltrim(rtrim(left(#tmpstr, #pos - 1)))
INSERT #tbl (value) VALUES(#tmpval)
SET #tmpstr = substring(#tmpstr, #pos + 1, len(#tmpstr))
SET #pos = charindex(#delimiter, #tmpstr)
END
INSERT #tbl(value) VALUES (ltrim(rtrim(#tmpstr)));
RETURN
END
Now use the following procedure to get the required output:
CREATE PROCEDURE [Report]
#statusValue varchar(200) = '%'
AS
BEGIN
DECLARE #iterator INT = 1;
DECLARE #total INT = 1;
DECLARE #keyword VARCHAR(100) = '';
SELECT ROW_NUMBER() OVER (ORDER BY value) SNo, value keyword
INTO #temp
FROM dbo.stringlist_to_table(#statusValue, '|')
SELECT *
INTO #output
FROM SomeTable
WHERE 1 = 0;
SELECT #total = MAX(SNo), #iterator = MIN(Sno)
FROM #temp
WHILE (#iterator <= #total)
BEGIN
SELECT #keyword = '%' + keyword + '%'
FROM #temp
WHERE SNo = #iterator;
INSERT INTO #output
SELECT *
FROM SomeTable
WHERE Something LIKE #keyword
SET #iterator = #iterator + 1;
END
SELECT *
FROM #output;
DROP TABLE #output, #temp;
END
You need the split function in this case. As there is no way to handle what you need. Another approach to add many variables. But in your case it will be enough to create split function and use it to parse your string. Please find the split function below:
CREATE FUNCTION [dbo].[ufnSplitInlineStringToParameters] (
#list NVARCHAR(MAX)
,#delim NCHAR(1) = ','
)
RETURNS TABLE
AS
RETURN
WITH csvTbl(START, STOP) AS (
SELECT START = CONVERT(BIGINT, 1)
,STOP = CHARINDEX(#delim, #list + CONVERT(NVARCHAR(MAX), #delim))
UNION ALL
SELECT START = STOP + 1
,STOP = CHARINDEX(#delim, #list + CONVERT(NVARCHAR(MAX), #delim), STOP + 1)
FROM csvTbl
WHERE STOP > 0
)
SELECT LTRIM(RTRIM(CONVERT(NVARCHAR(4000), SUBSTRING(#list, START, CASE
WHEN STOP > 0
THEN STOP - START
ELSE 0
END)))) AS VALUE
FROM csvTbl
WHERE STOP > 0
GO
One of the simplest way to achieve this is using a custom type. Sample snippet as follows:
CREATE TYPE dbo.StatusList
AS TABLE
(
statusValue varchar(200)
);
GO
CREATE PROCEDURE [Report]
#statusValue AS dbo.StatusList READONLY
AS
BEGIN
SELECT * FROM SomeTable
WHERE Something IN (SELECT * FROM #statusValue)
END
GO
--EDIT---
If you are using SSMS, you can execute the procedure as follows:
DECLARE #status dbo.StatusList
INSERT INTO #status VALUES('Pending')
EXEC [Report] #status

Trim first zero after dot twice sql query

I'm trying to compare assembly versions using SQL Server, however there can be more than one version returned and I need it be in a six digit format.
For example, the assembly version 2.00.0001 and I need that to be returned as 2.0.1.
There could be versions like 1.01.0031 that I would need to be 1.1.31.
This works but is there a better way of doing it?
select left(left([output],9),1)+'.'+substring(left([output],9),3,1)+'.'+substring(right(left([output],9),1),1,1)
Using ParseName function, you can achieve this. Try this -
DECLARE #val VARCHAR(100) = '01.10.0031'
SELECT CONVERT(VARCHAR, CONVERT(INT, PARSENAME(#val, 3))) + '.' +
CONVERT(VARCHAR, CONVERT(INT, PARSENAME(#val, 2))) + '.' +
CONVERT(VARCHAR, CONVERT(INT, PARSENAME(#val, 1)))
Result
1.10.31
For limited numbers of zeros, you can replace .0 with .:
select replace(replace(replace([output], '.00', '.'), '.0', '.'), '..', '.0.')
This is a bit of a hack, but it is relatively simple.
Because the pattern would always be fixed, you could use substring and cast to do this.
select substring(col,1,1) + '.'
cast(cast(substring(col,3,2) as int) as varchar(2)) + '.'
cast(cast(substring(col,6,4) as int) as varchar(4))
from tablename
Here is a dynamic solution that will work with any format provided there are no alpha and '.' is the seperator.
Create Function [dbo].[SplitString] ( #stringToSplit VARCHAR(MAX) )
RETURNS
varchar(MAX)
AS
BEGIN
DECLARE #name VARCHAR(MAX)
DECLARE #pos INT
Declare #Return Varchar(MAX) = ''
WHILE CHARINDEX('.', #stringToSplit) > 0
BEGIN
SELECT #pos = CHARINDEX('.', #stringToSplit)
SELECT #name = Convert(Varchar(MAX), Convert(Int, SUBSTRING(#stringToSplit, 1, #pos-1)))
Set #Return = #Return + #name + '.'
SELECT #stringToSplit = SUBSTRING(#stringToSplit, #pos+1, LEN(#stringToSplit)-#pos)
END
RETURN #Return + Convert(Varchar(MAX), Convert(Int, #stringToSplit))
END
Declare #ver Varchar(100) = '7.00.0001'
Select dbo.splitstring(#ver)
I believe this should work as long as the pattern contains two decimal points and should handle any number of zeros in each position
DECLARE #version VARCHAR(19)
SET #version = '2.00.0001'
SELECT
CAST(CAST(SUBSTRING(#version,1,CHARINDEX('.',#version,1)-1) AS INT) AS VARCHAR(5)) + '.'+
CAST(CAST(SUBSTRING(#version,CHARINDEX('.',#version,1)+1,CHARINDEX('.',#version,CHARINDEX('.',#version,1) + 1)-CHARINDEX('.',#version,1)-1) AS INT) AS VARCHAR(5)) + '.' +
CAST(CAST(SUBSTRING(#version,CHARINDEX('.',#version,CHARINDEX('.',#version,1) + 1)+1,LEN(#version)) AS INT) AS VARCHAR(5))

Spliting large string in Sql Server

I am using this logic to split the string query
declare #query nvarchar(max)
set #query = '1&2&3&4&5&6&7&8&9&10&11&12&13&14'
SELECT SUBSTRING('&' + #query + '&', Number + 1, -- is used to split the '#query' on the basis of '&' sign
CHARINDEX('&', '&' + #query + '&', Number + 1) - Number -1)AS VALUE
FROM master..spt_values
WHERE Type = 'P'
AND Number <= LEN('&' + #query + '&') - 1
AND SUBSTRING('&' + #query + '&', Number, 1) = '&'
It works fine when query is small, but its giving me less result then actual when the value of #query is very large
For eg.
#query = 'very large string containing 60 & sign '
returns only 10 records
How can I split large string, and what is the reason? Why can SUBSTRING not handle large strings?
You can use this function. It returns a table of splitted values, based on input string and a delimeter.
Usage:
select *
from dbo.fn_ParseText2Table('1&2&3&4&5&6&7&8&9&10&11&12&13&14','&')
The function has a parameter #p_SourceText which type is varchar(8000), so input string can be up to 8000 characters.
You can change type to varchar(max) if version of your SQL Server allows you to do this.
I used this Function and its working for me Perfectly :)
CREATE function f_split(#SourceSql nvarchar(Max),#StrSeprate varchar(10))
returns #temp
table([column] nvarchar(Max))
begin
declare #i int
set #SourceSql=rtrim(ltrim(#SourceSql))
set #i=charindex(#StrSeprate,#SourceSql)
while #i>=1
begin
insert #temp values(left(#SourceSql,#i-1))
set #SourceSql=substring(#SourceSql,#i+1,len(#SourceSql)-#i)
set #i=charindex(#StrSeprate,#SourceSql)
end
if #SourceSql<>'\'
insert #temp values(#SourceSql)
return
end
go
select * from dbo.f_split('1,2,3,4,5',',')
go
I am not sure why your code is not getting the result. I executed the query with large amount of data. But I got the result. May be your string is very much bigger than I did the testing. I have also the same requirement to split the string. I am using this function to get the solution. You can try this.
CREATE FUNCTION [dbo].[fnSplitString] ( #MyArray VARCHAR(8000), #separator CHAR(1) )
RETURNS #RetTable TABLE
(StrValue VARCHAR(256))
AS
BEGIN
DECLARE #SeperatorString VARCHAR(10);
SET #SeperatorString = '%' + #separator + '%'
DECLARE #separator_position INT
DECLARE #array_value VARCHAR(1000)
SET #MyArray = #MyArray + #separator
WHILE PATINDEX( #SeperatorString , #MyArray) <> 0
BEGIN
SELECT #separator_position = PATINDEX(#SeperatorString , #MyArray)
SELECT #array_value = LEFT(#MyArray, #separator_position - 1)
INSERT #RetTable VALUES ( CAST(#array_value AS VARCHAR(256)) )
SELECT #MyArray = STUFF(#MyArray, 1, #separator_position, '')
END
RETURN
END
If you want more explanation on this function, how the function is using and what the parameters are , you can take a look here.. This is very simple function and easy to use.

How to change case in string

My table has one column that contain strings like: ” HRM_APPLICATION_DELAY_IN”
I want to perform bellow operations on each row on this column
convert to lower case
remove underscore “_”
change case (convert to upper case) of the character after the underscore like: ” hrm_Application_Delay_In”
Need help for conversion. Thanks for advance
Here is a function to achieve it:
create function f_test
(
#a varchar(max)
)
returns varchar(max)
as
begin
set #a = lower(#a)
while #a LIKE '%\_%' ESCAPE '\'
begin
select #a = stuff(#a, v, 2, upper(substring(#a, v+1,1)))
from (select charindex('_', #a) v) a
end
return #a
end
Example:
select dbo.f_test( HRM_APPLICATION_DELAY_IN')
Result:
hrmApplicationDelayIn
To update your table here is an example how to write the syntax with the function:
UPDATE <yourtable>
SET <yourcolumn> = dbo.f_test(col)
WHERE <yourcolumn> LIKE '%\_%' ESCAPE '\'
For a variable this is overkill, but I'm using this to demonstrate a pattern
declare #str varchar(100) = 'HRM_APPLICATION_DELAY_IN';
;with c(one,last,rest) as (
select cast(lower(left(#str,1)) as varchar(max)),
left(#str,1), stuff(lower(#str),1,1,'')
union all
select one+case when last='_'
then upper(left(rest,1))
else left(rest,1) end,
left(rest,1), stuff(rest,1,1,'')
from c
where rest > ''
)
select max(one)
from c;
That can be extended to a column in a table
-- Sample table
declare #tbl table (
id int identity not null primary key clustered,
str varchar(100)
);
insert #tbl values
('HRM_APPLICATION_DELAY_IN'),
('HRM_APPLICATION_DELAY_OUT'),
('_HRM_APPLICATION_DELAY_OUT'),
(''),
(null),
('abc<de_fg>hi');
-- the query
;with c(id,one,last,rest) as (
select id,cast(lower(left(str,1)) as varchar(max)),
left(str,1), stuff(lower(str),1,1,'')
from #tbl
union all
select id,one+case when last='_'
then upper(left(rest,1))
else left(rest,1) end,
left(rest,1), stuff(rest,1,1,'')
from c
where rest > ''
)
select id,max(one)
from c
group by id
option (maxrecursion 0);
-- result
ID COLUMN_1
1 hrm_Application_Delay_In
2 hrm_Application_Delay_Out
3 _Hrm_Application_Delay_Out
4
5 (null)
6 abc<de_Fg>hi
select
replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(lower('HRM_APPLICATION_DELAY_IN'),'_a','A'),'_b','B'),'_c','C'),'_d','D'),'_e','E'),'_f','F'),
'_g','G'),'_h','H'),'_i','I'),'_j','J'),'_k','K'),'_l','L'),
'_m','M'),'_n','N'),'_o','O'),'_p','P'),'_q','Q'),'_r','R'),
'_s','S'),'_t','T'),'_u','U'),'_v','V'),'_w','W'),'_x','X'),
'_y','Y'),'_z','Z'),'_','')
Bellow two steps can solve problem,as example i use sys.table.user can use any one
declare #Ret varchar(8000), #RetVal varchar(8000), #i int, #count int = 1;
declare #c varchar(10), #Text varchar(8000), #PrevCase varchar, #ModPrefix varchar(10);
DECLARE #FileDataTable TABLE(TableName varchar(200))
INSERT INTO #FileDataTable
select name FROM sys.tables where object_name(object_id) not like 'sys%' order by name
SET #ModPrefix = 'Pur'
DECLARE crsTablesTruncIns CURSOR
FOR select TableName FROM #FileDataTable
OPEN crsTablesTruncIns
FETCH NEXT FROM crsTablesTruncIns INTO #Text
WHILE ##FETCH_STATUS = 0
BEGIN
SET #RetVal = '';
select #i=1, #Ret = '';
while (#i <= len(#Text))
begin
SET #c = substring(#Text,#i,1)
--SET #Ret = #Ret + case when #Reset=1 then UPPER(#c) else LOWER(#c)
IF(#PrevCase = '_' OR #i = 1)
SET #Ret = UPPER(#c)
ELSE
SET #Ret = LOWER(#c)
--#Reset = case when #c like '[a-zA-Z]' then 0 else 1 end,
if(#c like '[a-zA-Z]')
SET #RetVal = #RetVal + #Ret
if(#c = '_')
SET #PrevCase = '_'
else
SET #PrevCase = ''
SET #i = #i +1
end
SET #RetVal = #ModPrefix + #RetVal
print cast(#count as varchar) + ' ' + #RetVal
SET #count = #count + 1
EXEC sp_RENAME #Text , #RetVal
SET #RetVal = ''
FETCH NEXT FROM crsTablesTruncIns INTO #Text
END
CLOSE crsTablesTruncIns
DEALLOCATE crsTablesTruncIns
I'd like to show you my nice and simple solution. It uses Tally function to split the string by pattern, in our case by underscope. For understanding Tally functions, read this article.
So, this is how my tally function looks like:
CREATE FUNCTION [dbo].[tvf_xt_tally_split](
#String NVARCHAR(max)
,#Delim CHAR(1))
RETURNS TABLE
as
return
(
WITH Tally AS (SELECT top (select isnull(LEN(#String),100)) n = ROW_NUMBER() OVER(ORDER BY [name]) from master.dbo.syscolumns)
(
SELECT LTRIM(RTRIM(SUBSTRING(#Delim + #String + #Delim,N+1,CHARINDEX(#Delim,#Delim + #String + #Delim,N+1)-N-1))) Value, N as Ix
FROM Tally
WHERE N < LEN(#Delim + #String + #Delim)
AND SUBSTRING(#Delim + #String + #Delim,N,1) = #Delim
)
)
This function returns a table, where each row represents part of string between #Delim (in our case between underscopes). Rest of the work is simple, just cobination of LEFT, RIGHT, LEN, UPPER and LOWER functions.
declare #string varchar(max)
set #string = ' HRM_APPLICATION_DELAY_IN'
-- convert to lower case
set #string = LOWER(#string)
declare #output varchar(max)
-- build string
select #output = coalesce(#output + '_','') +
UPPER(left(Value,1)) + RIGHT(Value, LEN(Value) - 1)
from dbo.tvf_xt_tally_split(#string, '_')
-- lower first char
select left(lower(#output),1) + RIGHT(#output, LEN(#output) - 1)

Increasing Alphanumeric value in user defined function

I'm trying to code a user defined function under SQL Server 2005 that will increase integer part of alphanumeric value by one. For example, uf_AlphanumericIncrease ('A000299') should return 'A000300'. Here's what I've done so far;
ALTER FUNCTION uf_AlphaNumericIncrement
(
#ID varchar(10)
)
RETURNS VARCHAR(10) AS
BEGIN
DECLARE #RES varchar(10);
IF SUBSTRING(#ID,LEN(#ID),1)='9'
SET #RES=SUBSTRING(#ID,1,LEN(#ID)-2)+CAST (CAST(SUBSTRING(#ID,LEN(#ID)-1,1) AS smallint)+1 AS VARCHAR(10))+'0';
ELSE
SET #RES=SUBSTRING(#ID,1,LEN(#ID)-1)+CAST (CAST(SUBSTRING(#ID,LEN(#ID),1) AS smallint)+1 AS VARCHAR(10));
RETURN #RES;
END
But as you can see it only works for last digit. I need to get it under loop so it can work for A002999 and so on. Any ideas?
Edit: Given value might have alpha prefix longer than one character, or none at all.
Now works with any length of prefix and number part (well upto 20 each)
DECLARE #prefix varchar(20), #numberstr varchar(20), #number int, #Val varchar(40)
SELECT #Val = 'ABCD000006'
--SELECT #Val = 'A03'
SELECT #prefix = LEFT(#Val, PATINDEX ('%[0-9]%', #Val) -1)
SELECT #numberstr = SUBSTRING(#Val, PATINDEX ('%[0-9]%', #Val), 8000)
SELECT #number = CAST(#numberstr AS int) + 1
SELECT #prefix + RIGHT(REPLACE(SPACE(LEN(#numberstr)), ' ', '0') + CAST(#number AS varchar(20)), LEN(#numberstr))
CREATE FUNCTION dbo.uf_ANinc
(
#in varchar(10)
)
RETURNS varchar(10) AS
BEGIN
DECLARE #prefix varchar(10);
DECLARE #res varchar(10);
DECLARE #pad varchar(10);
DECLARE #num int;
DECLARE #start int;
SET #start = PATINDEX('%[0-9]%',#in);
SET #prefix = LEFT(#in, #start - 1 );
SET #num = CAST( RIGHT( #in, LEN(#in) - #start ) AS int ) + 1
SET #pad = REPLICATE( '0', 10 - LEN(#prefix) - CEILING(LOG(#num)/LOG(10)) );
SET #res = #prefix + #pad + CAST( #num AS varchar);
RETURN #res
END
GO
SELECT dbo.uf_ANinc('ABC000123');
Assuming that the alpha part of your alphanumeric is always only the first character, this should work.
EDIT: OK, if the alpha part varies in length this gets ugly pretty quickly for a UDF. This is just a quick-and-dirty solution, so it can probably be optimized a bit, but the logic should be sound.
EDIT AGAIN: patindex() ftw - I learned something new today ;-)
ALTER FUNCTION uf_AlphaNumericIncrement
(
#ID varchar(10)
)
RETURNS VARCHAR(10) AS
BEGIN
DECLARE #RES varchar(10);
DECLARE #num int;
DECLARE #prefix varchar(10);
set #prefix = left(#id, patindex('%[0-9]%', #id) -1)
set #num = cast(right(#id, len(#id) - len(#prefix)) as int) + 1
set #res = #prefix + replicate('0', len(#id) - len(#prefix) - len(#num)) + cast(#num as varchar(10))
RETURN #RES;
END