Reputation: 2998
for example, i have the string 'This Is An Example Of The String'
and i want to return this result 'This is an Example of the String'
==> I want all the 'Is', 'An' 'Of' and 'The' in lower cases, the rest should stay in Initcap.
How can be this done in a simple and unique query? here is my query to lower case only the 'Of' :
SELECT 'This Is An Example Of The String',
CASE
WHEN 'This Is An Example Of The String' like '% Of %'
THEN replace('This Is An Example Of The String', ' Of ', ' of ')
END
FROM dual ;
Thanks!
Upvotes: 1
Views: 366
Reputation: 50017
Although it's not a pure SQL solution, another option would be to define a function which transformed the string as desired, perhaps calling it REPLACE_MULTI. The invocation would be something like
SELECT REPLACE_MULTI('This Is An Example Of The String',
'Is|An|Of|The',
'is|an|of|the')
FROM DUAL;
and the implementation would be something along the lines of
CREATE OR REPLACE FUNCTION REPLACE_MULTI(strOriginal IN VARCHAR2,
strTokens_to_replace IN VARCHAR2,
strReplacement_tokens IN VARCHAR2)
RETURN VARCHAR2
IS
strResult VARCHAR2(2000);
arrTokens_to_replace DBMS_SQL.VARCHAR2A;
arrReplacement_tokens DBMS_SQL.VARCHAR2A;
i NUMBER;
FUNCTION extract_tokens(p_string IN VARCHAR2,
p_separators IN VARCHAR2) RETURN DBMS_SQL.VARCHAR2A
IS
arrTokens DBMS_SQL.VARCHAR2A;
BEGIN
WITH sel_string AS
(SELECT p_string AS fullstring FROM DUAL)
SELECT SUBSTR(fullstring, beg + 1, end_p - beg - 1) AS token
BULK COLLECT INTO arrTokens
FROM (SELECT beg, LEAD(beg) OVER (ORDER BY beg) AS end_p, fullstring
FROM (SELECT beg, fullstring
FROM (SELECT LEVEL beg, fullstring
FROM sel_string
CONNECT BY LEVEL <= LENGTH(fullstring))
WHERE INSTR(p_separators, SUBSTR(fullstring, beg, 1)) > 0
UNION ALL
SELECT 0, fullstring FROM sel_string
UNION ALL
SELECT LENGTH(fullstring) + 1, fullstring FROM sel_string))
WHERE end_p IS NOT NULL AND
end_p > beg + 1;
RETURN arrTokens;
END extract_tokens;
BEGIN
arrTokens_to_replace := extract_tokens(strTokens_to_replace, '|');
arrReplacement_tokens := extract_tokens(strReplacement_tokens, '|');
strResult := strOriginal;
FOR i IN 1..arrTokens_to_replace.COUNT LOOP
strResult := REGEXP_REPLACE(strResult,
'^' || arrTokens_to_replace(i) || ' ',
arrReplacement_tokens(i));
strResult := REPLACE(strResult,
' ' || arrTokens_to_replace(i) || ' ',
' ' || arrTokens_to_replace(i) || ' ');
strResult := REGEXP_REPLACE(strResult,
' ' || arrTokens_to_replace(i) || '$',
' ' || arrReplacement_tokens(i));
END LOOP;
RETURN strResult;
END REPLACE_MULTI;
I'm sure that there are token strings which can be created which will break the regular expression-based parsing (try putting a '^' or '$' in there and watch the sparks fly :-) but this is good enough for an initial hack.
(Incidentally, the 'extract_tokens' routine isn't mine - I found it on the web somewhere a while back and am eternally grateful to whoever it was that created this).
Share and enjoy.
Upvotes: 2
Reputation: 4268
Try this:
SELECT REPLACE(REPLACE(REPLACE(REPLACE('This Is An Example Of The String', 'Of', 'of'), 'The', 'the'), 'An', 'an'), 'Is', 'is') FROM dual;
I feel a little dirty after writing that though.
Edit: Removed the extra 'an' replace, then added indentation, then removed indentation again. It looks ugly no matter how you wrap it.
Upvotes: 4
Reputation: 14764
I can tell you the algorithm but I am not sure how to do that in SQL. for example:
words[] = string.split(" ")
foreach word in words
---if(word.length<=3) //do that only for short words
-------if(word[i]>=65 && word[i]<=90) //check the ascii code for upper case
------------word[i] += 21; // transfer it into lower case
---new sentence += " " + words[i] //add to the resultant string
Upvotes: 0
Reputation: 4533
Basically it's going to take a lot of logic of the nature you've described. There's no quick and easy way. You'd find it quicker and easier to do this type of manipulation in your business logic code rather than at the database.
If you are going to do it in the database consider wrapping up the logic in a function, like this one.
Upvotes: 2