有这么一个字符串,if(4/(if(2>1,2,1)+2) = 0,if(6/(3+3)=1,3,2),4/(4+4))
,怎么把他里面的 和if左括号 匹配的 右小括号 都变成 右中括号。处理前:if(4/(if(2>1,2,1)+2) = 0,if(6/(3+3)=1,3,2),4/(4+4))
处理后:if(4/(if(2>1,2,1]+2) = 0,if(6/(3+3)=1,3,2],4/(4+4)]项目里很重要的一个功能,各位高手帮帮忙啊,谢了sql 字符串处理 

解决方案 »

  1.   

    嗯,程序处理 应该能处理的 更好。但是 现在我们还有其他操作,最好还是在 sql里面 解决。谢谢留言啊
      

  2.   

    --仅供参考啊,汗~,期待好的算法……
    --还是用程序实现比较方便。用CLR写个函数,放到SQL SERVER里来处理吧,最简单。
    DROP TABLE #temp
    CREATE TABLE #temp(id INT, expression VARCHAR(MAX))
    INSERT #temp values(1, 'if(4/(if(2>1,2,1)+2) = 0,if(6/(3+3)=1,3,2),4/(4+4))')
    --SQL
    ;WITH cte1 AS  
    (
    SELECT
    id,
    pos = CHARINDEX('(', expression),
    word = CAST(LEFT(expression, CHARINDEX('(', expression) - 1) AS NVARCHAR(MAX)),
    name = 1,
    Split = CAST(STUFF(expression + '(', 1, CHARINDEX('(', expression + '('), '') AS NVARCHAR(MAX))
    FROM #temp
    UNION ALL
    SELECT
    id,
    pos = a.pos + CHARINDEX('(', Split),
    word = CAST(LEFT(Split, CHARINDEX('(', Split) - 1) AS NVARCHAR(MAX)),
    name = 1,
    Split = CAST(STUFF(Split, 1, CHARINDEX('(', Split), '') AS NVARCHAR(MAX))
    FROM cte1 a
    WHERE Split > ''
    ),
    cte2 AS  
    (
    SELECT
    id,
    pos = CHARINDEX(')', expression),
    word = CAST(LEFT(expression, CHARINDEX(')', expression) - 1) AS NVARCHAR(MAX)),
    name = -1,
    Split = CAST(STUFF(expression + ')', 1, CHARINDEX(')', expression + ')'), '') AS NVARCHAR(MAX))
    FROM #temp
    UNION ALL
    SELECT
    id,
    pos = a.pos + CHARINDEX(')', Split),
    word = CAST(LEFT(Split, CHARINDEX(')', Split) - 1) AS NVARCHAR(MAX)),
    name = -1,
    Split = CAST(STUFF(Split, 1, CHARINDEX(')', Split), '') AS NVARCHAR(MAX))
    FROM cte2 a
    WHERE Split > ''
    ),
    cte3 AS
    (
    SELECT rowno = ROW_NUMBER() OVER(ORDER BY id, pos), * FROM
    (
    SELECT id,pos,word,name FROM cte1 WHERE pos < 52
    UNION ALL
    SELECT id,pos,word,name FROM cte2 WHERE pos < 52
    ) t 
    ),
    cte4 AS
    (
    SELECT rowno, id,pos,word,name  FROM cte3 WHERE LEN(word) >= 2 AND UPPER(RIGHT(word, 2))='IF'
    UNION ALL
    SELECT b.rowno, b.id,a.pos,b.word,name=a.name+b.name
    FROM cte4 a
    INNER JOIN cte3 b
    ON a.rowno = b.rowno-1
    WHERE a.name+b.name > 0
    )
    SELECT RESULT=REPLACE(
    (
    SELECT A.WORD + (CASE WHEN a.name=1 THEN '(' WHEN A.NAME = -1 AND b.rowno IS NOT NULL THEN ']' ELSE ')' end)
    FROM cte3 a
    LEFT JOIN 
    (
    SELECT id, pos, rowno = MAX(rowno)+1
    FROM cte4
    group BY id, pos
    ) b
    ON a.rowno = b.rowno
    WHERE a.name = -1
    ORDER BY a.id, a.pos
    FOR XML PATH('')
    ),
    '&gt;', '>'
    )/*
    RESULT
    if(4/(if(2>1,2,1]+2) = 0,if(6/(3+3)=1,3,2],4/(4+4)]
    */
      

  3.   

    @lzw_0736
    先谢谢了,期待中
      

  4.   


    --第一步:创建自定义函数
    create function [dbo].[test_if]
    (@STR VARCHAR(MAX)) 
    returns varchar(max)
    as
    beginDECLARE @cu1 TABLE (SName varchar(1000),Number int,LR CHAR(1),re int ,number_R int,fz BIT)
    DECLARE @cu2 TABLE (number_R int,re int)INSERT @cu1
    SELECT *,ROW_NUMBER() OVER(ORDER BY NUMBER) RE
    ,CAST(0 AS int) number_R
    ,CAST(0 AS BIT) fz
    FROM
    (
    SELECT SName=SUBSTRING(a.SName,b.Number,Charindex('(',a.SName+'(',b.Number)-b.Number),
    b.Number-1 Number,'L' LR
    FROM (SELECT SName=@STR)a,master.dbo.spt_values b  
    Where SUBSTRING('('+a.SName,b.Number,1)='(' and b.Type='P'
    UNION ALL
    SELECT SName=SUBSTRING(a.SName,b.Number,Charindex(')',a.SName+')',b.Number)-b.Number),
    Charindex(')',a.SName+')',b.Number) Number,'R'
    FROM (SELECT SName=@STR)a,master.dbo.spt_values b  
    Where SUBSTRING(')'+a.SName,b.Number,1)=')' and b.Type='P'
    ) aDECLARE @number_R int,@re_R int,@number_L int,@re_L int
    WHILE EXISTS(SELECT 1 FROM @cu1 WHERE fz=0)
    BEGIN
    SELECT TOP 1 @number_R=number,@re_R=re FROM @cu1 WHERE lr='R' AND fz=0 ORDER BY re ASC
    SELECT TOP 1 @number_L=number,@re_L=re FROM @cu1 WHERE lr='L' AND fz=0 AND re<@re_R ORDER BY re DESC
    UPDATE @cu1 SET fz=1 WHERE re IN (@re_R,@re_L)
    UPDATE @cu1 SET number_R=@number_R WHERE re=@re_L
    END;
    WITH a1 AS
    (
    SELECT SName,number_R,ROW_NUMBER() OVER(ORDER BY re) re
    FROM @cu1
    WHERE lr='L'
    )
    INSERT @cu2
    SELECT number_R,ROW_NUMBER() OVER(ORDER BY re) re
    FROM a1 
    WHERE re IN (SELECT re+1 re FROM a1 WHERE CHARINDEX('IF',UPPER(SName))>0)DECLARE @i1 int,@i2 INT
    SELECT @i1=1,@i2=MAX(re) FROM @cu2
    WHILE @i1<=@i2
    BEGIN
    SELECT @number_R=number_R FROM @cu2 WHERE re=@i1
    SET @STR=STUFF(@STR,@number_R,1,']')
    SET @i1=@i1+1
    END
    return @STR
    end--第二步:执行自定义函数
    SELECT dbo.test_if('if(4/(if(2>1,2,1)+2) = 0,if(6/(3+3)=1,3,2),4/(4+4))')
      

  5.   

    @wwwwgou @lzw_0736 
    OK,可以解决。十分感谢。
    这两个方法 都花了 0.05秒左右,如果能更快些 就好了。
    分给你们俩了,如果 有更快的 方法,希望 高手 不吝赐教!