我们在适当的情况下拥有庞大的属性列表,我们希望在每个单词之后获得适当空间的输出
例如 -
按原样: ServiceProviderReferenceNumber
未来:服务提供商参考编号
关于如何在T-SQL中转换它的任何想法?任何帮助将不胜感激
注意:我们正在使用SQL Server 2016
答案 0 :(得分:4)
试试这个工作
Create Function dbo.Split_On_Upper_Case(@Temp VarChar(100))
Returns VarChar(100)
AS
Begin
Declare @KeepValues as varchar(50)
Set @KeepValues = '%[^ ][A-Z]%'
While PatIndex(@KeepValues collate Latin1_General_Bin, @Temp) > 0
Set @Temp = Stuff(@Temp, PatIndex(@KeepValues collate Latin1_General_Bin, @Temp) + 1, 0, ' ')
Return @Temp
End
答案 1 :(得分:3)
这是一种没有循环的方法......
除了事实之外,这些循环是要避免的,这使得完整表的处理非常容易。
首先,我创建一个带有三个字符串的模拟表
DECLARE @tbl TABLE(ID INT IDENTITY,YourString VARCHAR(100));
INSERT INTO @tbl VALUES('ServiceProviderReferenceNumber'),('SomeOther'),('AndOneMore');
查询将首先创建一个数字计数表,然后将字符串拆分为单个字符,检查大写字母并添加空格。
最后,这会被重新调整和修剪
注意如果您可能需要超过1000个字符,只需向,Numbers AS c
添加一个Tally
(然后提供10.000个数字)
WITH Numbers AS
(SELECT Nr FROM(SELECT Nr FROM(VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS x(Nr)) AS y)
,Tally AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nr
FROM Numbers,Numbers AS a,Numbers AS b
)
,Splitted AS
(
SELECT ID
,CASE WHEN ASCII(Chars.OneChar) BETWEEN ASCII('A') AND ASCII('Z') THEN ' ' + Chars.OneChar ELSE Chars.OneChar END AS TheChar
FROM @tbl AS t
CROSS APPLY (SELECT TOP(LEN(t.YourString)) Tally.Nr FROM Tally) AS Nmbr
CROSS APPLY (SELECT SUBSTRING(t.YourString,Nmbr.Nr,1) AS OneChar) AS Chars
)
SELECT ID
,LTRIM((
SELECT s.TheChar AS [*]
FROM Splitted AS s
WHERE s.ID=Splitted.ID
FOR XML PATH('')
)) AS ReConcatenated
FROM Splitted
GROUP BY ID
结果
1 Service Provider Reference Number
2 Some Other
3 And One More
CREATE DATABASE testDB;
GO
USE testDB;
GO
CREATE TABLE tbl(ID INT IDENTITY,YourString VARCHAR(100));
GO
CREATE FUNCTION dbo.TestF(@String VARCHAR(4000))
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE @StringNew nvarchar(100) = '';
DECLARE @Char nvarchar(1);
DECLARE @len int = LEN(@String);
DECLARE @i int = 0;
WHILE @i <= @len
BEGIN
SET @i = @i+1;
SET @Char = substring(@String,@i,1);
IF (UNICODE(@Char) = UNICODE(UPPER(@Char)) AND @i > 1)
SET @StringNew = @StringNew + ' ' + @Char;
ELSE
SET @StringNew = @StringNew + @Char;
END;
RETURN @StringNew
END
GO
INSERT INTO tbl VALUES('ServiceProviderReferenceNumber'),('SomeOther'),('AndOneMore');
GO 100000
DECLARE @d DATETIME=GETDATE();
WITH Numbers AS
(SELECT Nr FROM(SELECT Nr FROM(VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS x(Nr)) AS y)
,Tally AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nr
FROM Numbers,Numbers AS a,Numbers AS b
)
,Splitted AS
(
SELECT ID
,CASE WHEN ASCII(Chars.OneChar) BETWEEN ASCII('A') AND ASCII('Z') THEN ' ' + Chars.OneChar ELSE Chars.OneChar END AS TheChar
FROM tbl AS t
CROSS APPLY (SELECT TOP(LEN(t.YourString)) Tally.Nr FROM Tally) AS Nmbr
CROSS APPLY (SELECT SUBSTRING(t.YourString,Nmbr.Nr,1) AS OneChar) AS Chars
)
SELECT ID
,LTRIM((
SELECT s.TheChar AS [*]
FROM Splitted AS s
WHERE s.ID=Splitted.ID
FOR XML PATH('')
)) AS ReConcatenated
FROM Splitted
GROUP BY ID;
SELECT CAST(GETDATE()-@d AS TIME);
GO
DECLARE @d DATETIME=GETDATE();
SELECT ID,dbo.TestF(tbl.YourString) AS ReConcatenated
FROM tbl
SELECT CAST(GETDATE()-@d AS TIME);
GO
USE master;
GO
DROP DATABASE testDB;
结果
**ad-hoc** 2.66 Seconds
**loop** 5.33
结果
**ad-hoc** 2.66 Seconds
**loop** 5.33
**while with `STUFF`** 1.71
答案 2 :(得分:1)
这是一种方法,它循环遍历字符串并比较字符的Uncicode值。我选择比较数字而不是字符,因为根据数据库配置'a'='A'评估为真。
DECLARE @String nvarchar(100) = 'ServiceProviderReferenceNumber';
DECLARE @StringNew nvarchar(100) = '';
DECLARE @Char nvarchar(1);
DECLARE @len int = LEN(@String);
DECLARE @i int = 0;
WHILE @i <= @len
BEGIN
SET @i = @i+1;
SET @Char = substring(@String,@i,1);
IF (UNICODE(@Char) = UNICODE(UPPER(@Char)) AND @i > 1)
SET @StringNew = @StringNew + ' ' + @Char;
ELSE
SET @StringNew = @StringNew + @Char;
END;
PRINT @StringNew
答案 3 :(得分:0)
尝试这种超高速递归CTE
;with
w as (
select
id,
cast(YourColumn collate LATIN1_GENERAL_BIN as varchar(500)) ss
from YourTable w
),
r as (
select id, ss s, 2 l, PATINDEX('%[A-Z]%', ss) p, 1 i
from w
union all
select w.id, cast(stuff(s, p, 0, ' ') as varchar(500)), p + 1 l, pos + p + 1 p, pos i
from w
join (
select id, s, PATINDEX('%[A-Z]%', substring(s, p+1, 500) ) pos, p, i
from r
) rr on w.id = rr.id and i>0
)
select id, s
from r
where i=0
OPTION (MAXRECURSION 500);
答案 4 :(得分:0)
;WITH a(s) AS
(
SELECT 'ServiceProviderReferenceNumber' UNION
SELECT 'ConvertProperCaseToSpaceAfterProperCase'
)
SELECT LTRIM(b.ss) FROM a
CROSS APPLY (
SELECT CASE WHEN ASCII(SUBSTRING(a.s,sv.number,1)) BETWEEN 65 AND 90 THEN ' '+SUBSTRING(a.s,sv.number,1) ELSE SUBSTRING(a.s,sv.number,1) END
FROM master.dbo.spt_values AS sv
WHERE sv.type='P' AND sv.number BETWEEN 1 AND LEN(a.s)
FOR XML PATH('')
) b(ss)
Convert Proper Case To Space After Proper Case Service Provider Reference Number