Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在sql中拆分带大写字母的单词_Sql_Sql Server_Tsql - Fatal编程技术网

在sql中拆分带大写字母的单词

在sql中拆分带大写字母的单词,sql,sql-server,tsql,Sql,Sql Server,Tsql,有人知道如何从字符串中拆分以大写字母开头的单词吗 例如: DECLARE @var1 varchar(100) = 'OneTwoThreeFour' DECLARE @var2 varchar(100) = 'OneTwoThreeFourFive' DECLARE @var3 varchar(100) = 'One' SELECT @var1 as Col1, <?> as Col2 SELECT @var2 as Col1, <?

有人知道如何从字符串中拆分以大写字母开头的单词吗

例如:

    DECLARE @var1 varchar(100) = 'OneTwoThreeFour'
    DECLARE @var2 varchar(100) = 'OneTwoThreeFourFive'
    DECLARE @var3 varchar(100) = 'One'

    SELECT @var1 as Col1, <?> as Col2
    SELECT @var2 as Col1, <?> as Col2
    SELECT @var3 as Col1, <?> as Col2

如果这是不可能的,或者如果太长,标量函数也可以。

这是我刚刚创建的一个函数

作用

质疑

结果集


建立一个数字表。有一些很好的帖子向你展示了如何做到这一点。用输入字符串最大长度的值填充它。选择从1到当前输入字符串实际长度的值。将此数字列表交叉连接到输入字符串。使用结果为每个字符添加子字符串。然后,您可以将一个字符值的结果列表与预填充的表值变量进行比较,或者使用ASCII将每个字符转换为整数,并仅选择介于65“a”和90“Z”之间的字符。此时,您有一个列表,它是每个大写字符在输入字符串中的位置。将输入字符串的最大长度合并到此列表的末尾。你马上就会明白为什么了。现在您可以对输入变量进行子串,从第N行给定的数字开始,取第N行给定的数字+1的长度-第N行给定的数字。这就是为什么您必须在末尾合并额外的数字。最后,使用您选择的算法将所有这些子字符串连接在一起,以空格分隔


对不起,我面前没有一个实例可以尝试代码。听起来是个有趣的任务。我认为使用嵌套的SELECT语句将变得复杂且不可维护;最好将其设置为CTE,IMHO。

如果需要单个查询,可以使用替换来检查每个大写字母,如

SELECT @var1 col1, REPLACE(
                    REPLACE(
                     REPLACE(
                      ...
                       REPLACE(@var1, 'A', ' A')
                    , ... 
                  , 'X', ' X')
                , 'Y', ' Y')
              , 'Z', ' Z') col2
这不是最漂亮的东西,但会有用的

编辑 只需添加另一个函数,以其他答案的不同方式执行相同的操作

CREATE FUNCTION splitCapital (@param Varchar(MAX))
RETURNS Varchar(MAX)
BEGIN
  Declare @ret Varchar(MAX) = '';
  declare @len int = len(@param);

  WITH Base10(N) AS (
              SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 
    UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 
    UNION ALL SELECT 8 UNION ALL SELECT 9
  ), Chars(N) As (
    Select TOP(@len)
           nthChar 
         = substring(@param, u.N + t.N*10 + h.N*100 + th.N*1000 + 1, 1) 
           Collate Latin1_General_CS_AI
    FROM   Base10 u
           CROSS JOIN Base10 t
           CROSS JOIN Base10 h
           CROSS JOIN Base10 th
    WHERE  u.N + t.N*10 + h.N*100 + th.N*1000 < @len
    ORDER BY u.N + t.N*10 + h.N*100 + th.N*1000
  )
  SELECT @ret += Case nthChar 
                      When UPPER(nthChar) Then ' ' 
                      Else '' 
                 End + nthChar
  FROM   Chars

  RETURN @ret;
END

这一个使用了TSQL连接字符串变量的可能性,我不得不使用TOP N技巧强制按正确的顺序排列字符CTE行

这里是我创建的一个函数,类似于删除非字母字符

这一个使用区分大小写的排序规则,主动查找非空格/大写字母组合,然后使用STUFF函数插入空格。这是一个标量UDF,因此一些人会立即说它将比其他解决方案慢。对于这个概念,我说,请测试一下。此函数不使用任何表数据,只根据需要多次循环,因此可能会提供非常好的性能

Create Function dbo.Split_On_Upper_Case(@Temp VarChar(1000))
Returns VarChar(1000)
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
可以这样称呼:

Select dbo.Split_On_Upper_Case('OneTwoThreeFour')
Select dbo.Split_On_Upper_Case('OneTwoThreeFour')
Select dbo.Split_On_Upper_Case('One')
Select dbo.Split_On_Upper_Case('OneTwoThree')
Select dbo.Split_On_Upper_Case('stackOverFlow')
Select dbo.Split_On_Upper_Case('StackOverFlow')

我知道已经有了一些很好的答案,但是如果您想避免创建函数,也可以使用递归CTE来完成这一点。这当然不是一个干净的方法,但它是有效的

DECLARE
    @camelcase nvarchar(4000) = 'ThisIsCamelCased'
;

WITH
    split
AS
    (
        SELECT
              [iteration]   = 0
             ,[string]      = @camelcase

        UNION ALL

        SELECT
             [iteration]    = split.[iteration] + 1
            ,[string]       = STUFF(split.[string], pattern.[index] + 1, 0, ' ')
        FROM
            split
        CROSS APPLY
            ( SELECT [index] = PATINDEX(N'%[^ ][A-Z]%' COLLATE Latin1_General_Bin, split.[string]) )
            pattern
        WHERE
            pattern.[index] > 0
    )
SELECT TOP (1)
    [spaced] = split.[string]
FROM
    split
ORDER BY
    split.[iteration]   DESC
;
正如我所说,这不是一种很好的编写查询的方法,但是当我只是编写一些不想向数据库添加新工件的特殊查询时,我会使用这种方法。您还可以使用此选项将函数创建为内联表值函数,这通常会更好。

请尝试以下操作:

    declare  @t nvarchar (100) ='IamTheTestString'  
    declare  @len int
    declare  @Counter int =0 
    declare  @Final nvarchar (100) =''
    set @len =len( @t)


    while (@Counter <= @len)
    begin 

    set @Final= @Final + Case when  ascii(substring (@t,@Counter,1))>=65 and  
    ascii(substring (@t,@Counter,1))<=90 then ' '+substring (@t,@Counter,1) else 
    substring (@t,@Counter,1) end


    set @Counter=@Counter+1
    end

    print ltrim(@Final)

我想这可以通过使用正则表达式来找到a-Z并替换为空格+a-Z来完成。注意,标量函数可能会影响性能。@jean SQL Server中没有正则表达式。概述了向t-sql添加简单正则表达式支持的方法。性能注意事项适用。请注意,您可以在like运算符的参数中使用简单模式,即%[a-z][a-z]%,以标识具有驼峰大小写数据列的记录。通过正则表达式,我的意思是执行类似于SELECT patindex“%[ABCDEFGHIJKLMNOPQRSTUVXYZ]”的操作,“gaurang Ahmedabad”校对SQL\u Latin1\u General\u CP1\u CS\u Syes创建这个很有趣我刚刚创建了一个看看:@M.Ali-我刚才很欣赏你的答案。我对OP的建议是,他将其作为单一选择进行尝试,利用查询引擎的关系特征,并将基于函数的解决方案可能产生的交叉应用对性能的影响降至最低。这似乎是无效的。您正在循环使用varchar,将其拆分并逐个字符地重新组合在一起。性能不好。@t-clausen.dk选择替换“bBb”COLLATE拉丁语1_General_CS_AI,“B”,“B”返回“B Bb”当然不值得否决票+1来报复你。@bum当一个答案给出错误的结果时,它应该受到惩罚downvote@t-clausen.dk确实,您没有发现需要区分大小写的排序规则。
CREATE FUNCTION splitCapital (@param Varchar(MAX))
RETURNS Varchar(MAX)
BEGIN
  Declare @ret Varchar(MAX) = '';
  declare @len int = len(@param);

  WITH Base10(N) AS (
              SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 
    UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 
    UNION ALL SELECT 8 UNION ALL SELECT 9
  ), Chars(N) As (
    Select TOP(@len)
           nthChar 
         = substring(@param, u.N + t.N*10 + h.N*100 + th.N*1000 + 1, 1) 
           Collate Latin1_General_CS_AI
    FROM   Base10 u
           CROSS JOIN Base10 t
           CROSS JOIN Base10 h
           CROSS JOIN Base10 th
    WHERE  u.N + t.N*10 + h.N*100 + th.N*1000 < @len
    ORDER BY u.N + t.N*10 + h.N*100 + th.N*1000
  )
  SELECT @ret += Case nthChar 
                      When UPPER(nthChar) Then ' ' 
                      Else '' 
                 End + nthChar
  FROM   Chars

  RETURN @ret;
END
Create Function dbo.Split_On_Upper_Case(@Temp VarChar(1000))
Returns VarChar(1000)
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
Select dbo.Split_On_Upper_Case('OneTwoThreeFour')
Select dbo.Split_On_Upper_Case('OneTwoThreeFour')
Select dbo.Split_On_Upper_Case('One')
Select dbo.Split_On_Upper_Case('OneTwoThree')
Select dbo.Split_On_Upper_Case('stackOverFlow')
Select dbo.Split_On_Upper_Case('StackOverFlow')
DECLARE
    @camelcase nvarchar(4000) = 'ThisIsCamelCased'
;

WITH
    split
AS
    (
        SELECT
              [iteration]   = 0
             ,[string]      = @camelcase

        UNION ALL

        SELECT
             [iteration]    = split.[iteration] + 1
            ,[string]       = STUFF(split.[string], pattern.[index] + 1, 0, ' ')
        FROM
            split
        CROSS APPLY
            ( SELECT [index] = PATINDEX(N'%[^ ][A-Z]%' COLLATE Latin1_General_Bin, split.[string]) )
            pattern
        WHERE
            pattern.[index] > 0
    )
SELECT TOP (1)
    [spaced] = split.[string]
FROM
    split
ORDER BY
    split.[iteration]   DESC
;
    declare  @t nvarchar (100) ='IamTheTestString'  
    declare  @len int
    declare  @Counter int =0 
    declare  @Final nvarchar (100) =''
    set @len =len( @t)


    while (@Counter <= @len)
    begin 

    set @Final= @Final + Case when  ascii(substring (@t,@Counter,1))>=65 and  
    ascii(substring (@t,@Counter,1))<=90 then ' '+substring (@t,@Counter,1) else 
    substring (@t,@Counter,1) end


    set @Counter=@Counter+1
    end

    print ltrim(@Final)