所以,我有一些函数来获取名字和姓氏,就像这样:
create function udf_get_first_name (@string nvarchar(100))
returns nvarchar(50)
as
begin
declare @first_name nvarchar(50)
set @string = ltrim(@string)
set @string = rtrim(@string)
if dbo.udf_get_number_of_spaces(@string) > 0
set @first_name = left(@string, charindex(' ',@string) -1)
else
set @first_name = @string
return @first_name
end
create function udf_get_last_name (@string nvarchar(100))
returns nvarchar(50)
as
begin
set @string = ltrim(@string)
set @string = rtrim(@string)
if dbo.udf_get_number_of_spaces (@string) > 0
begin
set @string = reverse(@string)
set @string = left(@string, charindex(' ', @string) -1)
set @string = reverse(@string)
end
return @string
end
我需要能够获得中间名,并且不能将我的头一直缠绕到到目前为止搜索中所阅读的内容。不知道我是否只是愚蠢。
我还需要能够将格式为L / M / F的名称也排序到适当的列中,这给我带来了更大的麻烦。
编辑:并非所有记录都有中间名。
答案 0 :(得分:3)
您可以使用以下解决方案,并使用函数以指定格式获取名称的一部分或全名:
--
-- function to get a part of a fullname or to reformat the fullname.
-- @fullname - the fullname to get the part from or to reformat.
-- @format - the format of the output using F (firstname), M (middlename) and L (lastname).
-- the function returns the fullname in specified format or NULL if input is not valid
-- or the part of name is empty.
--
CREATE FUNCTION GetNamePart(@fullname VARCHAR(200), @format VARCHAR(30))
RETURNS VARCHAR(200)
AS
BEGIN
-- replace multiple spaces of the fullname and trim the result.
SET @fullname = LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(@fullname, ' ', '<>'), '><', ''), '<>', ' ')))
-- get the different name parts (firstname, middlename and lastname) of the fullname.
DECLARE @first_name VARCHAR(100)
SET @first_name = LTRIM(RTRIM(LEFT(@fullname, CHARINDEX(' ', @fullname))))
DECLARE @last_name VARCHAR(100)
SET @last_name = LTRIM(RTRIM(RIGHT(@fullname, CHARINDEX(' ', REVERSE(@fullname)))))
DECLARE @middle_name VARCHAR(100)
SET @middle_name = LTRIM(RTRIM(SUBSTRING(@fullname, LEN(@first_name) + 1, LEN(@fullname) - LEN(@first_name) - LEN(@last_name))))
-- init the formatted name of the fullname.
DECLARE @formatted_name VARCHAR(100)
-- return only the formatted name if format string is valid.
IF PATINDEX('%[^LMF]%', UPPER(@format)) > 0
SET @formatted_name = ''
ELSE
BEGIN
SET @format = REPLACE(REPLACE(REPLACE(@format, 'M', '##M##'), 'L', '##L##'), 'F', '##F##')
SET @formatted_name = LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(UPPER(@format), '##F##', @first_name + ' '), '##M##', @middle_name + ' '), '##L##', @last_name + ' ')))
END
-- check the input (@fullname) for valid value (firstname, lastname or firstname, middlename, lastname).
IF PATINDEX('%_ %_% _%', @fullname) = 0 AND PATINDEX('%_ _%', @fullname) = 0
SET @formatted_name = ''
-- return the new formatted name and replace multiple spaces.
RETURN NULLIF(REPLACE(REPLACE(REPLACE(@formatted_name, ' ', '<>'), '><', ''), '<>', ' '), '')
END
此功能GetNamePart
使用两个参数(@fullname
和@format
)。第一个参数@fullname
是包含名字,姓氏和中间名的全名。第二个参数定义名称的输出格式。您可以使用字母F
(姓),M
(中间名)和L
(姓)来定义输出格式。
因此,您可以使用函数GetNamePart
来获取全名的中间名:
SELECT dbo.GetNamePart(fullname, 'M') FROM table_name
...或重新格式化全名:
SELECT dbo.GetNamePart(fullname, 'LMF') FROM table_name
demo on dbfiddle.uk (演示和测试用例)
但是您也可以使用SELECT
查询来获取名称的各个部分,而无需使用函数:
SELECT
LTRIM(RTRIM(LEFT(fullname, CHARINDEX(' ', fullname)))) AS first_name,
LTRIM(RTRIM(RIGHT(fullname, CHARINDEX(' ', REVERSE(fullname))))) AS last_name,
LTRIM(RTRIM(CASE WHEN PATINDEX('%_ %_% _%', fullname) > 0 THEN SUBSTRING(fullname, CHARINDEX(' ', fullname) + 1, (CHARINDEX(' ', fullname, CHARINDEX(' ', fullname)+1)-(CHARINDEX(' ', fullname) + 1))) ELSE '' END)) AS middle_name
FROM table_name
答案 1 :(得分:1)
类似于Sebastian Brosch的答案。在看到他的回答后,我还添加了TRIM函数。在此查询中,没有必要。但这真是太好了。例如,如果用户错误地添加了多个空格,则将其删除。
可能会有更好或更简单的方法来获得名字,中间名和姓氏。但这是我目前想出的方式。
CREATE FUNCTION dbo.SplitFullName(
@FullName NVARCHAR(MAX),
@Format NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE @FN NVARCHAR(MAX);
DECLARE @MN NVARCHAR(MAX);
DECLARE @LN NVARCHAR(MAX);
DECLARE @RV NVARCHAR(MAX);
SET @FN = RTRIM(LTRIM(SUBSTRING(@FullName,0, CHARINDEX(' ',@FullName))));
SET @MN = RTRIM(LTRIM(SUBSTRING(@FullName, CHARINDEX(' ',@FullName) + 1 , LEN(@FullName) - (CHARINDEX(' ',@FullName) + CHARINDEX(' ',REVERSE(@FullName)))+1)));
SET @LN = RTRIM(LTRIM(REVERSE(SUBSTRING(REVERSE(@FullName),0, CHARINDEX(' ',REVERSE(@FullName))))));
IF (@Format='FN')
SET @RV = CASE WHEN LEN(@FN) = 0 THEN NULL ELSE @FN END;
ELSE IF (@Format='MN')
SET @RV = CASE WHEN LEN(@MN) = 0 THEN NULL ELSE @MN END;
ELSE IF (@Format='LN')
SET @RV = CASE WHEN LEN(@LN) = 0 THEN NULL ELSE @LN END;;
ELSE
SET @RV = CONCAT(@LN, ' ', CASE WHEN LEN(@MN) = 0 THEN NULL ELSE CONCAT(@MN , ' ') END, @FN);
RETURN @RV;
END;
示例01
SELECT dbo.SplitFullName('Antonio P. Green', 'FN') AS FN,
dbo.SplitFullName('Antonio P. Green', 'MN') AS MN,
dbo.SplitFullName('Antonio P. Green', 'LN') AS LN,
dbo.SplitFullName('Antonio P. Green', 'LMF') AS LMF;
+---------+----+-------+------------------+
| FN | MN | LN | LMF |
+---------+----+-------+------------------+
| Antonio | P. | Green | Green P. Antonio |
+---------+----+-------+------------------+
示例02
select dbo.SplitFullName('Cindy Bertha Collier Sproles', 'FN') AS FN,
dbo.SplitFullName('Cindy Bertha Collier Sproles', 'MN') AS MN,
dbo.SplitFullName('Cindy Bertha Collier Sproles', 'LN') AS LN,
dbo.SplitFullName('Cindy Bertha Collier Sproles', 'LMF') AS LMF;
+-------+----------------+---------+------------------------------+
| FN | MN | LN | LMF |
+-------+----------------+---------+------------------------------+
| Cindy | Bertha Collier | Sproles | Sproles Bertha Collier Cindy |
+-------+----------------+---------+------------------------------+
示例03
SELECT dbo.SplitFullName('Tristan Jackson', 'FN') AS FN,
dbo.SplitFullName('Tristan Jackson', 'MN') AS MN,
dbo.SplitFullName('Tristan Jackson', 'LN') AS LN,
dbo.SplitFullName('Tristan Jackson', 'LMF') AS LMF;
+---------+------+---------+-----------------+
| FN | MN | LN | LMF |
+---------+------+---------+-----------------+
| Tristan | NULL | Jackson | Jackson Tristan |
+---------+------+---------+-----------------+
答案 2 :(得分:0)
您可以使用多个逗号分隔的CTE处理此问题。
declare @str nvarchar(max) ='kareena kapoor khan';
with
t0 AS (select charindex(' ',@str) pos, @str name ),
t1 AS (select charindex(' ',@str,pos+1)pos,@str name from t0)
select substring(t0.name,0,t0.pos) "firstName",
substring(t0.name,t0.pos+1,(t1.pos-t0.pos)) "MiddleName",
substring(t0.name,t1.pos+1,(len(t0.name)- t1.pos)) "Lastname"
from t0
inner join t1 on t0. name= t1.name
输出
|名字| MiddleName |姓氏
| kareena |卡普尔|汗
此外,您无需创建3个用于名字,中间名和姓氏的函数,而只需创建一个函数并将参数作为@namepart传递即可。
答案 3 :(得分:0)
未来从sql-server 2016开始: 使用STRING_SPLIT函数
Use Northwind
Go
SELECT ProductID, value
FROM Products
CROSS APPLY STRING_SPLIT(ProductName, ' ');
通过该查询,您可以拆分名称...,然后通过Row()函数使用,可以选择中间名称。
STRING_SPLIT要求兼容性级别至少为130。如果该级别小于130,则SQL Server无法找到STRING_SPLIT函数。
答案 4 :(得分:-1)
选择Ltrim(SUBSTRING(name,CharIndex('',name), 当(CHARINDEX('',name,CHARINDEX(''',name)+1)-CHARINDEX('',name))<= 0时 else CHARINDEX('',name,CHARINDEX('',name)+1)-CHARINDEX('',name)end))作为MiddleName 来自TableName