Removing all but one of a certain character in a string - sql

I have an issue where I'm trying to remove all of the '.' from the string/filename below in SSMS apart from the last one which dictates file type.
EPC 14.10.14.pdf
Ideally I would like this string to appear as below:
EPC 141014.pdf
Any help would be appreciated

As a variable :
declare #doc varchar(30) = 'EPC 14.10.14.pdf'
declare #ext varchar(8) = right(#doc, charindex('.', reverse(#doc)));
set #doc = concat(replace(left(#doc,len(#doc)-len(#ext)),'.',''), #ext);
select #doc as doc;
doc
EPC 141014.pdf
As a table column :
create table test (
doc varchar(30) not null
);
insert into test (doc) values
('EPC 14.10.14.pdf'),
('FQD 15.11.15.jpeg');
select doc
, undotted_doc = concat(replace(left(doc, len(doc)-charindex('.', reverse(doc))),'.',''), right(doc, charindex('.', reverse(doc))))
from test;
doc
undotted_doc
EPC 14.10.14.pdf
EPC 141014.pdf
FQD 15.11.15.jpeg
FQD 151115.jpeg
Test on db<>fiddle here

Use replace,substring and len function
select replace(substring(#x,0,len(#x) - 3),'.','') + substring(#x,len(#x) - 3,len(#x))
EDIT:
If the name extension has a variable length, you can use the following query
select
CONCAT(
replace(substring(#x,0,len(#x) - CHARINDEX('.',TRIM(REVERSE(#x)))),'.','')
,
substring(#x,len(#x) - CHARINDEX('.',TRIM(REVERSE(#x))),len(#x))
)
Result

If you have extensions with different length (e.g. docx, xls), you need to find the index of the last occurrence of the . character using REVERSE() and CHARINDEX():
SELECT CONCAT(
REPLACE(SUBSTRING(SomeText, 1, LEN(SomeText) - CHARINDEX('.', REVERSE(SomeText))), '.', ''),
STUFF(SomeText, 1, LEN(SomeText) - CHARINDEX('.', REVERSE(SomeText)), '')
) AS FileName
FROM (VALUES
('EPC 14.10.14.pdf'),
('EPC 14.10.14.docx'),
('14.10.14.xlsx')
) t (SomeText)
Result:
FileName
----------------
EPC 141014.pdf
EPC 141014.docx
141014.xlsx

One more way.
SQL
SELECT fileName AS [Before]
, CONCAT(CONCAT(PARSENAME(fileName,4), PARSENAME(fileName,3), PARSENAME(fileName,2))
, '.', PARSENAME(fileName,1)) AS [After]
FROM (VALUES
('EPC 14.10.14.pdf'),
('EPC 14.10.14.docx'),
('14.10.14.xlsx'),
('csharp.10.14.cs')
) AS t(fileName);
Output
+-------------------+-----------------+
| Before | After |
+-------------------+-----------------+
| EPC 14.10.14.pdf | EPC 141014.pdf |
| EPC 14.10.14.docx | EPC 141014.docx |
| 14.10.14.xlsx | 141014.xlsx |
| csharp.10.14.cs | csharp1014.cs |
+-------------------+-----------------+

Related

Find and replace by pattern

I have a table that has a column like the one below
url
----------------
dir=mp3\cat152AB&fileName=file-01.mp3
dir=mp3\cat2500DfDD00&fileName=file-02.mp3
dir=mp3\cat4500f0655&fileName=file-03.mp3
...
How can I delete extra strings and arrange the fields as follows in SQL Server.
url
----------------
file-01
file-02
file-03
...
you can use charindex and substring :
SELECT substring ('dir=mp3\cat152AB&fileName=file-01.mp3', CHARINDEX('fileName=', 'dir=mp3\cat152AB&fileName=file-01.mp3') +9 ,
LEN('dir=mp3\cat152AB&fileName=file-01.mp3')-CHARINDEX('fileName=', 'dir=mp3\cat152AB&fileName=file-01.mp3')
) AS MatchPosition;
CHARINDEX and SUBSTRING can help you, please check the example:
select substring (field, charindex (';fileName=', field) + len (';fileName='), len (field) - len ('.mp3') + 1 - charindex (';fileName=', field) - len (';fileName='))
from (
select 'dir=mp3\cat152AB&fileName=file-01.mp3' field union all
select 'dir=mp3\cat2500DfDD00&fileName=file-02.mp3' union all
select 'dir=mp3\cat4500f0655&fileName=file-03.mp3'
) a
The information you want always seems to be the 11th to 5th characters before the end of the string. I would suggest a simple solution:
select left(right(url, 11), 7)
Here is a db<>fiddle.
Please try the following method.
It is using tokenization via XML/XQuery.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, url VARCHAR(255));
INSERT INTO #tbl (url) VALUES
('dir=mp3\cat152AB&fileName=file-01.mp3'),
('dir=mp3\cat2500DfDD00&fileName=file-02.mp3'),
('dir=mp3\cat4500f0655&fileName=file-03.mp3');
-- DDL and sample data population, end
DECLARE #separator CHAR(1) = '=';
SELECT id, url
, LEFT(x, CHARINDEX('.', x) - 1) AS Result
FROM #tbl
CROSS APPLY (SELECT CAST('<root><r><![CDATA[' +
REPLACE(url, #separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(c)
CROSS APPLY (VALUES (c.value('(/root/r[last()]/text())[1]', 'VARCHAR(100)'))) AS t2(x);
Output
+----+------------------------------------------------+---------+
| id | url | Result |
+----+------------------------------------------------+---------+
| 1 | dir=mp3\cat152AB&fileName=file-01.mp3 | file-01 |
| 2 | dir=mp3\cat2500DfDD00&fileName=file-02.mp3 | file-02 |
| 3 | dir=mp3\cat4500f0655&fileName=file-03.mp3 | file-03 |
+----+------------------------------------------------+---------+
I know we have an accepted answer but I wanted to chime in with another simple, high-performing solution that addresses file names and file extensions with various lengths. For fun I included a parameter that allows you to include the file extension if you choose.
--==== Easily Consumable Sample Data
DECLARE #link TABLE ([url] VARCHAR(100) UNIQUE);
INSERT #link VALUES ('dir=mp3\cat152AB&fileName=file-01.mp3'),
('dir=mp3\cat2500DfDD00&fileName=file-02.mp3'),
('dir=mp3\cat4500f0655&fileName=file-03.mp3'),
('dir=mp3\cat4500f0655&fileName=file-999.mp3'),
('dir=mp3\cat4500d9997&fileName=file-0021.prodigi');
--==== Allows you to determine if you want the file extension
DECLARE #exclude BIT=1;
SELECT l.[url], TheFile = SUBSTRING(l.[url], s.Pos, s.Ln-s.Pos- ((#exclude*(fl.Ln)-1)))
FROM #link AS l
CROSS APPLY (VALUES(CHARINDEX('.',REVERSE(l.[url])))) AS fl(Ln)
CROSS APPLY (VALUES(CHARINDEX('fileName=',l.[url])+9, LEN(l.[url]))) AS s(Pos,Ln);
#exclude=1 returns:
url TheFile
----------------------------------------------------- --------------
dir=mp3\cat152AB&fileName=file-01.mp3 file-01
dir=mp3\cat2500DfDD00&fileName=file-02.mp3 file-02
dir=mp3\cat4500d9997&fileName=file-0021.prodigi file-0021
dir=mp3\cat4500f0655&fileName=file-03.mp3 file-03
dir=mp3\cat4500f0655&fileName=file-999.mp3 file-999
#exclude=0 returns:
url TheFile
----------------------------------------------------- --------------
dir=mp3\cat152AB&fileName=file-01.mp3 file-01.mp3
dir=mp3\cat2500DfDD00&fileName=file-02.mp3 file-02.mp3
dir=mp3\cat4500d9997&fileName=file-0021.prodigi file-0021.prodigi
dir=mp3\cat4500f0655&fileName=file-03.mp3 file-03.mp3
dir=mp3\cat4500f0655&fileName=file-999.mp3 file-999.mp3

Split a column into multiple columns in a SQL query using pipe delimiter

I have below data in a column of a table, I want to split it into further columns.
| is used as the separator in this scenario . Column header should be before : & after column is its value.
Column
-----------------------------------------------------------------------------
ID: 30000300 | Name: India | Use: New Use
ID: 30000400 | Name: Aus | New ID: 15625616 | Address 1: NEW Rd
ID: 30000400 | Name: USA | City: VIA ARAMAC | New ID: 123
ID: 30000500 | Name: Russia | New ID: 15624951 | Address 2: 2131 BEAUDESERT
Output should be:
ID Name Use New ID City Address 1 Address 2 New City
----------------------------------------------------------------------
30000300 India New Use
30000400 Aus 15625616 NEW Rd
30000400 USA 15625616 VIA ARAMAC GALILEE
30000500 Russia 15624951 2131 BEAUDESERT
You have several rows that contain key value pairs inside an nvarchar column, but you want a table that has a header based on the keys and then rows containing just the values, sans keys. There is first the issue of an input like Key1: Value1 | Key2: Value2. Should this be returned as
Key1 Key2
Value1 NULL
NULL Value2
or is this not a possible scenario? Either way, there is the issue of generating a table with dynamic column names.
The problem with your question is that this is not a scenario that would normally be solved via SQL. You should get the data in your programming language of choice, then use regular expressions or split methods to get what you need.
If you insist doing it via SQL, then the solution is to turn the original lines input into another string, that you then sp_executesql (https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql), but I do NOT recommend it.
Here is a partial answer that you can use to return the n-th entry in a delimited string:
DECLARE #DelimitedString VARCHAR(8000);
DECLARE #Delimiter VARCHAR(100);
DECLARE #indexToReturn INT;
DECLARE #tblArray TABLE
(
ElementID INT IDENTITY(1, 1), -- Array index
Element VARCHAR(1000) -- Array element contents
);
-- Local Variable Declarations
-- ---------------------------
DECLARE #Index SMALLINT,
#Start SMALLINT,
#DelSize SMALLINT;
SET #DelSize = LEN(#Delimiter + 'x') - 1;
-- Loop through source string and add elements to destination table array
-- ----------------------------------------------------------------------
WHILE LEN(#DelimitedString) > 0
BEGIN
SET #Index = CHARINDEX(#Delimiter, #DelimitedString);
IF #Index = 0
BEGIN
INSERT INTO #tblArray
(
Element
)
VALUES
(LTRIM(RTRIM(#DelimitedString)));
BREAK;
END;
ELSE
BEGIN
INSERT INTO #tblArray
(
Element
)
VALUES
(LTRIM(RTRIM(SUBSTRING(#DelimitedString, 1, #Index - 1))));
SET #Start = #Index + #DelSize;
SET #DelimitedString = SUBSTRING(#DelimitedString, #Start, LEN(#DelimitedString) - #Start + 1);
END;
END;
DECLARE #val VARCHAR(1000);
SELECT #val = Element
FROM #tblArray AS ta
WHERE ta.ElementID = #indexToReturn;
SELECT #val;

Removing varchar(s) after a semicolon

So I have a lot of data like this:
pix11co;10.115.0.1
devapp087co;10.115.0.100
old_main-mgr;10.115.0.101
radius03co;10.115.0.110
And I want to delete the stuff after the ; so it just becomes
pix11co
devapp087co
old_main-mgr
radius03co
Since they're all different I can live with the semi-colon staying there.
I have the following query and it runs successfully but doesn't delete anything.
UPDATE dns$ SET [Name;] = REPLACE ([Name;], '%_;%__________%', '%_;');
What wildcards can I use to specify the characters after the ; ?
Can you use CHARINDEX? E.g.:
SELECT LEFT('pix11co;10.115.0.1', CHARINDEX(';', 'pix11co;10.115.0.1') - 1)
You can use SUBSTRING() and CHARINDEX() functions:
CREATE TABLE MyStrings (
STR VARCHAR(MAX)
);
INSERT INTO MyStrings VALUES
('pix11co;10.115.0.1'),
('devapp087co;10.115.0.100'),
('old_main-mgr;10.115.0.101'),
('radius03co;10.115.0.110');
SELECT STR, SUBSTRING(STR, 1, CHARINDEX(';', STR) -1 ) AS Result
FROM MyStrings;
Results:
+---------------------------+--------------+
| STR | Result |
+---------------------------+--------------+
| pix11co;10.115.0.1 | pix11co |
| devapp087co;10.115.0.100 | devapp087co |
| old_main-mgr;10.115.0.101 | old_main-mgr |
| radius03co;10.115.0.110 | radius03co |
+---------------------------+--------------+

Update Unique Column partial string SQL

I have a table that has a user names in the column. This is an example
| **Path**
| /test/path/Barry/home
| /test/path/Jenny/home
| /test/path/Jermehiam/home/Docs
| /test/path/Sarah/home/Docs
I am not sure how to update just the part of the path that ends at 'home'. I need the other parts of the path to remain as the string I am replacing is with an environment variable. So the end result would be:
| **Path**
| ${PATH}
| ${PATH}
| ${PATH}/Docs
| ${PATH}/Docs
Any help would be appreciated
You may do it in this way:
UPDATE PathTable
SET Path = '...'
WHERE Path LIKE '/test/path/%/home'
UPDATE PathTable
SET Path = '.../Docs'
WHERE Path LIKE '/test/path/%/home/Docs'
if you are using SQL-Server you can use CHARINDEX(), SUBSTRING() and LEN()
SELECT CASE WHEN CHARINDEX('home',url) = 0
THEN url
ELSE '${PATH}' + SUBSTRING(url, (CHARINDEX('home',url) + 4), LEN(url) - (CHARINDEX('home',url) + 3))
END url
FROM t_link
in Oracle, you can use INSTR(), SUBSTR() and LENGTH()
SELECT CASE WHEN CHARINDEX('home',url) = 0
THEN url
ELSE '${PATH}' + SUBSTRING(url, (CHARINDEX('home',url) + 4), LEN(url) - (CHARINDEX('home',url) + 3))
END url
FROM t_link
Result
url
**Path**
${PATH}
${PATH}
${PATH}/Docs
${PATH}/Docs

How to split a string in sql server using stored procedure and insert the data to table

<pre>update d
set d.Price = null
from dbo.SalDocumentDetail d
left join dbo.StkWarehouse w on w.WarehouseID = d.WarehouseID
where DocumentID=" + 1 + "
and DocumentTypeID=" + 2 + "
and FiscalYear= " + 2016 + "
and isnull(isPrescription,0) <>1
and w.POSType is null
and ProductName BETWEEN ''C' 'AND' 'M''
and Country LIKE ''%land%'''</pre>
Actually this string is only a sample one my original string is very large . i am not getting a point that if i break this string than how many variables i have to make to capture the data also after splitting the string i want that to be inserted into data table containing columns as Felid and Value?
I want my result like :
<pre>
Felid Value
DocumentID= 1
DocumentTypeID= 2
FiscalYear= 2016
isnull(isPrescription,0) <>= 1
w.POSType is= null
ProductName= C
ProductName= M
Country= land
</pre>
<pre>I Use this function but this function split 'and' not split like what i want in my result i want split 'and,or,like,is,between ' if function find any this split it to two columns (Felid and Value)</pre>
<pre>ALTER FUNCTION [dbo].[fnSplitString]
(#List NVARCHAR(MAX),#Delimiter NVARCHAR(255))
RETURNS #Items TABLE(Felid NVARCHAR(Max),Valu nvarchar(MAx))
WITH SCHEMABINDING
AS BEGIN
DECLARE #ll INT=LEN(#List)+1,#ld INT=LEN(#Delimiter);
WITH a AS
(SELECT
[end]=COALESCE(NULLIF(CHARINDEX(#Delimiter,#List,1),0),#ll),
[VlaueFelid]=SUBSTRING(#List,(select
CHARINDEX('where',#List)+5),COALESCE(NULLIF(CHARINDEX('=', #List,0),0),#ll) ) ,
[Value]=SUBSTRING(#List,(select CHARINDEX('="',#List)+2),(select CHARINDEX('and',#List))-(select C`enter code here`HARINDEX('="',#List)+3))
UNION ALL
SELECT
[end]=COALESCE(NULLIF(CHARINDEX(#Delimiter,#List,[end]+#ld), 0),#ll),
[VlaueFelid]=SUBSTRING(#List,[end]+#ld, COALESCE(NULLIF(CHARINDEX('=',#List, [end]+#ld),0),#ll)-[end]-#ld),
[Value]=SUBSTRING(#List,[end]+#ld+16, COALESCE(NULLIF(CHARINDEX('=',#List,[end]+#ld),0),#ll)-[end]-#ld-5)
FROM a WHERE [end]< #ll) INSERT #Items SELECT[VlaueFelid],[Value] FROM a WHERE LEN([VlaueFelid])>0 RETURN;
END</pre>