昨天,一同事發過來的一道數據庫題目,就是哪一種經典的父子級 ID 在同一數據庫表中設計類型。須要在原表中添加一個字段,同時,將該節點的父子級詳細信息插入到原表新增的一字段中,具體效果以下圖。數據庫
AreaCode 、AreaName、ParentCode (原表三字段). Content __新增字段,更新該 AreaCode 下全部父級菜單信息至新增至原表的 Content 字段下面,用紅線框起來(意思應該講明白了吧.)緩存
AreaCode:地區 ID AreaName:地區介紹 ParentCode:父級 AreaCode (Content---將該 AreaCode 下的全部父級 AreaName 拼成 相似:越城區,紹興市,浙江省 字符串插入)ide
更新前:函數
更新後:性能
在項目中,相對於此種內容,通常會存儲在內存中,做爲緩存使用,避免頻繁鏈接數據庫,帶來的性能問題。spa
代碼就不上了,簡單的遞歸便可實現。設計
1 先從數據庫將該表全部內容取出來,緩存起來。(該表差很少 3000 左右條數據)code
2 再寫個遞歸函數,根據每次傳入的 AreaCode(第一步已緩存數據庫取出來的整表集合 可轉成 Dictionary<int,AreaRegion> 類型),獲取其 ParentCode 值,只要 ParentCode 不爲 0(即不爲頂級結點,ParentCode 爲頂級結點),那麼,繼續調用該函數,傳入本次查詢實體的 ParentCode 信息。blog
3 在代碼很方便查出父結點全部信息,再 Update 至數據庫便可。遞歸
感謝 清海揚波 grayboy 徹底能夠經過公用表表達式完成
Code 以下:
1 with cte(areacode,areaName,content) as 2 ( 3 --- 查詢 ParentCode 爲 0 (ParentCode 爲 0 的爲頂級菜單) 4 select areacode,areaName,cast(areaName as varchar(50)) AS content 5 from [AreaRegion] where parentcode=0 6 union all 7 -- 再進行遞歸查詢 8 select a.areacode,a.areaName,cast(a.content+','+b.areaName as varchar(50) AS content
9 from [AreaRegion] a inner join cte b on a.parentcode=b.areacode )
10 select * from cte
--- 樓主當初想法(我想複雜了 SB 了 )
2 遊標每次取得一條記錄的 AreaCode ,再經過該 AreaCode 查出其全部父級表(包括自身)信息,最後,將查詢出的該表某字段拼成字符串,
插入表變量中(兩字段分別爲:AreaCode、Content)。
3 最後,將定義的表變量與原表經過 INNER JOIN(表變量中插入了 AreaCode 字段),進行聯表更新。
更新腳本具體以下:
1 USE JKCRM 2 GO 3 --定義遊標 4 DECLARE updateCursor CURSOR SCROLL FOR 5 SELECT A.AreaCode FROM DBO.AreaRegion A 6 --打開遊標 7 OPEN updateCursor 8 --定義變量 存儲依次獲取遊標值 9 DECLARE @aID NVARCHAR(30)='' 10 ---定義變量 存儲父結點具體信息 11 DECLARE @pStr NVARCHAR(300)=''; 12 --定義表變量 存儲兩字段 AreaCode Content ( Content :爲該字段全部父級菜單信息) 13 DECLARE @TempTable TABLE 14 ( 15 AreaCode INT PRIMARY KEY, 16 Content NVARCHAR(3000) 17 ) 18 --首次獲取遊標第一個值 插入變量 @AID 19 FETCH FIRST FROM updateCursor INTO @AID 20 21 WHILE(@@FETCH_STATUS=0) 22 BEGIN 23 --PRINT(@AID) ; 24 ---經過傳入的 @AID ,查詢其全部父級菜單信息 25 WITH TB AS 26 ( 27 ---遞歸查詢父子菜單信息 公用表表達式遞歸查詢 28 SELECT A.*,0 AS LEVEL FROM JKCRM.DBO.AreaRegion A 29 WHERE A.AreaCode=@AID 30 UNION ALL 31 SELECT B.* ,LEVEL+1 AS LEVEL FROM TB A INNER JOIN JKCRM.DBO.AreaRegion B 32 ON A.ParentCode=B.AreaCode 33 ) 34 ---再將查詢的表信息 拼接成字符串 此處 即採用 SELECT 循環查詢 35 SELECT @pStr=@pStr+ CASE 36 WHEN @pStr='' THEN TB.AreaName ELSE ','+TB.AreaName END 37 FROM TB ORDER BY TB.LEVEL ASC 38 -- PRINT(@pSTR) 39 --插入表變量 40 INSERT INTO @TempTable SELECT @aID,@pStr 41 ---將這次經過 AreaCode 獲取的該節點 @pStr 置空 42 SET @pStr='' 43 FETCH NEXT FROM updateCursor INTO @AID 44 END 45 46 --SELECT B.AreaCode,B.AreaName,B.ParentCode,A.Content,A.AreaCode 47 --FROM @TempTable A RIGHT JOIN DBO.AreaRegion B ON A.AreaCode=B.AreaCode ORDER BY B.AreaCode 48 49 ---此處 便可進行 UPDATE 更新操做 50 UPDATE A SET A.Content=B.Content FROM DBO.AreaRegion A 51 INNER JOIN @TempTable B ON A.AreaCode=B.AreaCode 52 53 --關閉釋放遊標 54 CLOSE updateCursor 55 DEALLOCATE updateCursor
原表部分腳本 SQL
1 /* 2 Navicat SQL Server Data Transfer 3 4 Source Server : SQL 5 Source Server Version : 120000 6 Source Host : .:1433 7 Source Database : JKCRM 8 Source Schema : dbo 9 10 Target Server Type : SQL Server 11 Target Server Version : 120000 12 File Encoding : 65001 13 14 Date: 2015-06-12 11:20:40 15 */ 16 17 18 -- ---------------------------- 19 -- Table structure for AreaRegion 20 -- ---------------------------- 21 DROP TABLE [dbo].[AreaRegion] 22 GO 23 CREATE TABLE [dbo].[AreaRegion] ( 24 [AreaCode] varchar(10) NOT NULL , 25 [AreaName] varchar(50) NULL , 26 [ParentCode] varchar(10) NULL , 27 [Content] nvarchar(200) NULL 28 ) 29 30 31 GO 32 33 -- ---------------------------- 34 -- Records of AreaRegion 35 -- ---------------------------- 36 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'110000', N'北京市', N'0', null) 37 GO 38 GO 39 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'110100', N'東城區', N'110000', null) 40 GO 41 GO 42 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'110200', N'西城區', N'110000', null) 43 GO 44 GO 45 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'110300', N'崇文區', N'110000', null) 46 GO 47 GO 48 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'110400', N'宣武區', N'110000', null) 49 GO 50 GO 51 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'110500', N'朝陽區', N'110000', null) 52 GO 53 GO 54 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'110600', N'豐臺區', N'110000', null) 55 GO 56 GO 57 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'110700', N'石景山區', N'110000', null) 58 GO 59 GO 60 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'110800', N'海淀區', N'110000', null) 61 GO 62 GO 63 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'110900', N'門頭溝區', N'110000', null) 64 GO 65 GO 66 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'111000', N'房山區', N'110000', null) 67 GO 68 GO 69 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'111100', N'通州區', N'110000', null) 70 GO 71 GO 72 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'111200', N'順義區', N'110000', null) 73 GO 74 GO 75 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'111300', N'昌平區', N'110000', null) 76 GO 77 GO 78 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'111400', N'大興區', N'110000', null) 79 GO 80 GO 81 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'111500', N'懷柔區', N'110000', null) 82 GO 83 GO 84 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'111600', N'平谷區', N'110000', null) 85 GO 86 GO 87 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'111700', N'密雲縣', N'110000', null) 88 GO 89 GO 90 INSERT INTO [dbo].[AreaRegion] ([AreaCode], [AreaName], [ParentCode], [Content]) VALUES (N'111800', N'延慶縣', N'110000', null)