I want to replace the first word before delimeter ' ,' with ' 0, the first word ')
select replace('tab,graph,map', split_part('tab,graph', ',', 1) like 'tab','0, tab')
ERROR: function replace(unknown, boolean, unknown) does not exist
LINE 1: select replace('tab,graph,map', split_part('tab,graph', ',',...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
The replace function replaces all occurrences of the string so you have to make sure the string to replace is unique or use something else. However, regexp_replace only replaces the first occurrence by default so you can use that; your question is a little unclear about what the expected output is but maybe this is is what you're looking for:
=> select regexp_replace('tab,graph,map', ',', '0,');
regexp_replace
----------------
tab0,graph,map
Or this one:
=> select regexp_replace('tab,graph,map', 'tab,', '0,');
regexp_replace
----------------
0,graph,map
Or maybe even this:
=> select regexp_replace('tab,graph,map', 'tab,', '0,,');
regexp_replace
----------------
0,,graph,map
you need to cast, since the function expects replace(text, text, text) and does not know how to handle your literal strings calling them unknown...
cast('tab,graph,map' AS text)
also the 2nd param is a LIKE comparison ? which returns boolean, but the function replace expects it to be the delimiter.
CAST(split_part('tab,graph', ',', 1) AS text)
finally the last param (same problem as the first)
cast('0, tab' AS text)
of course if you really just want to prepend '0, ' to your string, 'tab,graph,map' you could just do that...
SELECT '0, ' || 'tab,graph,map' ;
Related
I have a string that I need to seperate into values seperated by commas. I have achieved this part with the below REPLACE statement:
declare #mc varchar(200)
declare #mc1 varchar(200)
select #mc = 'FRED&#g4;g;MARY&#g4;g;BILL&#g4;g;TIMOTHY&#g4;g;JOHNATHAN'
select #mc1 = REPLACE(#mc, '&#g4;g;',', ')
The replace returns a string 'FRED, MARY, BILL, TIMOTHY, JOHNATHAN'
I then want to have another variable that will return the first 3 characters of each value before the commas, so the above string would be returned as:
'FRE, MAR, TIM, JOH'
Anyone know how I can achieve this?
Also happy for this to be done directly to the original #mc variable
ON SQL Server 2017+ you can make use of openJson to split the string into manageble segments and then string_agg to assemble the desired result:
declare #mc varchar(100)='FRED&#g4;g;MARY&#g4;g;BILL&#g4;g;TIMOTHY&#g4;g;JOHNATHAN'
select String_Agg(v, ', ')
from (select #mc)x(s)
cross apply (
select Left(j.[value],3) v, Convert(tinyint,j.[key]) Seq
from OpenJson(Concat('["',replace(s,';', '","'),'"]')) j
where Convert(tinyint,j.[key]) % 2 = 0
)j;
Demo Fiddle
I have a column with Names, and I am trying to split the column into First and Last Name using Text functions such as LEFT/SUBSTRING/CHARINDEX.
Data in the column:
Name
Yang, Jon
Huang, Eugene
Torres, Ruben
Zhu, Christy
Johnson, Elizabeth
Everything works fine as long as I use this code:
SELECT
[Name]
--,LEFT([Name], CHARINDEX(' ', [Name])) AS FirstName
,SUBSTRING([Name], 1, CHARINDEX(' ', [Name] )) AS FirstName
FROM
DataModeling.Customer
But the problem arises when I try to subtract 1 from CHARINDEX to exclude the Comma from the result and it throws this error:
I have done this operation many times in Excel so trying to replicate it with TSQL. Any suggestion on what I am doing wrong is helpful.
You get that error when CHARINDEX(' ', [Name] ) return 0. So minus 1 will make it negative and it is invalid value for substring()
You can use CASE expression to check the return value from CHARINDEX() and return the correct value to substring()
Or, you can "cheat" by using
CHARINDEX( ' ', [Name] + ' ' )
So CHARINDEX() will always return a value that is more than 0
I find '#' can replace some string in posgresql like:
SELECT
'Record #' || i
FROM
generate_series(1, 1000) i;
The symbol '#' can replace the by i, in this SQL commands.
I want to do similar like this for function like
SELECT lo_unlink('#') || i
From
SELECT picture i FROM image where belong_to = 254;
Of course '#' there is grammar error around '#', I just want to know any placehold grammar or symbol can work in function parameter like it replace string mark '#'
The symbol # is not replaced, you are concatenating a number to a string containing this symbol.
This concatenation can occur anywhere, including when building a function parameter:
SELECT lo_unlink('#' || i)
From
SELECT picture i FROM image where belong_to = 254;
which, if i is number 1, will create (and call) lo_unlink('#1')
so you may want to use i directly:
SELECT lo_unlink(i)
From
SELECT picture i FROM image where belong_to = 254;
which, if i is number 1, will create (and call) lo_unlink(1)
I need to replace all spaces with one % between two specific symbols (# and &); like followings:
'this # is test &that did not #turn& out well'
should be converted to
'this #%is%test%&that did not #turn& out well'
and
'#pattern matching& is my number one enemy'
to
'#pattern%matching& is my number one enemy'
I almost read all related questions in stackoverflow and other sites but couldn't get a helpful answer.
One (inefficient) way of doing this is by doing multiple REGEXP_REPLACE calls.
For example, lets look at the following plpgsql function.
CREATE OR REPLACE FUNCTION replaceSpacesBetweenTwoSymbols(startChar TEXT, endChar TEXT, textToParse TEXT)
RETURNS TEXT
AS $$
DECLARE resultText TEXT := textToParse;
DECLARE tempText TEXT := textToParse;
BEGIN
WHILE TRUE LOOP
tempText = REGEXP_REPLACE(resultText,
'(' || startChar || '[^' || endChar || ']*)' || '( )(.*' || endChar || ')',
'\1%\3');
IF tempText = resultText
THEN RETURN resultText;
END IF;
resultText := tempText;
END LOOP;
RETURN resultText;
END;
$$
LANGUAGE 'plpgsql';
We create a function that takes three arguments, the startChar, the endChar and the textToParse which holds the text that will be trimmed.
We start by creating a a regular expression based on the startChar and endChar. If the value of startChar is # and the value of endChar is & we will get the following regular expression:
(#[^&]*)( )(.*&)
This regular expression is consisted of three groups:
(#[^&]*) - This group matches the text that is between the # and an an empty space character - ' ';
( ) - This group matches a single space character.
(.*&) - This group matches the text that is between a space character and the & character.
In order to replace the space (group 2), we use the following REGEXP_REPLACE call:
REGEXP_REPLACE(resultText,' (#[^&]*)( )(.*&)', '\1%\3')
From that expression you can see that we are replacing the second group (which is a space) with the % character.
This way, we will only replace one space per one REGEXP_REPLACE execution.
Once we find that there are no more spaces that need to be replaced, we return the modified TEXT.
At this moment, the spaces are replaced with % characters. One last thing we need to do is to replace the multiple consecutive % characters with a single %.
That can be done with another REGEXP_REPLACE call at the end.
So for example:
SELECT REGEXP_REPLACE(replaceSpacesBetweenTwoSymbols('#','&','this # is test &that did not #turn& out well'),'%{2,}','%');
Will return
this #%is%test%&that did not #turn& out well
as a result, while this
SELECT REGEXP_REPLACE(replaceSpacesBetweenTwoSymbols('#','&','this is #a more complex& task #test a a & w'),'%{2,}','%');
will return
this is #a%more%complex& task #test%a%a%& w
as a result.
Using Postgres 9.4, is it possible to apply a function on the captured match?
Example: upper case only the string which are surrounded by double-quotes.
SELECT regexp_replace(
'123, "name", ignored~me, "Beer & Cheese", pi=3.14',
'"(.+?)"',
upper('"\1"'),
'g'
);
--Result : '123, "name", ignored~me, "Beer & Cheese", pi=3.14'
--Expected: '123, "NAME", ignored~me, "BEER & CHEESE", pi=3.14'
It looks like the function appearing in the 3rd parameter of regexp_replace is ignored. Is there anyway to use a function and passing the \n group capture as input argument?
I once had same question, and this
I did not get the answer, but general impression that you are not supposed to use SQL functions on arguments of regular expression functions...
In SQL, functions aren't first-class. They can't be passed. There is no part of the language that's interpreted either. It's declarative, compiled (with an optimizer), and evaluated strictly.
Keep in mind, under normal circumstance an update to any column requires rewriting the whole row (not just the column).
You can still accomplish this I would just be looking to a slightly smarter tool for it..
PL/Perl
PL/v8
Here is an example with plperl,
CREATE LANGUAGE plperl;
CREATE OR REPLACE FUNCTION perl_dynamic_eval_regexp_replace( IN str text, IN pattern text, IN replacementPerl text, OUT text )
STRICT
AS $BODY$
my ($input, $pattern, $replacement) = #_;
$input =~ s/$pattern/eval $replacement/ge;
return $input;
$BODY$
LANGUAGE plperl
VOLATILE;
SELECT perl_dynamic_eval_regexp_replace(
'123, "name", ignored~me, "Beer & Cheese", pi=3.14',
'"(.+?)"',
$$uc("$1")$$
);