T-SQL 大写字母前的空格

发布于 2024-10-10 05:14:49 字数 180 浏览 0 评论 0原文

这个问题是不言自明的。您能指出一种在字符串的每个大写字母之间放置空格的方法吗?

SELECT dbo.SpaceBeforeCap('ThisIsATestString')

会导致

This Is A Test String.

The question is self explanatory. Could you please point out a way to put spaces between each capital letter of a string.

SELECT dbo.SpaceBeforeCap('ThisIsATestString')

would result in

This Is A Test String.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

过去的过去 2024-10-17 05:14:49

仅当前一个和下一个字符为小写时才会添加空格。这样,“MyABCAnalysis”将成为“我的 ABC 分析”。

我也添加了对先前空间的检查。由于我们的一些字符串以 'GR_' 为前缀,有些还包含下划线,因此我们可以使用替换函数,如下所示:

select dbo.GR_SpaceBeforeCap(replace('GR_ABCAnalysis_Test','_',' '))
返回“GR ABC 分析测试”

CREATE FUNCTION GR_SpaceBeforeCap (
    @str nvarchar(max)
)
returns nvarchar(max)
as
begin

declare
    @i int, @j int
,   @cp nchar, @c0 nchar, @c1 nchar
,   @result nvarchar(max)

select
    @i = 1
,   @j = len(@str)
,   @result = ''

while @i <= @j
begin
    select
        @cp = substring(@str,@i-1,1)
    ,   @c0 = substring(@str,@i+0,1)
    ,   @c1 = substring(@str,@i+1,1)

    if @c0 = UPPER(@c0) collate Latin1_General_CS_AS
    begin
        -- Add space if Current is UPPER 
        -- and either Previous or Next is lower
        -- and Previous or Current is not already a space
        if @c0 = UPPER(@c0) collate Latin1_General_CS_AS
        and (
                @cp <> UPPER(@cp) collate Latin1_General_CS_AS
            or  @c1 <> UPPER(@c1) collate Latin1_General_CS_AS
        )
        and @cp <> ' '
        and @c0 <> ' '
            set @result = @result + ' '
    end -- if @co

    set @result = @result + @c0
    set @i = @i + 1
end -- while

return @result
end

This will add spaces only if the previous and next character is lowercase. That way 'MyABCAnalysis' will be 'My ABC Analysis'.

I added a check for a previous space too. Since some of our strings are prefixed with 'GR_' and some also contain underscores, we can use the replace function as follows:

select dbo.GR_SpaceBeforeCap(replace('GR_ABCAnalysis_Test','_',' '))
Returns 'GR ABC Analysis Test'

CREATE FUNCTION GR_SpaceBeforeCap (
    @str nvarchar(max)
)
returns nvarchar(max)
as
begin

declare
    @i int, @j int
,   @cp nchar, @c0 nchar, @c1 nchar
,   @result nvarchar(max)

select
    @i = 1
,   @j = len(@str)
,   @result = ''

while @i <= @j
begin
    select
        @cp = substring(@str,@i-1,1)
    ,   @c0 = substring(@str,@i+0,1)
    ,   @c1 = substring(@str,@i+1,1)

    if @c0 = UPPER(@c0) collate Latin1_General_CS_AS
    begin
        -- Add space if Current is UPPER 
        -- and either Previous or Next is lower
        -- and Previous or Current is not already a space
        if @c0 = UPPER(@c0) collate Latin1_General_CS_AS
        and (
                @cp <> UPPER(@cp) collate Latin1_General_CS_AS
            or  @c1 <> UPPER(@c1) collate Latin1_General_CS_AS
        )
        and @cp <> ' '
        and @c0 <> ' '
            set @result = @result + ' '
    end -- if @co

    set @result = @result + @c0
    set @i = @i + 1
end -- while

return @result
end
夏日落 2024-10-17 05:14:49

假设 SQL Server 2005 或更高版本,此修改自此处的代码: http ://www.kodyaz.com/articles/case-sensitive-sql-split-function.aspx

CREATE FUNCTION SpaceBeforeCap
(
 @str nvarchar(max)
)
returns nvarchar(max)
as
begin

declare @i int, @j int
declare @returnval nvarchar(max)
set @returnval = ''
select @i = 1, @j = len(@str)

declare @w nvarchar(max)

while @i <= @j
begin
 if substring(@str,@i,1) = UPPER(substring(@str,@i,1)) collate Latin1_General_CS_AS
 begin
  if @w is not null
  set @returnval = @returnval + ' ' + @w
  set @w = substring(@str,@i,1)
 end
 else
  set @w = @w + substring(@str,@i,1)
 set @i = @i + 1
end
if @w is not null
 set @returnval = @returnval + ' ' + @w

return ltrim(@returnval)

end

然后可以按照您上面的建议进行调用。

Assuming SQL Server 2005 or later, this modified from code taken here: http://www.kodyaz.com/articles/case-sensitive-sql-split-function.aspx

CREATE FUNCTION SpaceBeforeCap
(
 @str nvarchar(max)
)
returns nvarchar(max)
as
begin

declare @i int, @j int
declare @returnval nvarchar(max)
set @returnval = ''
select @i = 1, @j = len(@str)

declare @w nvarchar(max)

while @i <= @j
begin
 if substring(@str,@i,1) = UPPER(substring(@str,@i,1)) collate Latin1_General_CS_AS
 begin
  if @w is not null
  set @returnval = @returnval + ' ' + @w
  set @w = substring(@str,@i,1)
 end
 else
  set @w = @w + substring(@str,@i,1)
 set @i = @i + 1
end
if @w is not null
 set @returnval = @returnval + ' ' + @w

return ltrim(@returnval)

end

This can then be called just as you have suggested above.

愚人国度 2024-10-17 05:14:49

该函数结合了之前的答案。有选择地选择保留相邻的 CAPS:

CREATE FUNCTION SpaceBeforeCap (
    @InputString NVARCHAR(MAX),
    @PreserveAdjacentCaps BIT
)
RETURNS NVARCHAR(MAX)
AS
BEGIN

DECLARE
    @i INT, @j INT,
        @previous NCHAR, @current NCHAR, @next NCHAR,
        @result NVARCHAR(MAX)

SELECT
    @i = 1,
        @j = LEN(@InputString),
        @result = ''

WHILE @i <= @j
BEGIN
    SELECT
        @previous = SUBSTRING(@InputString,@i-1,1),
                @current = SUBSTRING(@InputString,@i+0,1),
                @next = SUBSTRING(@InputString,@i+1,1)

    IF @current = UPPER(@current) COLLATE Latin1_General_CS_AS
    BEGIN
        -- Add space if Current is UPPER 
        -- and either Previous or Next is lower or user chose not to preserve adjacent caps
        -- and Previous or Current is not already a space
        IF @current = UPPER(@current) COLLATE Latin1_General_CS_AS
        AND (
                            @previous <> UPPER(@previous) COLLATE Latin1_General_CS_AS
                            OR  @next <> UPPER(@next) collate Latin1_General_CS_AS
                            OR  @PreserveAdjacentCaps = 0
        )
        AND @previous <> ' '
        AND @current <> ' '
            SET @result = @result + ' '
    END 

    SET @result = @result + @current
    SET @i = @i + 1
END 

RETURN @result
END

GO
SELECT dbo.SpaceBeforeCap('ThisIsASampleDBString', 1)
GO
SELECT dbo.SpaceBeforeCap('ThisIsASampleDBString', 0)

This function combines previous answers. Selectively choose to preserve adjacent CAPS:

CREATE FUNCTION SpaceBeforeCap (
    @InputString NVARCHAR(MAX),
    @PreserveAdjacentCaps BIT
)
RETURNS NVARCHAR(MAX)
AS
BEGIN

DECLARE
    @i INT, @j INT,
        @previous NCHAR, @current NCHAR, @next NCHAR,
        @result NVARCHAR(MAX)

SELECT
    @i = 1,
        @j = LEN(@InputString),
        @result = ''

WHILE @i <= @j
BEGIN
    SELECT
        @previous = SUBSTRING(@InputString,@i-1,1),
                @current = SUBSTRING(@InputString,@i+0,1),
                @next = SUBSTRING(@InputString,@i+1,1)

    IF @current = UPPER(@current) COLLATE Latin1_General_CS_AS
    BEGIN
        -- Add space if Current is UPPER 
        -- and either Previous or Next is lower or user chose not to preserve adjacent caps
        -- and Previous or Current is not already a space
        IF @current = UPPER(@current) COLLATE Latin1_General_CS_AS
        AND (
                            @previous <> UPPER(@previous) COLLATE Latin1_General_CS_AS
                            OR  @next <> UPPER(@next) collate Latin1_General_CS_AS
                            OR  @PreserveAdjacentCaps = 0
        )
        AND @previous <> ' '
        AND @current <> ' '
            SET @result = @result + ' '
    END 

    SET @result = @result + @current
    SET @i = @i + 1
END 

RETURN @result
END

GO
SELECT dbo.SpaceBeforeCap('ThisIsASampleDBString', 1)
GO
SELECT dbo.SpaceBeforeCap('ThisIsASampleDBString', 0)
毅然前行 2024-10-17 05:14:49

为了完全避免循环,使用计数表可以有所帮助。如果您在 SQL 2022 上运行,则 generate_series 函数甚至可以删除此依赖项。此方法将比循环迭代快得多。

create function core.ufnAddSpaceBeforeCapital
(
    @inputString nvarchar(max)
)
returns nvarchar(max)
as
begin

    declare @outputString nvarchar(max)

    select 
        @outputString = string_agg(iif(t.value = 1, upper(substring(@inputString,t.value,1)),iif(ascii(substring(@inputString,t.value,1)) between 65 and 90, ' ','') + substring(@inputString,t.value,1)),'')
    from 
        generate_series(1,cast(len(@inputString) as int)) t

    return @outputString

end

标量函数不可内联,因此如果您需要的话,我提供了替代的内联表值函数。

create function core.ufnAddSpaceBeforeCapitalITVF
(
    @inputString nvarchar(max)
)
returns table
as
return
(
    select 
        string_agg(iif(t.value = 1, upper(substring(@inputString,t.value,1)),iif(ascii(substring(@inputString,t.value,1)) between 65 and 90, ' ','') + substring(@inputString,t.value,1)),'') as outputString
    from 
        generate_series(1,cast(len(@inputString) as int)) t
)

end

To avoid loops altogether, use of a tally table can help here. If you are running on SQL 2022, then the generate_series function can remove even this dependency. This method will be significantly faster than iterating through a loop.

create function core.ufnAddSpaceBeforeCapital
(
    @inputString nvarchar(max)
)
returns nvarchar(max)
as
begin

    declare @outputString nvarchar(max)

    select 
        @outputString = string_agg(iif(t.value = 1, upper(substring(@inputString,t.value,1)),iif(ascii(substring(@inputString,t.value,1)) between 65 and 90, ' ','') + substring(@inputString,t.value,1)),'')
    from 
        generate_series(1,cast(len(@inputString) as int)) t

    return @outputString

end

The scalar function is not inlineable, so I've provided an alternative inline table-valued function if that's what you need.

create function core.ufnAddSpaceBeforeCapitalITVF
(
    @inputString nvarchar(max)
)
returns table
as
return
(
    select 
        string_agg(iif(t.value = 1, upper(substring(@inputString,t.value,1)),iif(ascii(substring(@inputString,t.value,1)) between 65 and 90, ' ','') + substring(@inputString,t.value,1)),'') as outputString
    from 
        generate_series(1,cast(len(@inputString) as int)) t
)

end
无语# 2024-10-17 05:14:49

CLR 和正则表达式或 26 个替换语句、区分大小写的整理子句和修剪。

CLR and regular expressions or 26 replace statements a case sensitive collate clause and a trim.

烙印 2024-10-17 05:14:49

另一种策略是检查每个字符的 ascii 值:

create function SpaceBeforeCap
 (@str nvarchar(max))
returns nvarchar(max)
as
begin
  declare @result nvarchar(max)= left(@str, 1), 
          @i int = 2

  while @i <= len(@str)
  begin
    if ascii(substring(@str, @i, 1)) between 65 and 90
      select @result += ' '
    select @result += substring(@str, @i, 1)
    select @i += 1 
  end

  return @result
 end

 /***
  SELECT dbo.SpaceBeforeCap('ThisIsATestString') 
 **/

Another strategy would be to check the ascii value of each character:

create function SpaceBeforeCap
 (@str nvarchar(max))
returns nvarchar(max)
as
begin
  declare @result nvarchar(max)= left(@str, 1), 
          @i int = 2

  while @i <= len(@str)
  begin
    if ascii(substring(@str, @i, 1)) between 65 and 90
      select @result += ' '
    select @result += substring(@str, @i, 1)
    select @i += 1 
  end

  return @result
 end

 /***
  SELECT dbo.SpaceBeforeCap('ThisIsATestString') 
 **/
_蜘蛛 2024-10-17 05:14:49

虽然我真的很喜欢字符循环的答案,但我对性能并不感到兴奋。我发现对于我的用例来说,这只需一小部分时间即可完成。

CREATE function SpaceBeforeCap
    (@examine nvarchar(max))
returns nvarchar(max)
as
begin

DECLARE @index as INT

SET @index = PatIndex( '%[^ ][A-Z]%', @examine COLLATE Latin1_General_BIN)
WHILE @index > 0 BEGIN

    SET @examine = SUBSTRING(@examine, 1, @index) + ' ' + SUBSTRING(@examine, @index + 1, LEN(@examine))
    SET @index = PatIndex( '%[^ ][A-Z]%', @examine COLLATE Latin1_General_BIN)

END

RETURN LTRIM(@examine)

end

这利用了以下事实:
区分大小写的模式搜索仅适用于某些情况排序规则。字符类 [^ ] 表示除空格之外的任何内容,因此当我们将缺失的空格添加到字符串中时,我们会进一步匹配该字符串,直到它完整为止。

While I really like the char looping answers I was not thrilled with the performance. I have found this performs in a fraction of the time for my use case.

CREATE function SpaceBeforeCap
    (@examine nvarchar(max))
returns nvarchar(max)
as
begin

DECLARE @index as INT

SET @index = PatIndex( '%[^ ][A-Z]%', @examine COLLATE Latin1_General_BIN)
WHILE @index > 0 BEGIN

    SET @examine = SUBSTRING(@examine, 1, @index) + ' ' + SUBSTRING(@examine, @index + 1, LEN(@examine))
    SET @index = PatIndex( '%[^ ][A-Z]%', @examine COLLATE Latin1_General_BIN)

END

RETURN LTRIM(@examine)

end

This makes use of the fact that
case sensitive pattern search only works in some collations. The character class [^ ] means anything except space, so as we add the missing spaces we match farther into the string until it is complete.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文