TSQL - Replace string before symbol - sql-server

I have a table storing pathes to files on sql server. I need to replace the path before the last backslash:
C:\Users\APP\AppData\Local\Temp\test\abc deg.pdf
to for example:
\app\pp\abc deg.pdf
EDIT: The table containts many pathes - I need to run through the whole table and change all pathes.

You can use:
CHARINDEX('\', REVERSE(#str))
to get the index of the first backslash starting from the end.
Using RIGHT with this index you can extract the string after the last backslash and concatenate it to the new path:
DECLARE #str VARCHAR(50) = 'C:\Users\APP\AppData\Local\Temp\test\abc deg.pdf'
SELECT '\app\pp' + RIGHT(#str, CHARINDEX('\', REVERSE(#str)))

Reverse the input string (using REVERSE) and find the index of the first backslash (using CHARINDEX).
Take the left part up to that index (using LEFT) and concatenate with the reverse of your replacement string (using + operator).
Then reverse that to get your final result.

Try this:
declare #a varchar(max)='C:\Users\APP\AppData\Local\Temp\test\abc deg.pdf'
select REPLACE(#a,SUBSTRING(#a,1,(LEN(#a)-charindex('\',reverse(#a),1))),'\app\pp')
Update: For updatingall the table column values.
select REPLACE([column-name],SUBSTRING([column-name],1,(LEN([column-name])-charindex('\',reverse([column-name]),1))),'\app\pp')
FROM [Your-table]

This is how it can be done.
UPDATE TABLE
SET PATH = REPLACE(PATH, 'C:\Users\APP\AppData\Local\Temp\test', '\app\pp')
WHERE ...
This is going to replace 'C:\Users\APP\AppData\Local\Temp\test' with '\app\pp'. Or you can modify the path as required.
Please test before executing this UPDATE statement. I havent specified filters here

Related

smart replace (re-phrase) text in SQL

I have a string in SQL with the following structure:
#number <logical> #number <logical> ....
ex:
#SQL='((#1 or #2) and (#10 or #21))'
I would like to update the string to be:
#SQL='((con_1=1 or con_2=1) and (con_10=1 or con_21=1))'
meaning remove the '#' and replace it with 'con_', leave the number (1 digit or more) as is and add '=1' after the digit.
Any idea how to do it?
Please avoid composing function or procedure for that.
you may use patindex, stuff or any other built in function for that.
First split the string into records on the '#' char that starts the value needing processed.
STUFF can be used to insert the '=1' after the last digit of the value in each record. I think searching for the last number is harder than searching for the first. The reverse allows searching for the first instead of the last. Because the string is reversed, insert the reverse '1=' at the start of the reverse number. If there is no number, return the revered value as is.
Concatenate it all back with 'con_' instead of '#'.
declare #SQL varchar(200) = ' ((#1 or #2) and (#10 or #21)) #33 #55 ';
with split as (
select value, REVERSE(value) as [rev], PATINDEX('%[0-9]%', REVERSE(value)) as [pat]
FROM STRING_SPLIT(#SQL, '#')
), fixed as (
select value, rev, pat, CASE WHEN pat= 0 THEN REVERSE(rev) ELSE REVERSE(STUFF(rev, pat, 0, '1=')) END as [fix]
FROM split
) select STRING_AGG(fix, 'con_') from fixed
Result: ((con_1=1 or con_2=1) and (con_10=1 or con_21=1)) con_33=1 con_55=1
It would be nice if Regex support was included in SQL server. I imagine to do so would require a careful implementation to avoid using all the server resources. A regex search on a millions of records or varchar(max) columns....
Found this solution which uses SQL# (SQLsharp).
SQL# is a .NET / CLR library that resides in a SQL Server 2005 (or newer) database and provides a suite of User-Defined Functions, Stored Procedures, User-Defined Aggregates, and User-Defined Types.
My solution:
declare #SQL varchar(200) = '#1 OR(#2 AND #3 AND (#4 or #5 or #6) AND (#7 or #8))'
SELECT SQL#.RegEx_Replace4k(#SQL, N'(#)+(\d*)', N'CON_$2=1', -1, 1, N'')

TSQL - Split delimited String into columns

The Problem
I have a number of filename strings that I want to parse into columns using a tilda as delimiter. The strings take on the static format:
Filepath example C:\My Documents\PDF
Surname example Walker
First Name example Thomas
Birth Date example 19991226
Document Created Datetime example 20180416150322
Document Extension example .pdf
So a full concatenated example would be something like:
C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf
I want to ignore the file path and extension given in the string and only parse the following values into columns:
Surname, First Name, Birth Date, Document Created Datetime
So something like:
SELECT Surname = --delimitedString[0]
FirstName = --delimitedString[1]
--etc.
What I have tried
I know that I have several tasks I would need to perform in order to split the string, first I would need to trim off the extension and file path so that I can return a string delimited by tildas (~).
This is problem one for me, however problem 2 is splitting the new delimted string itself i.e.
Walker~Thomas~19991226~20180416150322
Ive had a good read through this very comprehensive question and It seems (as im using SQL Server 2008R2) the only options are to use either a function with loops or recursive CTE's or attempt a very messy attempt using SUBSTRING() with charIndex().
Im aware that If I had access to SQL Server 2016 I could use string_split but unfortunately I cant upgrade.
I do have access to SSIS but im very new to it so decided to attempt the bulk of the work within a SQL statement
Here is a way without a splitter that shouldn't be too complicated...
declare #var table (filepath varchar(256))
insert into #var values
('C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf')
;with string as(
select
x = right(filepath,charindex('\',reverse(filepath))-1)
from #var
)
select
SurName= substring(x,1,charindex('~',x) - 1)
,FirstName = substring(x,charindex('~',x) + 1,charindex('~',x) - 1)
from string
I know you mentioned wanting to avoid the charindex() option if at all possible, but I worked it out in a hopefully semi-readable way. I find it somewhat easy to read complex functions like this when I space each parameter on a different line and use indent levels. It's not the most proper looking, but it helps with legibility:
with string as (select 'C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf' as filepath)
select
substring(
filepath,
len(filepath)-charindex('\',reverse(filepath))+2, --start location, after last '\'
len(filepath)- --length of path
(len(filepath)-charindex('\',reverse(filepath))+2)- --less characters up to last '\'
(len(filepath)-charindex('.',filepath)) --less file extention
)
from string
Fritz already have a great start, my answer just add on top it
with string as (select 'C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf' as filepath)
, newstr as (
select
REPLACE(substring(
filepath,
len(filepath)-charindex('\',reverse(filepath))+2, --start location, after last '\'
len(filepath)- --length of path
(len(filepath)-charindex('\',reverse(filepath))+2)- --less characters up to last '\'
(len(filepath)-charindex('.',filepath)) --less file extention
) , '~', '.') as new_part
from string
)
SELECT
PARSENAME(new_part,4) as Surname,
PARSENAME(new_part,3) as [First Name],
PARSENAME(new_part,2) as [Birth Date],
PARSENAME(new_part,1) as [Document Created Datetime]
FROM newstr

Use result of sql query to replace text on multiple xml files

i have a table on sql like this:
CD_MATERIAL | CD_IDENTIFICACAO
1 | 002323
2 | 00322234
... | ...
AND SO ON (5000+ lines)
I need to use that info to search and replace multiple external xml files on a folder (all the tags on those XML had numbers like the CD_IDENTIFICACAO from sql query, i need to replace with corresponding cd_material from sql query "ex.: 002323 becomes 1)
I used this query to extract all the cd_identificacao to use on Notepad++:
declare #result varchar(max)
select #result = COALESCE(#result + '', '') + CONCAT('(',CD_IDENTIFICACAO,')|') from TBL_MATERIAIS WHERE CD_IDENTIFICACAO <> '' ORDER BY CD_MATERIAL
select #result
That would bring me ex.:
(1TEC45D025)|(1TEC800039)|(999999999)|(542251)|(2TEC58426)|(234852)
and changed the parameters to get the replace ex.:
(? 2000)|(? 2001)|(? 2002)|(? 2003)|(? 2004)|(? 2005)
but i don't know how to add a number (increment) on front of "?" so notepad++ would understand it (search and replace would have 5000+ results, so it's not pratical to manually add the increment).
I was able to get a workaround for this. I've used this query to get all the the terms for find and replace i needed (1 per line)
select concat('<cProd>',cd_identificacao,'</cProd>'), concat('<cProd>',cd_material,'</cProd>') from tbl_materiais where cd_identificacao <> '' order by cd_material
That would result in:
<cProd>1TEC460054</cProd> <cProd>1</cProd>
<cProd>1TEC240035</cProd> <cProd>2</cProd>
(i added the tag too to make sure no other information could be replaced as there were many number combinations that could lead to incorrect replacement)
then pasted it on a txt and i used the notepad++ to replace the space between column 1 and 2 for /r/n wich would result in:
<cProd>1TEC460054</cProd>
<cProd>1</cProd>
<cProd>1TEC240035</cProd>
<cProd>2</cProd>
then i used "Ecobyte Replace Text" Tool, pasted my result file as new selection in bottom frame, loaded all my files on a new replace group on top frame (on properties of the group, u can change directory and options), then executed the replacement, it worked perfectly.
Thx.

SQL Server String extract based on pattern

I have string data in the following format:
MODELNUMBER=Z12345&HELLOWORLD=WY554&GADTYPE=PLA&ID=Z-12345
/DTYPE=PLA&ID=S-10758&UN_JTT_REDIRECT=UN_JTT_IOSV
and need to extract IDs based on two conditions
Starting after a pattern &ID=
Ending till the last character or
if it hits a & stop right there.
So in the above example I'm using the following code:
SUBSTRING(MyCol,(PATINDEX('%&id=%',[MyCol])+4),(LEN(MyCol) - PATINDEX('%&id%',[MyCol])))
Essentially looking the pattern &id=% and extract string after that till end of the line. Would anyone advise on how to handle the later part of the logic ..
My current results are
Z-12345
Z-12345&UN_JTT_REDIRECT=UN_JTT_IOSV
What I need is
Z-12345
Z-12345
Try this
SUBSTRING(MyCol, (PATINDEX('%[A-Z]-[0-9][0-9][0-9][0-9][0-9]%',[MyCol])),7)
if you run into performance issues add the where clause below
-- from Mytable
WHERE [MyCol] like '%[A-Z]-[0-9][0-9][0-9][0-9][0-9]%'
maybe not the most elegant solution but it works for me.
Correct syntax of PATINDEX
Here's one example how to do it:
select
substring(d.data, s.s, isnull(nullif(e.e,0),2000)-s.s) as ID,
d.data
from data d
cross apply (
select charindex('&ID=', d.data)+4 as s
) s
cross apply (
select charindex('&', d.data, s) as e
) e
where s.s > 4
This assumes there data column is varchar(2000) and the where clause leaves out any rows that don't have &ID=
The first cross apply searches for the start position, the second one for the end. The isnull+nulliff in the actual select handles the case where & is not found and replaces it with 2000 to make sure the whole string is returned.

Building dynamic query for Sql Server 2008 when table name contains " ' "

I need to fetch Table's TOP_PK, IDENT_CURRENT, IDENT_INCR, IDENT_SEED for which i am building dynamic query as below:
sGetSchemaCommand = String.Format("SELECT (SELECT TOP 1 [{0}] FROM [{1}]) AS TOP_PK, IDENT_CURRENT('[{1}]') AS CURRENT_IDENT, IDENT_INCR('[{1}]') AS IDENT_ICREMENT, IDENT_SEED('[{1}]') AS IDENT_SEED", pPrimaryKey, pTableName)
Here pPrimaryKey is name of Table's primary key column and pTableName is name of Table.
Now, i am facing problem when Table_Name contains " ' " character.(For Ex. KIN'1)
When i am using above logic and building query it would be as below:
SELECT (SELECT TOP 1 [ID] FROM [KIL'1]) AS TOP_PK, IDENT_CURRENT('[KIL'1]') AS CURRENT_IDENT, IDENT_INCR('[KIL'1]') AS IDENT_ICREMENT, IDENT_SEED('[KIL'1]') AS IDENT_SEED
Here, by executing above query i am getting error as below:
Incorrect syntax near '1'.
Unclosed quotation mark after the character string ') AS IDENT_SEED'.
So, can anyone please show me the best way to solve this problem?
Escape a single quote by doubling it: KIL'1 becomes KIL''1.
If a string already has adjacent single quotes, two becomes four, or four becomes eight... it can get a little hard to read, but it works :)
Using string methods from .NET, your statement could be:
sGetSchemaCommand = String.Format("SELECT (SELECT TOP 1 [{0}] FROM [{1}]) AS TOP_PK, IDENT_CURRENT('[{2}]') AS CURRENT_IDENT, IDENT_INCR('[{2}]') AS IDENT_ICREMENT, IDENT_SEED('[{2}]') AS IDENT_SEED", pPrimaryKey, pTableName, pTableName.Replace("'","''"))
EDIT:
Note that the string replace is now only on a new, third substitution string. (I've taken out the string replace for pPrimaryKey, and for the first occurrence of pTableName.) So now, single quotes are only doubled, when they will be within other single quotes.
You need to replace every single quote into two single quotes http://beyondrelational.com/modules/2/blogs/70/posts/10827/understanding-single-quotes.aspx

Resources