SQL Server 游標運用:鼠標軌跡字符串分割


一.本文所涉及的內容(Contents)

  1. 本文所涉及的內容(Contents)
  2. 背景(Contexts)
  3. 游標模板(Cursor Template)
  4. 鼠標軌跡字符串分割SQL腳本實現(SQL Codes)
  5. 補充說明(Addon)

二.背景(Contexts)

  我們的系統中記錄了用戶的鼠標行為軌跡字符串,這些字符串的格式是:PosSet:[573,1103,2010-09-03 22:32:35],[864,110,2010-09-03 22:32:57],這個字段表示用戶點擊頁面的X坐標,Y坐標,時間。現在要求對這樣字符串進行分割。

  需要注意的是當字符串只有一個坐標的時候,如:PosSet:[513,1303,2010-09-03 22:34:35],你需要考慮這種情況的處理,因為這個時候就沒有分隔字符在字符串了。

  還需要考慮字符串不規則的時候的異常處理;

wps_clip_image-25473

(Figure1:基礎數據)

wps_clip_image-3548

(Figure2:實現效果圖)

三.游標模板(Cursor Template)

  在正式解決問題之前我先提供一個游標的模板,它簡單的實現了找出數據庫中所有的數據庫名,其實這個模板的目的是為了提供一個規范化的游標SQL代碼模板。

--游標模板
DECLARE @databaseName VARCHAR(100)

DECLARE @itemCur CURSOR
SET @itemCur = CURSOR FOR 
    SELECT name FROM sys.databases 
        WHERE database_id > 4

OPEN @itemCur
FETCH NEXT FROM @itemCur INTO @databaseName
WHILE @@FETCH_STATUS=0
BEGIN
    --邏輯處理
    PRINT @databaseName
    
    FETCH NEXT FROM @itemCur INTO @databaseName
END 

CLOSE @itemCur
DEALLOCATE @itemCur

wps_clip_image-27448

(Figure3:返回數據庫名)

四.鼠標軌跡字符串分割SQL腳本實現(SQL Codes)

(一) 首先創建測試表VisiteLog,並插入測試數據:

--創建測試表[VisiteLog]
CREATE TABLE [dbo].[VisiteLog](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [PosSet] [varchar](500) NULL,
 CONSTRAINT [PK_VisiteLog] 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]
GO

--插入測試數據
SET IDENTITY_INSERT [dbo].[VisiteLog] ON
INSERT [dbo].[VisiteLog] ([Id], [PosSet]) VALUES (1, N'[573,1103,2010-09-03 22:32:35],[864,110,2010-09-03 22:32:57]')
INSERT [dbo].[VisiteLog] ([Id], [PosSet]) VALUES (2, N'[513,1303,2010-09-03 22:34:35]')
SET IDENTITY_INSERT [dbo].[VisiteLog] OFF

--查看數據
SELECT * FROM [dbo].[VisiteLog]

clip_image001

(Figure4:基礎數據)

 

(二) 接着創建表PosSetInfo,這個表是用來保存鼠標軌跡字符串分割后的數據:

--創建表[PosSetInfo]
CREATE TABLE [dbo].[PosSetInfo](
    [ID] [int] NULL,
    [PosSet_x] [int] NULL,
    [PosSet_y] [int] NULL,
    [PosTime] [datetime] NULL
) ON [PRIMARY]
GO

 

(三) 根據鼠標軌跡字符串:[573,1103,2010-09-03 22:32:35],[864,110,2010-09-03 22:32:57]。它坐標點與坐標點之間的分隔符是“,”,X坐標與Y坐標同樣適用分隔符“,”,這給我們的分割帶來了一些不便,所以我們創建了一個函數,它的作用是把字符串@str以@split分隔符進行分隔,返回第@index次匹配的元素。如下圖所示:

-- =============================================
-- Author:      <聽風吹雨>
-- Create date: <2010/05/27>
-- Description: <把字符串@str以@split分隔符進行分隔,返回第@index次匹配的元素>
-- =============================================
CREATE FUNCTION [dbo].[Get_StrArrayStrOfIndex]
(
    @str VARCHAR(5000),  --要分割的字符串
    @split VARCHAR(10),  --分隔符號
    @index INT --取第幾個元素
)
RETURNS VARCHAR(5000)
AS
BEGIN
    DECLARE @location INT
    DECLARE @start INT
    DECLARE @next INT
    DECLARE @seed INT
    SET @str=LTRIM(RTRIM(@str))
    SET @start=1
    SET @next=1
    SET @seed=LEN(@split)
  
    SET @location=CHARINDEX(@split,@str)
    WHILE @location<>0 and @index>@next
    BEGIN
        SET @start=@location+@seed
        SET @location=CHARINDEX(@split,@str,@start)
        SET @next=@next+1
    END
    IF @location =0 SELECT @location =LEN(@str)+1 
    RETURN SUBSTRING(@str,@start,@location-@start)
END

--測試函數
SELECT DBO.[Get_StrArrayStrOfIndex]('AB,CDE,FG,HIJK',',',3);

wps_clip_image-11407

(Figure5:函數測試效果)

 

(四) 下面的SQL腳本就是對VisiteLog表的數據進行分割,再把分割后的字符串保存到PosSetInfo表中,這個腳本的主要做法是先把[573,1103,2010-09-03 22:32:35],[864,110,2010-09-03 22:32:57]以“]”做為分隔符,把數據分割成兩段:[573,1103,2010-09-03 22:32:35]和[864,110,2010-09-03 22:32:57],再以“,”做為分割符,找出X坐標、Y坐標和時間;

--鼠標軌跡字符串分割
DECLARE @ID int,@PosSet VARCHAR(2000)
DECLARE @splitlen INT
DECLARE @split NVARCHAR(10)
DECLARE @temp VARCHAR(100)
DECLARE @PosSet_x INT
DECLARE @PosSet_y INT
DECLARE @PosTime DATETIME
SET @split = ']'
DECLARE @itemCur CURSOR
SET @itemCur = CURSOR FOR 
    SELECT ID,PosSet FROM [VisiteLog]
        WHERE PosSet <> ''

OPEN @itemCur
FETCH NEXT FROM @itemCur INTO @ID,@PosSet
WHILE @@FETCH_STATUS=0
BEGIN
    SET @splitlen=LEN(@split+'a')-2
    WHILE CHARINDEX(@split,@PosSet)>0
    BEGIN
        SET @Temp = LEFT(@PosSet,CHARINDEX(@split,@PosSet)-1)
        SET @Temp = replace(replace(@Temp,',[',''),'[','')
        SET @PosSet_x = dbo.Get_StrArrayStrOfIndex(@Temp,',',1)
        SET @PosSet_y = dbo.Get_StrArrayStrOfIndex(@Temp,',',2)
        SET @PosTime = dbo.Get_StrArrayStrOfIndex(@Temp,',',3)
        INSERT PosSetInfo VALUES(@ID,@PosSet_x,@PosSet_y,@PosTime)
        SET @PosSet=STUFF(@PosSet,1,CHARINDEX(@split,@PosSet)+@splitlen,'')
    END

    FETCH NEXT FROM @itemCur INTO @ID,@PosSet
END 

CLOSE @itemCur
DEALLOCATE @itemCur

執行完上面運用游標的SQL腳本,現在查看PosSetInfo表的數據,返回的結果如下圖所示:

--查看數據
SELECT * FROM [dbo].[PosSetInfo]

clip_image001[4]

(Figure6:分割后數據)

五.補充說明(Addon)

(一) 如果需要循環每個數據庫進行操作,你可以使用下面的SQL腳本:

--循環每個數據庫
EXEC sp_MSForEachDB 'USE [?];
SELECT * FROM sys.database_files'

wps_clip_image-20534

(Figure7:sp_MSForEachDB效果圖)

更多sp_MSForEachDB和sp_MSforeachtable的運用,可以參考:

SQL Server 游標運用:查看一個數據庫所有表大小信息(Sizes of All Tables in a Database)

SQL Server 游標運用:查看所有數據庫所有表大小信息(Sizes of All Tables in All Database)

 

(二) 步驟四中處理SQL代碼可能性能不是最優的,因為就函數Get_StrArrayStrOfIndex的調用就已經非常頻繁的,如果一個PosSet字段的值非常多,你可以考慮用一個表值函數返回一個表。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM