postgresql replace symbol for store function variable? - postgresql

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)

Related

How to find/replace weird whitespace in string

I find in my sql database string whit weird whitespace which cannot be replace like REPLACE(string, ' ', '') RTRIM and cant it even find with string = '% %'. This space is even transfered to new table when using SELECT string INTO
If i select this string in managment studio and copy that is seems is normal space and when everything is works but cant do nothing directly from database. What else can i do? Its some kind of error or can i try some special character for this?
First, you must identify the character.
You can do that by using a tally table (or a cte) and the Unicode function:
The following script will return a table with two columns: one contains a char and the other it's unicode value:
DECLARE #Str nvarchar(100) = N'This is a string containing 1 number and some words.';
with Tally(n) as
(
SELECT TOP(LEN(#str)) ROW_NUMBER() OVER(ORDER BY ##SPID)
FROM sys.objects a
--CROSS JOIN sys.objects b -- (unremark if there are not enough rows in the tally cte)
)
SELECT SUBSTRING(#str, n, 1) As TheChar,
UNICODE(SUBSTRING(#str, n, 1)) As TheCode
FROM Tally
WHERE n <= LEN(#str)
You can also add a condition to the where clause to only include "special" chars:
AND SUBSTRING(#str, n, 1) NOT LIKE '[a-zA-Z0-9]'
Then you can replace it using it's unicode value using nchar (I've used 32 in this example since it's unicode "regular" space:
SELECT REPLACE(#str, NCHAR(32), '|')
Result:
This|is|a|string|containing|1|number|and|some|words.

REGEXP_REPLACE replace spaces between two symbols

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.

How to search in SQL for cloumn with asterisk?

I try to create advanced search to my database.
I want to do something like that: if the user type for search = overf**w
and I have in my database an cloumn that his value = overflow - show him.
this my code:
$name = str_replace('*', '_', $name);
SELECT name FROM table WHERE name LIKE CONCAT('%', ?, '%')
its not working, I dont know what the problem.
You can't use LIKE in this situation, you need to use REGEXP() to do a wildcard search. Replace * or ** with .*. To only return names that starts with the given value use ^ at the beginning of the regular expression
SELECT name
FROM actors
WHERE name REGEXP('^overf.*w')
I don't know php but your $name parameter should be set like this (in pseudo code)
$name = '^' + replace($name, '**', '.*')

Replacing Turkish characters with English characters

I have a table which has 120 columns and some of them is including Turkish characters (for example "ç","ğ","ı","ö"). So i want to replace this Turkish characters with English characters (for example "c","g","i","o"). When i use "TRANWRD Function" it could be really hard because i should write the function 120 times and sometimes hte column names could be change so always i have to check the code one by one because of that.
Is there a simple macro which replaces this characters in all columns .
EDIT
In retrospect, this is an overly complicated solution... The translate() function should be used, as pointed by another user. It could be integrated in a SAS function defined with PROC FCMP when used repeatedly.
A combination of regular expressions and a DO loop can achieve that.
Step 1: Build a conversion table in the following manner
Accentuated letters that resolve to the same replacement character are put on a single line, separated by the | symbol.
data conversions;
infile datalines dsd;
input orig $ repl $;
datalines;
ç,c
ğ,g
ı,l
ö|ò|ó,o
ë|è,e
;
Step 2: Store original and replacement strings in macro variables
proc sql noprint;
select orig, repl, count(*)
into :orig separated by ";",
:repl separated by ";",
:nrepl
from conversions;
quit;
Step 3: Do the actual conversion
Just to show how it works, let's deal with just one column.
data convert(drop=i re);
myString = "ç ğı òö ë, è";
do i = 1 to &nrepl;
re = prxparse("s/" || scan("&orig",i,";") || "/" || scan("&repl",i,";") || "/");
myString = prxchange(re,-1,myString);
end;
run;
Resulting myString: "c gl oo e, e"
To process all character columns, we use an array
Say your table is named mySource and you want all character variables to be processed; we'll create a vector called cols for that.
data convert(drop=i re);
set mySource;
array cols(*) _character_;
do c = 1 to dim(cols);
do i = 1 to &nrepl;
re = prxparse("s/" || scan("&orig",i,";") || "/" || scan("&repl",i,";") || "/");
cols(c) = prxchange(re,-1,cols(c));
end;
end;
run;
When changing single characters TRANSLATE is the proper function, it will be one line of code.
translated = translate(string,"cgio","çğıö");
First get all your columns from dictionary, and then replace the values of all of them in a macro do loop.
You can try a program like this (Replace MYTABLE with your table name):
proc sql;
select name , count(*) into :columns separated by ' ', :count
from dictionary.columns
where memname = 'MYTABLE';
quit;
%macro m;
data mytable;
set mytable;
%do i=1 %to &count;
%scan(&columns ,&i) = tranwrd(%scan(&columns ,&i),"ç","c");
%scan(&columns ,&i) = tranwrd(%scan(&columns ,&i),"ğ","g");
...
%end;
%mend;
%m;

replace string with split_part function

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' ;