在基于多个规则的字符串转换中需要帮助

时间:2019-05-16 20:46:06

标签: sql sql-server

我有一个func_name列。我在该func_name列上设置了一组规则,以创建func_short_name。

func_short_name所需的逻辑是:

  1. 使用'>'右边的任何内容;先于每个之后 FUNC_NAME字段中的“ +”或“ @”

  2. 每次出现“ +”或“ @”,将其附加到func_short_name

示例:

func_name:工具箱/matlab/cefclient/+matlab/+internal/getOpenPort.p> getOpenPort

func_short_name:matlab.internal.getOpenPort

上面的示例在'matlab'后面加上'internal',因为它们后面是'+'和'getOpenPort',因为它在'>'的右边

如何考虑每次出现“ +”或“ a”。有人可以帮我构造一个SQL或存储的proc吗?谢谢!

我尝试过单独实施规则,但是无法对每次出现的“ +”或“ @”进行递归追加。

select  substring(FUNC_NAME,charindex('a',FUNC_NAME)+1,100)
FROM table

select  FUNC_NAME,
charindex('@',FUNC_NAME)+1,
charindex('/',FUNC_NAME)-1
from table

select  concat(substring(FUNC_NAME,charindex('@',FUNC_NAME)+1,charindex('/',FUNC_NAME)-1),'.',substring(FUNC_NAME,charindex('>',FUNC_NAME)+1,100))
FROM table

func_name:工具箱/matlab/cefclient/+matlab/+internal/getOpenPort.p> getOpenPort

func_short_name:matlab.internal.getOpenPort

另一个例子: 功能名称: 工具箱/符号/符号/@sym/@aem/diag.m>诊断

func_short_name: sym.aem.diag

3 个答案:

答案 0 :(得分:1)

无论SQL Server的版本如何,都应该这样做。

DECLARE @func_name VARCHAR(200);
DECLARE @func_short_name VARCHAR(100) = '';
DECLARE @i INT = 1;
DECLARE @func_name_length INT;
DECLARE @start_position INT = 0;
DECLARE @end_position INT = 0;
DECLARE @gt_position INT = 0;

SET @func_name = 'toolbox/matlab/cefclient/+matlab/+internal/getOpenPort.p>getOpenPort';
--SET @func_name = 'toolbox/symbolic/symbolic/@sym/@aem/diag.m>diag';

SET @i = 1;
SET @func_name_length = LEN(@func_name);

-- loop through string character by character
WHILE @i <= @func_name_length
BEGIN
    IF (SUBSTRING(@func_name, @i, 1)) IN ('+', '@')
    BEGIN
        SET @start_position = @i;
    END;

    -- ending character found after starting character has been found
    IF (SUBSTRING(@func_name, @i, 1)) = '/'
       AND @start_position > 0
    BEGIN

        SET @end_position = @i;
        SET @func_short_name = @func_short_name
                               + SUBSTRING(@func_name, @start_position + 1, (@end_position - 1) - @start_position)
                               + '.';
        SET @start_position = 0;
    END;

    SET @i += 1;

END;

-- find greater than character
SET @gt_position = CHARINDEX('>', @func_name);

SET @func_short_name = @func_short_name + SUBSTRING(@func_name, @gt_position + 1, @func_name_length - @gt_position);

SELECT @func_name AS [FUNC NAME], @func_short_name AS [FUNC SHORT NAME];

答案 1 :(得分:0)

仅适用于SQL Server 2017 +

初始化:

DECLARE @Table TABLE (Func_Name NVARCHAR(MAX));
INSERT INTO @Table (Func_Name)VALUES
     ('toolbox/matlab/cefclient/+matlab/+internal/getOpenPort.p>getOpenPort')
    ,('toolbox/symbolic/symbolic/@sym/@aem/diag.m>diag')
;

代码:

SELECT STRING_AGG(REPLACE(REPLACE(a.[value],'+',''),'@',''),'.') 
    WITHIN GROUP (ORDER BY rn DESC) AS [Result]
FROM (
    SELECT b.ID,j.[value],ROW_NUMBER()OVER(PARTITION BY b.ID ORDER BY j.[Key] DESC) AS [rn]
    FROM (
        SELECT '["' + REPLACE(REPLACE(t.Func_Name,'/','","'),'>','","') + '"]' AS [value]
            ,ROW_NUMBER()OVER(ORDER BY (SELECT 1)) AS [ID]
        FROM @Table t
    ) b
    CROSS APPLY OPENJSON(b.[value]) j
) a
WHERE (a.[value] LIKE '[+]%' OR a.[value] LIKE '[@]%' OR a.rn = 1 /*last piece*/)
GROUP BY a.ID
;

答案 2 :(得分:0)

此解决方案基于递归公用表表达式,适用于2005年之前的任何SQL Server版本,但对于分隔字符并不十分严格。模式'%[@+>]%'查找以下任一字符:@+>。它确实返回了所需的结果:matlab.internal.getOpenPort

declare @f varchar(255); 
set @f='toolbox/matlab/cefclient/+matlab/+internal/getOpenPort.p>getOpenPort'+'/';

With rcte as (
 select 0 n,@f str, patindex('%[@+>]%',@f) p union all
 select p, substring(str, p+1,255), 
   patindex('%[@+>]%',substring(str, p+1,255)) 
 from rcte where p>0
)
SELECT STUFF((SELECT '.' +LEFT(str,charindex('/',str)-1)
      FROM rcte
      WHERE n>0
      FOR XML PATH('')), 1, 1, '') short

@f是包含需要转换的长函数名(在末尾添加了/)的变量。

参见此处的演示:https://rextester.com/MFVO10768