How can i find the pattern identified by PATINDEX() - sql-server

Which pattern is identified by PATINDEX in the below statement? Could any one help me analyse it?
How can we find which of ('I','II','III') is identified ?
select PATINDEX ('%[I,II,III]%','sjfhasjdg II')
Please help me finding it.

This is not how you use PATINDEX. , is not an alternation operator.
You are telling it to find characters in the set I,II,III which just repeats a lot of characters so can be simplified to "find the first location of either I or ,"
You could try
WITH SearchTerms(Term)
AS (SELECT 'I'
UNION ALL
SELECT 'II'
UNION ALL
SELECT 'III'),
ToBeSearched(string)
AS (SELECT 'sjfhasjdg II')
SELECT string,
Term,
Charindex(Term, string) AS Location
FROM ToBeSearched
JOIN SearchTerms
ON Charindex(Term, string) > 0
Returns
string Term Location
------------ ---- -----------
sjfhasjdg II I 11
sjfhasjdg II II 11
Of course both I and II match as anything that matches the second will always match the first.

Related

SQL Server - How to get last numeric value in the given string

I am trying to get last numeric part in the given string.
For Example, below are the given strings and the result should be last numeric part only
SB124197 --> 124197
287276ACBX92 --> 92
R009321743-16 --> 16
How to achieve this functionality. Please help.
Try this:
select right(#str, patindex('%[^0-9]%',reverse(#str)) - 1)
Explanation:
Using PATINDEX with '%[^0-9]%' as a search pattern you get the starting position of the first occurrence of a character that is not a number.
Using REVERSE you get the position of the first non numeric character starting from the back of the string.
Edit:
To handle the case of strings not containing non numeric characters you can use:
select case
when patindex(#str, '%[^0-9]%') = 0 then #str
else right(#str, patindex('%[^0-9]%',reverse(#str)) - 1)
end
If your data always contains at least one non-numeric character then you can use the first query, otherwise use the second one.
Actual query:
So, if your table is something like this:
mycol
--------------
SB124197
287276ACBX92
R009321743-16
123456
then you can use the following query (works in SQL Server 2012+):
select iif(x.i = 0, mycol, right(mycol, x.i - 1))
from mytable
cross apply (select patindex('%[^0-9]%', reverse(mycol) )) as x(i)
Output:
mynum
------
124197
92
16
123456
Demo here
Here is one way using Patindex
SELECT RIGHT(strg, COALESCE(NULLIF(Patindex('%[^0-9]%', Reverse(strg)), 0) - 1, Len(strg)))
FROM (VALUES ('SB124197'),
('287276ACBX92'),
('R009321743-16')) tc (strg)
After reversing the string, we are finding the position of first non numeric character and extracting the data from that position till the end..
Result :
-----
124197
92
16

Changing character in a string of characters

I was wondering regarding how to edit the following column that exists in oracle DB
PPPPFPPPPPPPPPPPPPPPPPPPPPPPPFPPPPPPPP
I want to only set the 5th F with P without affecting other structure.
I've around 700 records and I want to change that position (5th) on all users to P
I was thinking of PLSQL instead of a query, so could you please advice.
Thanks
Use REGEXP_REPLACE:
> SELECT REGEXP_REPLACE('PPPPFPPPPPPPPPPPPPPPPPPPPPPPPFPPPPPPPP', '^(\w{4}).(.*)', '\1P\2') AS COL_REGX FROM dual
COL_REGX
--------------------------------------
PPPPPPPPPPPPPPPPPPPPPPPPPPPPPFPPPPPPPP
Klashxx answer is a good one - REGEXP_REPLACE is the way to go. Old fashioned way built up bit by bit so you can see what's going on :
WITH
test_data (text)
AS (SELECT '1234F1234F1234F1234F1234F1234F1234' FROM DUAL
)
SELECT
text
,INSTR(text,'F',1,5) --fifth occurence
,SUBSTR(text,1,INSTR(text,'F',1,5)-1) --substr up to that point
,SUBSTR(text,1,INSTR(text,'F',1,5)-1)||'P' --add P
,SUBSTR(text,1,INSTR(text,'F',1,5)-1)||'P'||SUBSTR(text,INSTR(text,'F',1,5)+1) --add remainder of string
FROM
test_data
;
So what you're trying to do would be something like
UPDATE <your table>
SET <your column> = SUBSTR(<your column>,1,INSTR(<your column>,'F',1,5)-1)||'P'||SUBSTR(<your column>,INSTR(<your column>,'F',1,5)+1)
..assuming you want to update all rows
The solution below looks for the first five characters at the beginning of the input string. If found, it keeps the first four unchanged and it replaces the fifth with the letter P. Note that if the input string is four characters or less, it is left unchanged. (This includes NULL as the input string, shown in the WITH clause which creates sample strings and also in the output - note that the output has FIVE rows, even though there is nothing visible in the last one.)
with
test_data ( str ) as (
select 'ABCDEFGH' from dual union all
select 'PPPPF' from dual union all
select 'PPPPP' from dual union all
select '1234' from dual union all
select null from dual
)
select str, regexp_replace(str, '^(.{4}).', '\1P') as replaced
from test_data
;
STR REPLACED
-------- --------
ABCDEFGH ABCDPFGH
PPPPF PPPPP
PPPPP PPPPP
1234 1234
5 rows selected.
Flip the 5th 'bit' to a 'P' where it's currently an 'F'.
update table
set column = regexp_replace(column , '^(.{4}).', '\1P')
where regexp_like(column , '^.{4}F');

Slicing the word to rows -TERADATA

I want to slice a word eg: SMILE into :
S
M
I
L
E
I did it like this
SEL SUBSTR(EMP_NAME,1,1) FROM etlt5.employe where EMP_ID='28008'
UNION ALL
SEL SUBSTR(EMP_NAME,2,1) FROM etlt5.employe where EMP_ID='28008'
UNION ALL
SEL SUBSTR(EMP_NAME,3,1) FROM etlt5.employe where EMP_ID='28008'
I also tried it with recursive query but no final results.is there a better way of doing this because this looks more like a hardcoded one.
You could use STRTOK_SPLIT_TO_TABLE to do this. STRTOK_SPLIT_TO_TABLE splits a field by a delimiter and then takes each token (stuff between the delimiter) and sticks it in it's own record of a new derived table.
In your case you don't have a delimiter between the characters of "SMILE" so we can use some REGEXP_REPLACE magic to stick a comma between each letter, and then split that to a table:
WITH test (id, word) AS (SELECT 1, 'SMILE')
SELECT D.*
FROM TABLE (strtok_split_to_table(test.id, REGEXP_REPLACE(test.word, '([a-zA-Z])', ',\1'), ',')
RETURNS
( id integer
, rownum integer
, new_col varchar(100)character set unicode)
) as d
I've used this STRTOK_SPLIT_TO_TABLE(REGEXP_REPLACE()) before to split apart document numbers in order to determine a check digit, so it definitely has its uses.
May I ask why you want to do that?
You need a table with a sequence from 1 to the max length of EMP_NAME:
select SUBSTR(EMP_NAME,n,1)
FROM etlt5.employe CROSS JOIN number_table
where EMP_ID='28008'

Make substring using a specific delimiter in SQL

I want to make a substring of a column value using a specific delimiter.I tried SUBSTRING_INDEX,but it doesn't work for SQL.Is there any way to achieve this??
Column values are:
ARTCSOFT-1111
ARTCSOFT-1112
ARTCSOFT-1113
and I want to achieve the same thing in SQL:
SUBSTRING_INDEX(Code,'SOFT-',1))
i.e I want the number after SOFT- in my substring.I can't use only - because before SOFT- there is chance that - may occur(rare case,but I don't want to take a chance)
Try using just SUBSTRING . For example
SELECT
SUBSTRING(code, CHARINDEX('SOFT-', code) + 5, LEN(code)) AS [name] from dbo.yourtable
hope this helps.
Tested Result:
SELECT RIGHT(Code , CHARINDEX ('-' ,REVERSE(Code))-1)
Read this as: Get the rightmost string after the first '-' in a reversed string - which is the same as the string after the last '-' character.
Try This Query:
select substring(col,charindex('-',col)+1,len(col)-charindex('-',col)) from #Your_table
Explanation of Query:
Here Charindex find the '-' delimeter [length] IN Given String and now that Result[length+1] is our starting point and ending length is [len(col)-starting length] gives ending point and then use substring Function to split a string according to our requirement.
Result of Query:
Required_col
1111
1112
1113

Sql Server's regex LIKE - behaviour clarification?

Someone asked here how to get only values which are a number :
So , if the table is :
DECLARE #Table TABLE(
Col nVARCHAR(50)
)
INSERT INTO #Table SELECT 'ABC'
INSERT INTO #Table SELECT '234.62'
INSERT INTO #Table SELECT '10:10:10:10'
INSERT INTO #Table SELECT 'France'
INSERT INTO #Table SELECT '2'
then - the desired results are :
234.62
2
But when I tested this query :
SELECT * FROM #Table WHERE Col LIKE '%[0-9.]%' --expected to see only 234.62
it showed :
234.62
10:10:10:10
2
Question #1
How come 10:10:10:10 , 2 satisfies the condition ?
Question #2
I saw this answer here which does work
SELECT * FROM #Table WHERE Col NOT LIKE '%[^0-9.]%'
But I don't understand why this works. AFAIU - it selects all values which are not like (not(has number) and not( has dot)) which is ===>(de morgan)===> not like ( has number or has dot)
Can someone please shed light ?
nb I already know that isnumeric can be used also , but it's unsafe (+). also valid wildcards are %,_,[],[^]
Any particular use of [set] within a LIKE expression is a check against one character in the target string.
So, LIKE '%[0-9.]%' says - % - match 0-to-many arbitrary characters, then [0-9.] match one character in the set 0-9., and then % match 0-to-many arbitrary characters. Paraphrased, it says "match any string that contains at least one character in the set 0-9.". So, 10:10:10:10 can be matched as 0 arbitrary characters, then 1 matches [0-9.], and then 0:10:10:10 matches the final %.
LIKE '%[^0-9.]%' says - % - match 0-to-many arbitrary characters, then [^0-9.] match one character not in the set 0-9., and then % match 0-to-many arbitrary characters. Paraphrased, it says "match any string that contains at least one character outside of the set 0-9.. So when we apply the NOT to the front of that, we are saying "match any string that doesn't contain at least one character outside of the set 0-9." or "match strings that only contain characters in the set 0-9..
Essentially, the double-negative is a way to make an assertion about all characters in the string.

Resources