SQL substring from a string - sql

I have a table XYZ with column FileName which has values as follows:
CCA_Type-PROPOSAL_Id-45845_Test1.txt
CPA_Type-PROPOSAL_Id-490845_Test2.txt
I want to update this column so that it contains only the filename and remove other characters preceeding:
Test1.txt
Test2.txt
Hence I wrote the following:
Update XYZ
set FileName = (select RIGHT(FileName,CHARINDEX('_',REVERSE(FileName),0)-1))
But if a FileName has a value like:
CCA_Type-PROPOSAL_Id-45845_Test_RR1.txt
My script returns RR1.txt instead of Test_RR1.txt! It finds the last underscore and returns substring from there. How can I change it so that I get the 3rd underscore and return a substring following it!

charindex optionally takes a start location. You could chain several together:
select right(FileName, len(FileName) -
charindex('_', FileName,
charindex('_', FileName,
charindex('_', FileName)
+ 1)
+ 1))
So you're asking for "The first underscore after (the first underscore after (the first underscore))" - i.e. the third underscore.

something like this should work:
declare #table table (
[file_name] [sysname]
);
declare #pattern [sysname]= N'_test';
insert into #table
([file_name])
values (N'CCA_Type-PROPOSAL_Id-45845_Test1.txt'),
(N'CPA_Type-PROPOSAL_Id-490845_Test2.txt'),
(N'CCA_Type-PROPOSAL_Id-45845_Test_RR1.txt');
select [file_name] as [file_name]
, charindex(#pattern, lower([file_name])) as [character_index_of_pattern]
, substring([file_name], charindex(#pattern, lower([file_name])), len([file_name])) as [desired_output]
from #table;

Related

Add String in a String before ".extention"?

I have a table like:
ID NAME
----------------
35 File.png
What I want to do is update that record as:
ID NAME
----------------
35 File_35.png
I have this:
DECLARE arch_cursor CURSOR FOR SELECT Id from dbo.Archivos WHERE Nombre LIKE ('%' + #Id_Relacion_Articulo_Archivo + '%')
OPEN contact_cursor;
FETCH NEXT FROM arch_cursor
INTO #Id_cur
WHILE(##FETCH_STATUS = 0 )
UPDATE dbo.Archivos SET Nombre ...
CLOSE arch_cursor;
DEALLOCATE arch_cursor;
I know that STUFF statement can do something like put a string on a specific place of the string, but somebody know how to specify "insert string before "." without losing the left chars too?"
select id
, concat(left(name, charindex('.', name)-1), '_', id, RIGHT(name,(CHARINDEX('.', name))-1)) NAME
from test
Here is a demo
Also you can do it with a replace:
select id
, replace(name, '.', concat('_',id,'.'))
from test
And here is the one option you can use if you will look from the right (first occurrence of the character '.'):
select id
, concat(substring(name, 1, len(name)-charindex('.', (reverse(name))))
, '_'
, id
, substring(name, len(name)-charindex('.', (reverse(name)))+1, charindex('.', (reverse(name)))))
from test
Here is a demo where you can see all 3 of this examples in action with this two rows of data:
insert into test values (35, 'File.png')
insert into test values (55,
'File.File.png')
If no files can have a . in the name (apart from to denote the extension) I find STUFF easiest for this:
SELECT ID, [Name],
STUFF([Name], CHARINDEX('.',[Name]),0,CONCAT('_',ID)) AS NewName
FROM (VALUES(35,'File.png'))V(ID,[Name]);
If there could be multiple . characters and it needs to prior to the last one, you have to use the (expensive) function REVERSE:*
SELECT ID, [Name],
STUFF([Name], LEN([Name]) - CHARINDEX('.',REVERSE([Name]))+1,0,CONCAT('_',ID)) AS NewName
FROM (VALUES(35,'File.png'),(36,'File.2.png'))V(ID,[Name])
Also, don't loop. Just do this in a set based method. You're using a RDBMS, not a Programming Language:
UPDATE dbo.YourTable
SET File = STUFF([Name], CHARINDEX('.',[Name]),0,CONCAT('_',ID));

SQL Trim on a file name

I am trying to trim a long file name and just want to get the last characters of that file name which is after the last forward slash (\) and I also want to eliminate the .xlsx at the end of the file name as well.
Original:
sasa\sasas\sasas\1234_IASS.xlsx
Expected Output:
1234_IASS
Your comments state that both your file path and file extension are constant. If the number of characters in your file is also constant the simplest solution is to use SUBSTRING.
SELECT SUBSTRING(YourColumn, 18, 9)
FROM YourTable
If the number of characters is changing, a more robust solution is to use RIGHT to extract the file name and REPLACE to remove the file extension.
SELECT REPLACE(RIGHT(YourColumn, LEN(YourColumn) - 17), '.xlsx', '')
FROM YourTable
If you need a more dynamic solution, you can first extract the filename as shown.
SELECT RIGHT(YourColumn, CHARINDEX('\', REVERSE(YourColumn)) - 1)
FROM YourTable
You can then combine this with REPLACE as before to remove the extension.
SELECT REPLACE(RIGHT(YourColumn, CHARINDEX('\', REVERSE(YourColumn)) - 1), '.xlsx', '')
FROM YourTable
You can try this it will work as said in the comment the file extension are fixed.
SELECT
Replace(
RIGHT('\' + RTRIM('sasa\sasas\sasas\1234_IASS.xlsx'), CHARINDEX('\', REVERSE('\' + RTRIM('sasa\sasas\sasas\1234_IASS.xlsx'))) - 1)
,'.xlsx', '')
as FileName
You can find the live example here.
You say your directory is the same and the extension is always the same? Replace [path] with your table column name:
select replace(replace([path],'sasa\sasas\sasas\',''),'.xlsx','')
declare #x varchar(100) = 'sasa\sasas\sasas\1234_IASS.xlsx'
declare #filename varchar(max) = reverse(substring(reverse(#x), 1, charindex('\', reverse(#x))-1 ))
select substring(#filename, 1, charindex('.', #filename)-1)
Your post's title is misleading, TRIM is performed in sql-server to remove whitespace either by RTRIM or LTRIM or a combination of the two, what you are trying to do is get a substring out of your example string, I am providing a solution which uses a combination of REVERSE, SUBSTRING and CHARINDEX, this answer is good for if you ever need to do this for different file extensions:
DECLARE #test varchar(255) = 'sasa\sasas\sasas\1234_IASS.xlsx';
DECLARE #lastOccurance INT = CHARINDEX('\', REVERSE(#test)); --Last occurence of the slash character to denote the end of the directory name or what not
DECLARE #lastPeriod INT = CHARINDEX('.', REVERSE(#test)); --This is the last occurence of the period, denoting the file extension
SET #lastOccurance = LEN(#test) + 1 - #lastOccurance;
SET #lastPeriod = LEN(#test) + 1 - #lastPeriod;
SELECT SUBSTRING(#test, #lastOccurance + 1, #lastPeriod - (#lastOccurance + 1));
If you want to remove extensions from filename then you can try this:
UPDATE TableName
SET FileName = REVERSE(SUBSTRING(REVERSE(FileName),
CHARINDEX('.', REVERSE(FileName)) + 1, 999))

SQL: how to select a substring between special characters

My string looks something like this:
\\\abcde\fghijl\akjfljadf\\
\\xyz\123
I want to select everything between the 1st set and next set of slashes
Desired result:
abcde
xyz
EDITED: To clarify, the special character is always slashes - but the leading characters are not constant, sometimes there are 3 slashes and other times there are only 2 slashes, followed by texts, and then followed by 1 or more slashes, some more texts, 1 or more slash, so on and so forth. I'm not using any adapter at all, just looking for a way to select this substring in my SQL query
Please advise.
Thanks in advance.
You could do a cross join to find the second position of the backslash. And then, use substring function to get the string between 2nd and 3rd backslash of the text like this:
SELECT substring(string, 3, (P2.Pos - 2)) AS new_string
FROM strings
CROSS APPLY (
SELECT (charindex('\', replace(string, '\\', '\')))
) AS P1(Pos)
CROSS APPLY (
SELECT (charindex('\', replace(string, '\\', '\'), P1.Pos + 1))
) AS P2(Pos)
SQL Fiddle Demo
UPDATE
In case, when you have unknown number of backslashes in your string, you could just do something like this:
DECLARE #string VARCHAR(255) = '\\\abcde\fghijl\akjfljadf\\'
SELECT left(ltrim(replace(#string, '\', ' ')),
charindex(' ',ltrim(replace(#string, '\', ' ')))-1) AS new_string
SQL Fiddle Demo2
Use substring, like this (only works for the specified pattern of two slashes, characters, then another slash):
declare #str varchar(100) = '\\abcde\cc\xxx'
select substring(#str, 3, charindex('\', #str, 3) - 3)
Replace #str with the column you actually want to search, of course.
The charindex returns the location of the first slash, starting from the 3rd character (i.e. skipping the first two slashes). Then the substring returns the part of your string starting from the 3rd character (again, skipping the first two slashes), and continuing until just before the next slash, as determined by charindex.
Edit: To make this work with different numbers of slashes at the beginning, use patindex with regex to find the first alphanumeric character, instead of hardcoding that it should be the third character. Example:
declare #str varchar(100) = '\\\1Abcde\cc\xxx'
select substring(#str, patindex('%[a-zA-Z0-9]%', #str), charindex('\', #str, patindex('%[a-zA-Z0-9]%', #str)) - patindex('%[a-zA-Z0-9]%', #str))
APH's solution works better if your string always follows the pattern as described. However this will get the text despite the pattern.
declare #str varchar(100) = '\\abcde\fghijl\akjfljadf\\'
declare #srch char(1) = '\'
select
SUBSTRING(#str,
(CHARINDEX(#srch,#str,(CHARINDEX(#srch,#str,1)+1))+1),
CHARINDEX(#srch,#str,(CHARINDEX(#srch,#str,(CHARINDEX(#srch,#str,1)+1))+1))
- (CHARINDEX(#srch,#str,(CHARINDEX(#srch,#str,1)+1))+1)
)
Sorry for the formatting.
Edited to correct user paste error. :)

need to replace some underscores with hypens

I have a column with value
AAA_ZZZZ_7890_10_28_2014_123456.jpg
I need to replace the middle underscores so that it displays it as date i.e.
AAA_ZZZZ_7890_10-28-2014_123456.jpg
Can some one please suggest a simple update query for this.
The Number of Underscores would be same for all the values in the column but the length will vary for example some can have
AAA_q10WRQ_001_10_28_2014_12.jpg
The following should do it:
http://sqlfiddle.com/#!3/d41d8/30384/0
declare #filename varchar(64) = 'AAA_ZZZZ_7890_10_28_2014_123456.jpg'
declare #datepattern varchar(64) = '%[_][0-1][0-9][_][0-3][0-9][_][1-2][0-9][0-9][0-9][_]%'
select
filename,
substring(filename,1,datepos+2)+'-'+
substring(filename,datepos+4,2)+'-'+
substring(filename,datepos+7,1000)
from
(
select
#filename filename,
patindex(#datepattern,#filename)
as datepos
) t
;
Resulting in
AAA_ZZZZ_7890_10-28-2014_123456.jpg
Caveats to watch out for:
It is important to exactly define how you find the date. In my definition it is MM_DD_YYYY surrounded by further two underscores, and I check that the first digits of M,D,Y are 0-1,0-3,1-2 respectively (i.e. I do NOT check if month is e.g. 13.) -- of course we assume that there is only one such string in any file name.
datepos actually finds the position of the underscore before the date -- this is not an issue if taken into account in the indexing of substring.
in the 3rd substring the length cannot be NULL or infinity and I couldn't get LEN() to work in SQL Fiddle so I dirty hardcoded a large enough number (1000). Corrections to this are welcome.
Try this (assuming that the DATE portion always starts at the same character index)
declare #string varchar(64) = 'AAA_ZZZZ_7890_10_28_2014_123456.jpg'
select replace(#string, reverse(substring(reverse(#string), charindex('_', reverse(#string), 0) + 1, 10)), replace(reverse(substring(reverse(#string), charindex('_', reverse(#string), 0) + 1, 10)), '_', '-'))
If there are exactly 6 _ then for the first
select STUFF ( 'AAA_ZZZZ_7890_10_28_2014_123456.jpg' , CHARINDEX ( '_' ,'AAA_ZZZZ_7890_10_28_2014_123456.jpg', CHARINDEX ( '_' ,'AAA_ZZZZ_7890_10_28_2014_123456.jpg', CHARINDEX ( '_' ,'AAA_ZZZZ_7890_10_28_2014_123456.jpg', CHARINDEX ( '_' ,'AAA_ZZZZ_7890_10_28_2014_123456.jpg', 0 ) + 1 ) + 1 ) + 1 ) , 1 , '-' )

Update one column from substring of another column

I have an existing column that I would like to take a subset of and insert into a second (new) column in the same table.
e.g. MyTable.[FullName] (existing column) contains a string like "P-13-146 PS - Goodyear - Tire repair"
I created a new column, MyTable.[ShortName] that I want to insert a substring of the value from the first column into ("P-13-146 PS"). The problem is that the length of the substring is different for each full name. The only real consistency is that I want up to the second whitespace character.
I am trying to resolve the following:
UPDATE [MyTable] SET [ShortName] = ???
Try this:
declare #exp varchar(200)
set #exp='P-13-146 PS - Goodyear - Tire repair'
select RTRIM(SUBSTRING(#exp,1,CHARINDEX(' ',#exp,charindex(' ',#exp)+1)))
Just combine the string manipulation functions until you get what you want:
SELECT
CASE WHEN CHARINDEX(' ',FullName, CHARINDEX(' ', FullName)+1) = 0 THEN FullName
ELSE SUBSTRING(FullName, 1, CHARINDEX(' ',FullName, CHARINDEX(' ', FullName)+1)-1)
END ShortName
FROM MyTable
The first part of the CASE statement is for names that have fewer than two spaces.