寫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
暫時先總結這么多,以后再補充。