写SQL时经常会遇到需要根据特定字符去截取原始字符串的情况,简单总结一下。
首先,准备工作:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MY_TEST](
[ID] [int] IDENTITY(1,1) NOT NULL,
[FIELDSVALUE] [nvarchar](255) NULL,
CONSTRAINT [PK_MY_TEST] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];
INSERT INTO [dbo].[MY_TEST]
([FIELDSVALUE])
VALUES
(‘5yt5g/h.7yj/5e//435tsd‘),
(‘//.we4rf6@gf/76iyg5t/ihjk//6yjf‘),
(‘435t/56yg/53ytdh/56uyj/6ury/5utyjf/6uyrh/65uyhf/74urh/q4rtegsd//‘),
(‘34tg3yuh/564yg‘),
(‘65uej/78irj/658jg44g/6jy/‘),
(‘34t/5euyhd/45yh/5yrth/5tr‘),
(‘192.168.1.1‘);
执行查询,
自此,准备工作完成。
首先,我想看一下ID为3的那一行,‘/’总共出现了几次:
SELECT len([FIELDSVALUE])-len(replace([FIELDSVALUE], ‘/‘, ‘‘)) AS [COUNTS] FROM [dbo].[MY_TEST] WHERE [ID] = 3;
接着,我想看看 ‘/‘ 在ID=1时,首次出现的位置:
SELECT CHARINDEX(‘/‘,[FIELDSVALUE]) AS [INDEXOF] FROM [dbo].[MY_TEST] WHERE [ID] =1;
然后,第二次出现的位置:
SELECT CHARINDEX(‘/‘,[FIELDSVALUE],CHARINDEX(‘/‘,[FIELDSVALUE])+1) AS [INDEXOF] FROM [dbo].[MY_TEST] WHERE [ID] = 1;
那么,想知道ID=1时,第一个‘/‘和第二个‘/‘之间的字串就很简单了:
SELECT SUBSTRING([FIELDSVALUE],CHARINDEX(‘/‘,[FIELDSVALUE])+1,
CHARINDEX(‘/‘,[FIELDSVALUE],CHARINDEX(‘/‘,[FIELDSVALUE])+1)-CHARINDEX(‘/‘,[FIELDSVALUE])-1)
AS [NEWSTRING]
FROM [dbo].[MY_TEST]
WHERE [ID] = 1;
如果指定的分隔符确定不超过3个的话,还有个简单的函数 PARSENAME ,该函数是用于域名解析的,先看下效果:
SELECT [ID], [FIELDSVALUE],
PARSENAME(REPLACE([FIELDSVALUE],‘/‘,‘.‘),4) AS [第四段],
PARSENAME(REPLACE([FIELDSVALUE],‘/‘,‘.‘),3) AS [第三段],
PARSENAME(REPLACE([FIELDSVALUE],‘/‘,‘.‘),2) AS [第二段],
PARSENAME(REPLACE([FIELDSVALUE],‘/‘,‘.‘),1) AS [第一段]
FROM [dbo].[MY_TEST]
WHERE [ID] = 7;
可以看出,PARSENAME 函数解析域名时,是从后向前解析的,微软官方提供的解释为:PARSENAME ( ‘object_name‘ , object_piece )
‘ object_name ‘
是要为其检索指定对象部分的对象的名称。
object_piece
是要返回的对象部分。object_piece的类型为int,值可以为1,2,3,4
但是,有时候也会碰到这样的情况:截取指定字符第N次出现和第N+1次出现时的字串。这个时候,单纯的写查询SQL就会很繁琐,就可以使用存储过程去实现,
比如,我想知道 [ID] = 3 时,‘/‘ 字符第6次和第7次出现时的中间字串。
先创建个存储过程:
IF EXISTS(SELECT 1 FROM SYSOBJECTS WHERE NAME=‘SELECTINDEX‘)
DROP FUNCTION SELECTINDEX
GO
CREATE FUNCTION SELECTINDEX(@STRINGS NVARCHAR(200),@STRING NVARCHAR(10),@INDEX INT)
--@STRINGS:待查找字符串,@INDEX:位置
RETURNS INT
AS
BEGIN
DECLARE
@I INT,--当前找到第@I个
@POSITION INT--所在位置
SET @POSITION=1;
SET @I=0;
WHILE CHARINDEX(@STRING,@STRINGS,@POSITION)>0
BEGIN
SET @POSITION=CHARINDEX(@STRING,@STRINGS,@POSITION)+1;
SET @I=@I+1;
IF @I=@INDEX
BEGIN
RETURN @POSITION-1;
END
END
RETURN 0;--0表示未找到
END
GO
然后就简单了:
SELECT SUBSTRING([FIELDSVALUE],
[dbo].SELECTINDEX([FIELDSVALUE],‘/‘,6)+1,
[dbo].SELECTINDEX([FIELDSVALUE],‘/‘,7)-([dbo].SELECTINDEX([FIELDSVALUE],‘/‘,6)+1))
AS [NEWSTRING]
FROM [dbo].[MY_TEST]
WHERE [ID] = 3
暂时先总结这么多,以后再补充。