我需要在字符串中的alpha和数字文本块之间插入连字符。 我甚至不确定如何解决这个问题。
ABC123 -> ABC-123
ABC123XYZ -> ABC-123-XYZ
D123 -> D-123
123C -> 123-C
答案 0 :(得分:4)
这个可以为您提供单一价值。
DECLARE @CODE VARCHAR(50) = '12ABC123XYZ'
,@NEWCODE VARCHAR(100) = ''
;WITH CTE
AS (
SELECT NUMBER
,SUBSTRING(@CODE, NUMBER, 1) AS VAL
FROM master.dbo.spt_values
WHERE TYPE = 'P'
AND number BETWEEN 1
AND LEN(@CODE)
)
SELECT @NEWCODE = @NEWCODE + CASE
WHEN ISNUMERIC(C1.VAL) <> ISNUMERIC(ISNULL(C2.VAL, C1.VAL))
THEN '-' + C1.VAL
ELSE C1.VAL
END
FROM CTE C1
LEFT JOIN CTE C2 ON C1.number = C2.number + 1
SELECT @NEWCODE
结果: 12-ABC-123-XYZ
如果您希望这与表列一起使用,则需要创建标量函数。
CREATE FUNCTION CODE_SPLIT
(
@CODE VARCHAR(50)
)
RETURNS VARCHAR(100)
AS
BEGIN
DECLARE @NEWCODE VARCHAR(100) ='';
;WITH CTE
AS (
SELECT NUMBER
,SUBSTRING(@CODE, NUMBER, 1) AS VAL
FROM master.dbo.spt_values
WHERE TYPE = 'P'
AND number BETWEEN 1
AND LEN(@CODE)
)
SELECT @NEWCODE = @NEWCODE + CASE
WHEN ISNUMERIC(C1.VAL) <> ISNUMERIC(ISNULL(C2.VAL, C1.VAL))
THEN '-' + C1.VAL
ELSE C1.VAL
END
FROM CTE C1
LEFT JOIN CTE C2 ON C1.number = C2.number + 1
RETURN @NEWCODE
END
GO
并在实际的桌子上调用它
<强>架构:强>
SELECT * INTO #TAB FROM(
SELECT 'ABC123' AS CODE
UNION ALL
SELECT 'ABC123XYZ'
UNION ALL
SELECT 'D123'
UNION ALL
SELECT '123C'
)A
SELECT CODE, dbo.CODE_SPLIT(CODE) AS NEWCODE FROM #TAB
<强>结果:强>
+-----------+-------------+
| CODE | NEWCODE |
+-----------+-------------+
| ABC123 | ABC-123 |
| ABC123XYZ | ABC-123-XYZ |
| D123 | D-123 |
| 123C | 123-C |
+-----------+-------------+
答案 1 :(得分:1)
patindex('%[0-9]%')
返回第一个数字的索引。
patindex('%[^0-9]%')
返回第一个非数字字符的索引。
您可以像这样使用recursive CTE
和PATINDEX。
DECLARE @SampleData AS TABLE
(
TextValue varchar(100)
)
INSERT INTO @SampleData
VALUES ('ABC124'), ('ABC123XYZ'), ('123C'), ('ABC'), ('1A2B3C')
;WITH cte AS
(
SELECT sd.TextValue AS RootText,
sd.TextValue AS CurrentText,
CAST('' AS varchar(100)) AS Result
FROM @SampleData sd
UNION ALL
SELECT
c.RootText,
CASE
WHEN patindex('%[0-9]%', c.CurrentText) = 0 OR patindex('%[^0-9]%', c.CurrentText) = 0
THEN ''
WHEN patindex('%[0-9]%', c.CurrentText) > patindex('%[^0-9]%', c.CurrentText)
THEN RIGHT(c.CurrentText, len(c.CurrentText) - patindex('%[0-9]%', c.CurrentText) + 1)
ELSE RIGHT(c.CurrentText, len(c.CurrentText) - patindex('%[^0-9]%', c.CurrentText) + 1)
END AS CurrentText,
CAST(
CASE
WHEN patindex('%[0-9]%', c.CurrentText) = 0 OR patindex('%[^0-9]%', c.CurrentText) = 0
THEN Result + '-' + c.CurrentText
WHEN patindex('%[0-9]%', c.CurrentText) > patindex('%[^0-9]%', c.CurrentText)
THEN Result + '-' + LEFT(CurrentText, patindex('%[0-9]%', c.CurrentText) - 1)
ELSE Result + '-' + LEFT(CurrentText, patindex('%[^0-9]%', c.CurrentText) - 1)
END AS varchar(100)
) AS Result
FROM cte c
WHERE LEN(CurrentText) > 0
)
SELECT cte.RootText, STUFF(cte.Result, 1,1,'') AS Result FROM cte
WHERE cte.CurrentText = ''