这篇文章包含一个非常完整的纯 SQL 解决方案,用 SQLServer 语法编写。我已将其转换为 Oracle 语法。它做得很好,尽管它不处理后缀(Jr.、III 等)。您应该阅读帖子中的其他警告:
SQL:从全名字段中解析名字、中间名和姓氏
SELECT first_name.original_input_data,
first_name.title,
first_name.first_name,
CASE
WHEN 0 = INSTR(first_name.rest_of_name, ' ') THEN
NULL --no more spaces? assume rest is the last name
ELSE
SUBSTR(first_name.rest_of_name, 1, INSTR(first_name.rest_of_name, ' ') - 1)
END AS middle_name,
SUBSTR(first_name.rest_of_name,
1 + INSTR(first_name.rest_of_name, ' '),
LENGTH(first_name.rest_of_name)) AS last_name
FROM (SELECT title.title,
CASE
WHEN 0 = INSTR(title.rest_of_name, ' ') THEN
title.rest_of_name --No space? return the whole thing
ELSE
SUBSTR(title.rest_of_name, 1, INSTR(title.rest_of_name, ' ') - 1)
END AS first_name,
CASE
WHEN 0 = INSTR(title.rest_of_name, ' ') THEN
NULL --no spaces @ all? then 1st name is all we have
ELSE
SUBSTR(title.rest_of_name, INSTR(title.rest_of_name, ' ') + 1, LENGTH(title.rest_of_name))
END AS rest_of_name,
title.original_input_data
FROM (SELECT
--if the first three characters are in this list,
--then pull it as a "title". otherwise return NULL for title.
CASE
WHEN SUBSTR(test_data.full_name, 1, 3) IN ('MR ', 'MS ', 'DR ', 'MRS') THEN
LTRIM(RTRIM(SUBSTR(test_data.full_name, 1, 3)))
ELSE
NULL
END AS title
--if you change the list, don't forget to change it here, too.
--so much for the DRY prinicple...
,
CASE
WHEN SUBSTR(test_data.full_name, 1, 3) IN ('MR ', 'MS ', 'DR ', 'MRS') THEN
LTRIM(RTRIM(SUBSTR(test_data.full_name, 4, LENGTH(test_data.full_name))))
ELSE
LTRIM(RTRIM(test_data.full_name))
END AS rest_of_name,
test_data.original_input_data
FROM (SELECT
--trim leading & trailing spaces before trying to process
--disallow extra spaces *within* the name
REPLACE(REPLACE(LTRIM(RTRIM(full_name)), ' ', ' '), ' ', ' ') AS full_name,
full_name AS original_input_data
FROM ( --if you use this, then replace the following
--block with your actual table
SELECT 'george w bush jr.' AS full_name
FROM dual
UNION
SELECT 'SUSAN B ANTHONY' AS full_name
FROM dual
UNION
SELECT 'alexander hamilton' AS full_name
FROM dual
UNION
SELECT 'osama bin laden jr' AS full_name
FROM dual
UNION
SELECT 'Martin J. VAN BUREN SENIOR III' AS full_name
FROM dual
UNION
SELECT 'Tommy' AS full_name
FROM dual
UNION
SELECT 'Billy' AS full_name
FROM dual
UNION
SELECT NULL AS full_name
FROM dual
UNION
SELECT ' ' AS full_name
FROM dual
UNION
SELECT ' JOHN JACOB SMITH' AS full_name
FROM dual
UNION
SELECT ' DR SANJAY GUPTA' AS full_name
FROM dual
UNION
SELECT 'DR JOHN S HOPKINS' AS full_name
FROM dual
UNION
SELECT ' MRS SUSAN ADAMS' AS full_name
FROM dual
UNION
SELECT ' MS AUGUSTA ADA SMITH-KING ' AS full_name
FROM dual) raw_data) test_data) title) first_name