Split a name field in Oracle into First and Last Name - oracle

I've got a table with names in it, which looks like this:
Emp_ID Emp_Name
0001 Jack Skelly
0002 Susan Ryan
I need to produce something that looks like this:
Emp_ID Emp_F_Name Emp_L_Name
0001 Jack Skelly
0002 Susan Ryan
I've come up with this to split the name:
SubStr(d.Name, 0, InStr(d.Name, ' ')-1) as FName,
SubStr(d.Name, InStr(d.Name, ' ')+1) as LName
I've seen people suggest INSTR, I've seen people suggest regexp_instr and I've seen them suggest regexp_substr. I'm still new to Oracle and I don't really understand either, or which (if either) of them is more efficient for the split I need to do. Can someone tell me the best way to go about splitting this field? Is the method I've used the best/most efficient for what I want to do?

substr and instr are almost always faster/more efficient than regular expression functions.
INSTR is used to find the position of the space in the input string. SUBSTR is used to extract a substring from the input string. Search (google) the Oracle documentation for these functions - you will find detailed explanations and examples.
The bigger issue you will have with your problem is the business requirement - what do you do with names like "John Clayton Stuart", "Ali Abu Ahmad", or single-word like "Belphegor"?
The query below shows how easily you can solve the problem if all the names have the format "Firstname Lastname".
with
input_table ( emp_id, emp_name ) as (
select '0001', 'Jack Skelly' from dual union all
select '0002', 'Susan Ryan' from dual
)
-- End of simulated input data (not part of the solution).
-- SQL query begins BELOW THIS LINE.
select emp_id, emp_name,
substr(emp_name, 1, instr(emp_name, ' ') - 1) as first_name,
substr(emp_name, instr(emp_name, ' ') + 1) as last_name
from input_table
;
EMP_ID EMP_NAME FIRST_NAME LAST_NAME
---- ----------- ----------- -----------
0001 Jack Skelly Jack Skelly
0002 Susan Ryan Susan Ryan

Related

How to add characters in sql between two strings?

I'd like to know is it possible to add characters between two or more string using LPAD in SQL example sentence 'The Cat Is Sleeping'
LPAD('string', number, '+')
expected results:
++++++The+++++Cat+++++++Is++++++Sleeping
pas :-amount of + above is just an example maybe the result will be different. I hope you can understand my question.
if you are willing give me the exact query
thanks
Your problem is a good candidate for doing a regex replacement with REGEXP_REPLACE:
SELECT REGEXP_REPLACE(input, '^| ', '+++++++') AS output
FROM yourTable;
The output is:
+++++++The+++++++Cat+++++++Is+++++++Sleeping
Demo
Data:
WITH yourTable AS (
SELECT 'The Cat Is Sleeping' AS input FROM dual
)

oracle regexp_replace to remove commas between Quote

Please can anybody help me out please. Have been trying for days to get a regexp_replace to remove commas between quotes irrespective of the commas position.
Example
cold, gold, "Block 12C, Jones Avenue, Broad Street, London", car
Expected Answer
cold, gold, "Block 12C Jones Avenue Broad Street London", car
thanks in advance
You could extract the contents within double quotes(REGEXP_SUBSTR), replace the commas, and stuff it back to the old string using replace.
select REPLACE (whole_str,quoted_str,REPLACE (quoted_str,',')) FROM
(
select
whole_str,
REGEXP_SUBSTR( whole_str, '^[^"]*("[^"]+")',1,1,NULL,1) quoted_str
FROM yourtable
);
DEMO
Note that this could also be done using INSTR,SUBSTR which could be more efficient, but hard to read.
You can use regexp_replace to get the desired output :
with t( id , val ) as(
select 1,'cold, gold, "Block 12C, Jones Avenue, Broad Street, London", car' from dual union
select 2,'"Block 12C, Jones Avenue, Broad Street, London", car, cold, gold' from dual )
select id, val value
from t
model dimension by( id ) measures( val )
rules iterate(100)( val[any] = regexp_replace(val[cv()],',(([^"]*"){2})*([^"]*"[^"]*)$',' \1\3') );
d E m O
I doubt that there is a single regular expression function that will achieve the desired result. The "obvious" line of attack is to chop the input string into pieces and delete commas from each double-quoted substring as needed. (Unless each string has at most ONE double-quoted substring, in which case the problem has easier answers - but judging from the sample input string, it is possible that the same needs to be done for input strings with an arbitrary number of double-quoted substrings.)
Here is a solution using a recursive WITH clause - so it requires Oracle 11.2 or higher. (For earlier versions, a solution with a CONNECT BY hierarchical query can be used instead.) I wrote it with regular expressions, as requested; if speed becomes an issue, it can be re-written with standard INSTR, SUBSTR and REPLACE functions.
In the first factored subquery (subquery in the WITH clause) I created a few more inputs, to test whether the solution returns the correct result in different situations.
with
inputs ( str ) as (
select 'cold, gold, "Block 12C, Jones Ave., London", car' from dual union all
select '"One, two, three","Four, five six,",' from dual union all
select 'No, double-quotes, in this, string' from dual union all
select 'No commas in "double quotes" here' from dual
),
r ( str, init, quoted, fin ) as (
select str, null, null, str
from inputs
union all
select str,
init || replace(quoted, ',') || regexp_substr(fin, '[^"]*'),
regexp_substr(fin, '"[^"]*"'),
regexp_substr(fin, '([^"]*"){2}(.*)', 1, 1, null, 2)
from r
where quoted is not null or fin is not null
)
select str, init as new_str
from r
where quoted is null and fin is null
;
STR NEW_STR
--------------------------------------------- -------------------------------------------
No, double-quotes, in this, string No, double-quotes, in this, string
cold, gold, "Block 12C, Jay Ave, London", car cold, gold, "Block 12C Jay Ave London", car
No commas in "double quotes" here No commas in "double quotes" here
"One, two, three","Four, five six,", "One two three","Four five six",

Oracle change any string to a number

I'm having this problem we have this database witch IDS are stored in varchar2 type this ids contains Letters.
Is there any solution to convert a string to a number no matter what the value if this string.
for example there is : SELCT ASCII('t') FROM DUAL; result : 116.
but ASCII accept only one CHAR Hope you get the idea. sorry for my english
use oracle translate method to replace A-Z or a-z characters with numbers.
then use to_number to get number from it.
select translate('A1B2C3', 'ABC', '456') from dual; --result '415263'
select to_number(translate('A1B2C3', 'ABC', '456')) from dual; --result 415263
translate function documentation
The Oracle/PLSQL TRANSLATE function replaces a sequence of characters in a string with another set of characters. However, it replaces a single character at a time.
For example, it will replace the 1st character in the string_to_replace with the 1st character in the replacement_string. Then it will replace the 2nd character in the string_to_replace with the 2nd character in the replacement_string, and so on.
EDIT: After discussing further with the OP, it turns out he needed a function (in the mathematical sense) from short strings to integers. Such a function is ORA_HASH. The OP decided that ORA_HASH is likely what is needed for his project.
https://docs.oracle.com/cd/B28359_01/server.111/b28286/functions112.htm#SQLRF06313
The solution below is kept for historical perspective.
You could use the analytic function DENSE_RANK to assign numbers to strings.
For example:
with
employees ( id, first_name, last_name ) as (
select 'ABC', 'Jane', 'Smith' from dual union all
select 'ABD', 'Jane', 'Dryer' from dual union all
select 'XYZ', 'Mike', 'Lopez' from dual
)
-- End of simulated inputs (for testing purposes only).
-- Solution (SQL query) begins below this line.
select id, dense_rank() over (order by id) as num_id, first_name, last_name
from employees
;
ID NUM_ID FIRST_NAME LAST_NAME
--- ------ ---------- ---------
ABC 1 Jane Smith
ABD 2 Jane Dryer
XYZ 3 Mike Lopez

PL/SQL Stored proc that uses a comma separated parameter to drive a dynamic LIKE clause?

Is there a fairly simple way to take an input parameter containing a comma seperated list of prefixes and return a cursor based on a select statement that uses these?
i.e. (Pseudocode)
PROCEDURE get_by_prefix(p_list_of_prefixes IN varchar2, r_csr OUT SYS_REFCURSOR)
IS
BEGIN
OPEN r_csr FOR
SELECT * FROM my_table where some_column LIKE (the_individual_fields_from p_list_of_prefixes ||'%')
END
I've tried various combinations, and now have two problems - coercing the input into a suitable table (I think it needs to go into a table type rather than a VARCHAR2_TABLE), and secondly getting the like clause to be effectively a SELECT from an internal 'pseudotable'...
EDIT: It seems that people are suggesting ways to use 'IN' with a set of potential values - whereas Im looking at using LIKE. I could use a similar technique - building up dynamic SQL, but was wondering if there isnt a more elegant way...
PL/SQL has no concept of a comma-separated list and no built-in splitter as in Perl etc, so you'll have to use one of the hand-rolled methods such as this one:
https://stewashton.wordpress.com/2016/08/01/splitting-strings-surprise
(Other methods are available.) Then it's just a matter of either populating a collection in one step and using it in the next, or else combining the two as something like this:
declare
p_list_of_prefixes varchar2(100) := 'John,Jim,Jules,Janice,Jenny';
begin
open :refcur for
with params as
( select x.firstname
from xmltable(
'ora:tokenize($X, "\,")'
passing p_list_of_prefixes as x
columns firstname varchar2(4000) path '.'
) x
)
, people as
( select 'Dave Clark' as fullname from dual union all
select 'Jim Potter' from dual union all
select 'Jenny Jones' from dual
)
select x.firstname, p.fullname
from params x
left join people p on p.fullname like x.firstname || '%';
end;
Output:
FIRSTNAME FULLNAME
-------------- -----------
John
Jim Jim Potter
Jules
Janice
Jenny Jenny Jones
Using LIKE the way you want is easy, but it is the wrong solution. (See my Comment under the original post).
Anyway - if by order of your superiors, or some other semi-legitimate reason, you must use a LIKE condition, it should look something like this:
... where ',' || p_list_of_whatever || ',' like '%,' || some_column || ',%
Concatenating commas at both ends of both sides of the comparison is needed, because you don't want Jo in the column to match John in the input list. Start from there and you will see why you need the commas on the right-hand side, and then follow from there and you will see why you need them on the left also.

Parse Oracle output to a specific format

I have cust_nm column in a database. The column cust_nm is formatted with last name then first name are separated by a comma followed by a space than the middle initial.
TUNGESVIK, MARK M
I want to run a Oracle query to output this format.
If all your names are really in that exact format, you can do something like this
SQL> ed
Wrote file afiedt.buf
1 with x as (
2 select 'TUNGESVIK, MARK M' cust_nm from dual
3 )
4 select substr( cust_nm, 1, instr(cust_nm, ', ')-1 ) last_name,
5 substr( cust_nm, instr(cust_nm, ', ')+2, instr(cust_nm, ' ', -1) - instr(cust_nm, ', ')-2) first_name,
6 substr( cust_nm, instr(cust_nm, ' ', -1)+1, length(cust_nm) ) middle_initial
7* from x
SQL> /
LAST_NAME FIRS M
--------- ---- -
TUNGESVIK MARK M
When you start including people that don't have a middle initial (or that have multiple middle initials), people with multiple spaces in their last or first name, the probability that at least some names aren't in this format but some other format, things get a lot more challenging. There are software products whose only purpose is to take incoming name data, parse it, scrub it, and standardize it. Writing your own code to try to handle every corner case is likely to take way more time than you're expecting.

Resources