I have a string like:
#TempCol = sigma_x1,sigma_x2,...,sigma_xd,XX,YY,ZZ
So how could I get a specific part of that string, based on, lets say an index.
so
if index is 0, get sigma_x1
if index is 1, get sigma_x2
if index is 2, get sigma_x3
if index is d-1,get sigma_xd
if index is d, get XX,
if index is d+1,get YY
and so on.
Previously Andriy M solved a similar issue, his code gets a substring based on a nomber but returns a substring the following way:
if #d is 1,get sigma_x1
if #d is 2,get sigma_x1,sigma_x2
if #d is 3,get sigma_x1,sigma_x2,sigma_x3
if #d is 4,get sigma_x1,sigma_x2,sigma_x3,sigma_x4
if #d is d,get sigma_x1,sigma_x2,sigma_x3,sigma_x4,...,sigma_xd (ALL THE STRING)
How to update this procedure to get specific element?
DECLARE #TempCol varchar(max), #d int, #p int, #Result varchar(max);
SET #TempCol = 'item1,item2,itemA,itemB,item#,item$';
SET #d = 3;
SET #p = 1;
WHILE #d > 0 AND #p > 0 BEGIN
SET #p = CHARINDEX(',', #TempCol, #p);
IF #p > 0 SET #p = #p + 1;
SET #d = #d - 1;
END;
IF #p = 0
SET #Result = #TempCol
ELSE
SET #Result = SUBSTRING(#TempCol, 1, #p - 2);
SELECT #Result;
just try this. hope this will meet your needs.
create a function GetIndex, which accepts string and delimiter to split the string
CREATE FUNCTION dbo.GetIndex(#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE (itemindex int identity(1,1), items varchar(8000))
as
begin
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable(Items) values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end
and you can query like,
suppose you need 4th index then
select * from dbo.GetIndex(#TempCol,',') where itemindex = 4
to get an item of 4th index then
select items from dbo.GetIndex(#TempCol,',') where itemindex = 4
to get item to a variable
select #Aux = items from dbo.GetIndex(#TempCol,',') where itemindex = 4
Related
How can I output text until it is ascii in SQL?
Here is what I am trying to do:
DECLARE #input VARCHAR(20)
SET #input = 'text'
DECLARE #index INT
SET #index = 1
DECLARE #output VARCHAR(32)
SET #output = ''
WHILE CHAR(ASCII(SUBSTRING(#input, #index, 1))) LIKE '[ -~]'
BEGIN
SET #output = #output + CHAR(ASCII(SUBSTRING(#input, #index, 1)))
SET #index = #index + 1
END
SELECT #output
But in the end I am getting an empty string. Why? What am I missing here?
I am expecting the value of the #output to be 'text' in the end of the script.
UPDATE
If I update the script to the
DECLARE #input VARCHAR(20)
SET #input = 'text'
DECLARE #index INT
SET #index = 1
DECLARE #output VARCHAR(32)
SET #output = ''
WHILE CHAR(ASCII(SUBSTRING(#input, #index, 1))) LIKE '[a-b]'
BEGIN
SET #output = #output + CHAR(ASCII(SUBSTRING(#input, #index, 1)))
SET #index = #index + 1
END
SELECT #output
It will work as expected. But here I just shrinked the set from all printable ascii characters to only small letters. Why does the shrinked set [a-b] include the text characters and the extended set [ -~] does not?
A space is not a valid range delimiter so LIKE [ -~] will not work. That becomes a test for those three characters only.
You could check the ASCII code directly, rather than using LIKE:
DECLARE #input VARCHAR(20)
SET #input = 'text'
DECLARE #index INT
SET #index = 1
DECLARE #output VARCHAR(32)
SET #output = ''
WHILE ASCII(SUBSTRING(#input, #index, 1)) BETWEEN 32 AND 126
BEGIN
SET #output = #output + CHAR(ASCII(SUBSTRING(#input, #index, 1)))
SET #index = #index + 1
END
SELECT #output
demo
Side note: It's possible to get unexpected results with LIKE ranges because the comparison is collation-aware.
Answer copied from the duplicate question on Database Administrators
I have my table with Column MailText which has values like
1. <strong>abc</strong>:<description1> <strong>bcd</strong>:<description2>
2. <strong>efg</strong>:<description3> <strong>hgl</strong>:<description7>
Upon update I want values like
1. <strong>abc</strong>:<abc> <strong>bcd</strong>:<bcd>
2. <strong>efg</strong>:<efg> <strong>hgl</strong>:<hgl>
Please help with dynamic replacement that it would update all string within <strong> tag to <description>. <strong> tag may contain any values.
CREATE FUNCTION GetString
(
#s NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #trav NVARCHAR(2000) = #s,
#length INT,
#count INT = 1,
#startIndex INT = 0,
#endIndex INT = 0,
#replaceStartIndex INT = 0,
#repalceEndIndex INT = 0,
#replaceword NVARCHAR(2000),
#newWord NVARCHAR(2000)
SELECT #length = LEN(#Trav)
WHILE ((#count + #startIndex) <= #length)
BEGIN
SET #startIndex = CHARINDEX('<strong>', #trav, #startIndex) + LEN('<strong>')
IF (#startIndex > 8)
BEGIN
SET #endIndex = CHARINDEX('</strong>', #trav, #startIndex)
SET #newWord = SUBSTRING(#trav, #startIndex, (#endIndex - #startIndex))
SET #replaceStartIndex = CHARINDEX(':', #trav, #startIndex) + 2
SET #repalceEndIndex = CHARINDEX('>', #trav, #replaceStartIndex)
SET #replaceword = SUBSTRING(
#trav,
#replaceStartIndex,
(#repalceEndIndex - #replaceStartIndex)
)
--SELECT #replaceword as 'repword', #newWord as 'newword'
SET #trav = REPLACE (#trav, #replaceword, #newWord)
SET #count = #repalceEndIndex
END
ELSE
BEGIN
SET #count = #count + 1
END
END
RETURN #trav
END
GO
IF OBJECT_ID('tempdb..#table') IS NOT NULL
DROP TABLE #table
CREATE TABLE #table
(
string VARCHAR(1000)
)
INSERT INTO #table
SELECT
'1. <strong>abc</strong>:<description1> <strong>bcd</strong>:<description2>'
INSERT INTO #table
SELECT
'2. <strong>efg</strong>:<description3> <strong>hgl</strong>:<description7>'
UPDATE #table
SET string = [dbo].[GetString](#table.string)
SELECT *
FROM #table
Need help to create a function that returns TRUE or FALSE. TRUE - if type 1 or 3 words (like '__hello_', '_hello', '_hello my frend' - spaces should be cut), if the condition is not fulfilled FALSE
CREATE FUNCTION dbo.nazvFac(#f nvarchar(30))
RETURNS bit
AS
BEGIN
DECLARE #l int = 1, #s nvarchar(30), #i int = 0, #b bit
WHILE LTRIM(RTRIM(LEN(#f))) >= #l --error here, but I do not know how to fix it
BEGIN
SET #s = SUBSTRING(#f, #l, 1)
IF #s BETWEEN 'А' AND 'я'
SET #l += 1
ELSE IF #s = ' '
BEGIN
SET #l -= 1
SET #s = SUBSTRING(#f, #l, 1)
SET #s = RTRIM(#s)
SET #l += 2
SET #i += 1
END
ELSE
BREAK
END
IF #i = 0 OR #i = 2
SET #b = 'TRUE'
ELSE
SET #b = 'FALSE'
RETURN #b
END
GO
WHILE LTRIM(RTRIM(LEN(#f))) >= #l --error here, but I do not know how to fix it
LEN() returns an int, which you are then passing to a string function: RTRIM().
You want to return TRUE only if there are one or three words? This should do it:
CREATE FUNCTION dbo.nazvFac(#f NVARCHAR(30))
RETURNS BIT
AS
BEGIN
DECLARE #l INT, #b BIT
SET #l = LEN(#f) - LEN(REPLACE(#f, ' ', '')) + 1
IF #l == 1 OR #l == 3
SET #b = 'TRUE'
ELSE
SET #b = 'FALSE'
RETURN #b
END
Also, JC. is right about the len() error.
You should trim the string and then check the length.
CREATE FUNCTION dbo.nazvFac(#f NVARCHAR(30))
RETURNS BIT
AS
BEGIN
DECLARE #l INT = 1, #s NVARCHAR(30), #i INT = 0, #b BIT
WHILE LEN(LTRIM(RTRIM(#f))) >= #l --I think youn need to trim the string and then check length
BEGIN
SET #s = SUBSTRING(#f, #l, 1)
IF #s BETWEEN 'А' AND 'я'
SET #l += 1
ELSE IF #s = ' '
BEGIN
SET #l -= 1
SET #s = SUBSTRING(#f, #l, 1)
SET #s = RTRIM(#s)
SET #l += 2
SET #i += 1
END
ELSE
BREAK
END
IF #i = 0 OR #i = 2
SET #b = 'TRUE'
ELSE
SET #b = 'FALSE'
RETURN #b
END
GO
I have the following slash-delimited example strings and need to split them:
Record---String
1--------ABC
2--------DEF/123
3--------GHI/456/XYZ
The strings will always have 1 - 3 parts; no more, no less.
To split them I have been using this function:
CREATE FUNCTION [dbo].[Split] (
#chunk VARCHAR(4000)
,#delimiter CHAR(1)
,#index INT
)
RETURNS VARCHAR(1000)
AS
BEGIN
DECLARE #curIndex INT = 0
,#pos INT = 1
,#prevPos INT = 0
,#result VARCHAR(1000)
WHILE #pos > 0
BEGIN
SET #pos = CHARINDEX(#delimiter, #chunk, #prevPos);
IF (#pos > 0)
BEGIN -- Characters between position and previous position
SET #result = SUBSTRING(#chunk, #prevPos, #pos - #prevPos)
END
ELSE
BEGIN -- Last Delim
SET #result = SUBSTRING(#chunk, #prevPos, LEN(#chunk))
END
IF (#index = #curIndex)
BEGIN
RETURN #result
END
SET #prevPos = #pos + 1
SET #curIndex = #curIndex + 1;
END
RETURN '' -- Else Empty
END
To split the strings, I call this function like so:
MyField1 = dbo.Split(MyInputString, '/', 0),
MyField2 = dbo.Split(MyInputString, '/', 1),
MyField3 = dbo.Split(MyInputString, '/', 2)
The expected results would be
Record 1:
MyField1 = ABC
MyField2 = NULL
MyField3 = NULL
Record 2:
MyField1 = DEF
MyField2 = 123
MyField3 = NULL
Record 3:
MyField1 = GHI
MyField2 = 456
MyField3 = XYZ
It is almost doing what I had hoped, except the last character of MyField1 for Record 1 is being truncated resulting in "AB" instead of "ABC". I believe this is because there is no slash delimiter for this one-part string.
Unfortunately, I did not write this function and my SQL skills are a bit weak. What should I change to make this function return proper results when there is no delimiter in the string?
The following fixes your "SPLIT" function. Add the following line just before the WHILE.
SET #chunk = #chunk + '/'
I would move the charindex to before the while:
alter FUNCTION [dbo].[Split] (
#chunk VARCHAR(4000)
,#delimiter CHAR(1)
,#index INT
)
RETURNS VARCHAR(1000)
AS
BEGIN
DECLARE #curIndex INT = 0
,#pos INT = 1
,#prevPos INT = 0
,#result VARCHAR(1000)
SET #pos = CHARINDEX(#delimiter, #chunk, #prevPos);
if #pos= 0 return #chunk
WHILE #pos > 0
BEGIN
SET #pos = CHARINDEX(#delimiter, #chunk, #prevPos);
IF (#pos > 0)
BEGIN -- Characters between position and previous position
SET #result = SUBSTRING(#chunk, #prevPos, #pos - #prevPos)
END
ELSE
BEGIN -- Last Delim
SET #result = SUBSTRING(#chunk, #prevPos, LEN(#chunk))
END
IF (#index = #curIndex)
BEGIN
RETURN #result
END
SET #prevPos = #pos + 1
SET #curIndex = #curIndex + 1;
SET #pos = CHARINDEX(#delimiter, #chunk, #prevPos);
END
RETURN #chunk -- Else Empty
END
DECLARE #curIndex INT = 0
,#pos INT = 1
,#prevPos INT = 0
,#result VARCHAR(1000)
if CHARINDEX(#delimiter, #chunk, #prevPos)= 0
set #chunk=#chunk+#delimiter
using (#johns correct solution)
I'm writing a function that takes a string and has to replace any non-numeric character with two numeric characters taken from a table. This is the code I use to explore the string and find the non-numeric characters:
SET #string = '1a2b3c4d'
SET #wcount= 0
SET #index = 1
SET #len= LEN(#string)
WHILE #index<= #len
BEGIN
SET #char = SUBSTRING(#string, #index, 1)
IF #char LIKE '%[a-z]%'
PRINT 'char ' + CONVERT(varchar(10), #index)
ELSE
PRINT #char
SET #index= #index+ 1
END
The output is the following
1
char 2
2
char 4
3
char 6
4
char 8
Now, when I find a non-numeric character I have to replace it with two numeric chars taken from a table by a select. E.g.
SELECT #temp = REPLACEMENT FROM Conversion_Tab WHERE EXPR = #char
In conclusion, if I have the following string '1a2a3a4a' and the replacement for 'a' is '88' the resulting string should be '188288388488'
Thanks in advance for any help.
Bye!
Try this
DECLARE #string VARCHAR(100)
DECLARE #outstring VARCHAR(100)
DECLARE #wcount INT
DECLARE #temp INT
DECLARE #index INT
DECLARE #len INT
DECLARE #char CHAR
SET #string = '1a2a3a4a'
SET #wcount= 0
SET #index = 1
SET #len= LEN(#string)
SET #outstring = ''
WHILE #index<= #len
BEGIN
SET #char = SUBSTRING(#string, #index, 1)
IF #char LIKE '%[a-z]%'
BEGIN
SELECT #temp = REPLACEMENT FROM #Conversion_Tab WHERE EXPR = #char
SET #outstring = #outstring + CONVERT(VARCHAR(10),#temp)
END
ELSE
BEGIN
SET #outstring = #outstring + #char
END
SET #index= #index+ 1
END
SELECT #outstring
SQL FIDDLE DEMO
looks like you need isnumeric(). so if not isnumeric(char) replace it with your lookup value.
taken from the other answer but produces the same result
DECLARE #string VARCHAR(100)
DECLARE #outstring VARCHAR(100)
DECLARE #wcount INT
DECLARE #temp INT
DECLARE #index INT
DECLARE #len INT
DECLARE #char CHAR
SET #string = '1a2a3a4a'
SET #wcount= 0
SET #index = 1
SET #len= LEN(#string)
SET #outstring = ''
WHILE #index<= #len
BEGIN
SET #char = SUBSTRING(#string, #index, 1)
IF ISNUMERIC(#char) = 0
BEGIN
SELECT #temp = REPLACEMENT FROM #Conversion_Tab WHERE EXPR = #char
SET #outstring = #outstring + CONVERT(VARCHAR(10),#temp)
END
ELSE
BEGIN
SET #outstring = #outstring + #char
END
SET #index= #index+ 1
END