惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Cyberwarzone
Cyberwarzone
The GitHub Blog
The GitHub Blog
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
小众软件
小众软件
Recent Announcements
Recent Announcements
博客园 - 三生石上(FineUI控件)
Security Archives - TechRepublic
Security Archives - TechRepublic
W
WeLiveSecurity
Cloudbric
Cloudbric
博客园 - 司徒正美
美团技术团队
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
PCI Perspectives
PCI Perspectives
宝玉的分享
宝玉的分享
H
Help Net Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Google DeepMind News
Google DeepMind News
Help Net Security
Help Net Security
Last Week in AI
Last Week in AI
S
Schneier on Security
N
News | PayPal Newsroom
B
Blog RSS Feed
L
LINUX DO - 最新话题
T
Troy Hunt's Blog
S
Secure Thoughts
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
L
Lohrmann on Cybersecurity
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Tenable Blog
S
Securelist
L
LangChain Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
I
InfoQ
H
Heimdal Security Blog
Cisco Talos Blog
Cisco Talos Blog
F
Full Disclosure
Y
Y Combinator Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
K
Kaspersky official blog
T
Tailwind CSS Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
阮一峰的网络日志
阮一峰的网络日志
C
Cisco Blogs

博客园 - 水如烟(LzmTW)

.NET的变量在代码集中是不安全的 HOW TO:获取硬盘物理序列号(VB.NET) 一个创建快捷方式类 一个简单的CodeAccessPermission生成器 认识一下Attribute HOW TO:端口打印(比较粗糙) 标记法定义和创建数据库(四) 标记法定义和创建数据库 Sql2005数据类型与Framework类型的对应关系 HOW TO:重启程序(WinForm) HOW TO:设置默认打印机 HOW TO:避免“将COM对象与其基础RCW分开后不能再使用该对象”错误 HOW TO:控制是否允许用户退出ExcelApplication的Workbook 树和自联表(五) 树和自联表(六) 树和自联表(四) 树和自联表(一) 行政区划数据数据库的设计(脚本) 行政区划数据数据库的设计(七)
行政区划数据数据库的设计(六)
水如烟(LzmTW) · 2006-09-20 · via 博客园 - 水如烟(LzmTW)

Author水如烟

行政区划数据数据库的设计()

在上文中,实现了网上数据导入数据库。

不过上文中全部数据导入的过程,有一个环节是忽略了的,就是没有检查是不是原有的区划码全部有效,有没有中止“Current”影射的。我是想当然的认为,后期版本肯定全部继承前期版本的。事实可能这样,但设计和操作逻辑不允许这样的想当然。当然,现在知道了,以后再补漏也不为迟。

这篇说附属表,关于行政区类型。

根据规约的说明,行政区分为三级,分别是省、省直辖市和地区州盟、市地辖区和县旗及省直辖县级市。

按我的理解,分别建两个表,一是行政区级别,二是行政区类型。

USE [RegionalCodeWorks]
GO
/****** 对象:  Table [Base].[行政区级别]    脚本日期: 09/20/2006 22:44:35 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [Base].[行政区级别](
    
[级别ID] [smallint] IDENTITY(0,1NOT NULL,
    
[级别] [nchar](10) COLLATE Chinese_PRC_CI_AS NOT NULL,
 
CONSTRAINT [PK_行政区级别] PRIMARY KEY CLUSTERED 
(
    
[级别ID] ASC
)
WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFFON [PRIMARY],
 
CONSTRAINT [IX_行政区级别] UNIQUE NONCLUSTERED 
(
    
[级别] ASC
)
WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFFON [PRIMARY]
ON [PRIMARY]

USE [RegionalCodeWorks]
GO
/****** 对象:  Table [Base].[行政区类型]    脚本日期: 09/20/2006 22:45:34 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [Base].[行政区类型](
    
[类型ID] [smallint] IDENTITY(0,1NOT NULL,
    
[类型] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
    
[级别ID] [smallint] NOT NULL,
 
CONSTRAINT [PK_行政区类型] PRIMARY KEY CLUSTERED 
(
    
[类型ID] ASC
)
WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFFON [PRIMARY],
 
CONSTRAINT [IX_行政区类型] UNIQUE NONCLUSTERED 
(
    
[类型] ASC
)
WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFFON [PRIMARY]
ON [PRIMARY]GO
ALTER TABLE [Base].[行政区类型]  WITH CHECK ADD  CONSTRAINT [FK_行政区类型_行政区级别] FOREIGN KEY([级别ID])
REFERENCES [Base].[行政区级别] ([级别ID])
GO
ALTER TABLE [Base].[行政区类型] CHECK CONSTRAINT [FK_行政区类型_行政区级别]

至于哪个区划码应属哪种类型,在上图中已经标示了出来,本来觉得是固定的,只是对比数据后,发现并非如此。因此另建一个表,为行政区类型情况,归属于“稳定数据日期”类。

USE [RegionalCodeWorks]
GO
/****** 对象:  Table [Edit].[行政区类型情况]    脚本日期: 09/20/2006 22:46:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [Edit].[行政区类型情况](
    
[ID] [smallint] IDENTITY(1,1NOT NULL,
    
[类型ID] [smallint] NOT NULL,
    
[范围] [nvarchar](max) COLLATE Chinese_PRC_CI_AS NOT NULL,
    
[截止日期] [Base].[RegionalDate] NOT NULL,
    
[起始日期] [Base].[RegionalDate] NOT NULL,
    
[备注] [nvarchar](max) COLLATE Chinese_PRC_CI_AS NULL,
 
CONSTRAINT [PK_行政区类型情况] PRIMARY KEY CLUSTERED 
(
    
[类型ID] ASC,
    
[截止日期] ASC
)
WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFFON [PRIMARY]
ON [PRIMARY]GO
EXEC sys.sp_bindefault @defname=N'[Base].[RegionalDateDefault]'@objname=N'[Edit].[行政区类型情况].[截止日期]' , @futureonly='futureonly'
GO
EXEC sys.sp_bindefault @defname=N'[Base].[RegionalDateDefault]'@objname=N'[Edit].[行政区类型情况].[起始日期]' , @futureonly='futureonly'
GO
ALTER TABLE [Edit].[行政区类型情况]  WITH CHECK ADD  CONSTRAINT [FK_行政区类型情况_行政区类型] FOREIGN KEY([类型ID])
REFERENCES [Base].[行政区类型] ([类型ID])
GO
ALTER TABLE [Edit].[行政区类型情况] CHECK CONSTRAINT [FK_行政区类型情况_行政区类型]
GO
ALTER TABLE [Edit].[行政区类型情况]  WITH CHECK ADD  CONSTRAINT [CK_行政区类型情况] CHECK  (([截止日期]>=[起始日期]))
GO
ALTER TABLE [Edit].[行政区类型情况] CHECK CONSTRAINT [CK_行政区类型情况]

 

行政区级别和行政区类型属于基础表,建好表后就要初始化,增加数据。

考虑到图示给出的各类型范畴不一定全适用于所有数据,因此级别表中我加了“未知”项,同时类型表中也加了“未知”项。在查询数据时,如果有例外,它的类型显示为“未知”,这会提醒我们重新审查这些定义条件。

USE [RegionalCodeWorks]
GOINSERT INTO [Base].[行政区级别]([级别]VALUES (N'未知')
INSERT INTO [Base].[行政区级别]([级别]VALUES (N'一级')
INSERT INTO [Base].[行政区级别]([级别]VALUES (N'二级')
INSERT INTO [Base].[行政区级别]([级别]VALUES (N'三级')INSERT INTO [RegionalCodeWorks].[Base].[行政区类型]([类型] ,[级别ID]VALUES (N'未知' ,0)
INSERT INTO [RegionalCodeWorks].[Base].[行政区类型]([类型] ,[级别ID]VALUES (N'' ,1)
INSERT INTO [RegionalCodeWorks].[Base].[行政区类型]([类型] ,[级别ID]VALUES (N'省直辖市' ,2)
INSERT INTO [RegionalCodeWorks].[Base].[行政区类型]([类型] ,[级别ID]VALUES (N'地区州盟' ,2)
INSERT INTO [RegionalCodeWorks].[Base].[行政区类型]([类型] ,[级别ID]VALUES (N'市地辖区' ,3)
INSERT INTO [RegionalCodeWorks].[Base].[行政区类型]([类型] ,[级别ID]VALUES (N'县旗' ,3)
INSERT INTO [RegionalCodeWorks].[Base].[行政区类型]([类型] ,[级别ID]VALUES (N'省直辖县级市' ,3)

 表[Edit].行政区类型情况的数据是,

USE [RegionalCodeWorks]
GOINSERT INTO [Edit].[行政区类型情况]
           (
[类型ID]
           ,
[范围]
           ,
[起始日期]
           ,
[备注])
     
VALUES
           (
1
           ,N
'二级 = N''00'' AND 三级 = N''00'''
           ,N
'20000101'
           ,N
'')INSERT INTO [Edit].[行政区类型情况]
           (
[类型ID]
           ,
[范围]
           ,
[起始日期]
           ,
[备注])
     
VALUES
           (
2
           ,N
'(二级 BETWEEN N''01'' AND N''20'' OR 二级 BETWEEN N''51'' AND N''99'' ) AND 三级 = N''00'' '
           ,N
'20000101'
           ,N
'省直辖市')INSERT INTO [Edit].[行政区类型情况]
           (
[类型ID]
           ,
[范围]
           ,
[起始日期]
           ,
[备注])
     
VALUES
           (
3
           ,N
'二级 BETWEEN N''21'' AND N''50'' AND 三级 = N''00'' '
           ,N
'20000101'
           ,N
'州盟')INSERT INTO [Edit].[行政区类型情况]
           (
[类型ID]
           ,
[范围]
           ,
[起始日期]
           ,
[备注])
     
VALUES
           (
4
           ,N
'三级 BETWEEN N''01'' AND N''20''  '
           ,N
'20000101'
           ,N
'市地辖区')INSERT INTO [Edit].[行政区类型情况]
           (
[类型ID]
           ,
[范围]
           ,
[起始日期]
           ,
[备注])
     
VALUES
           (
5
           ,N
'三级 BETWEEN N''21'' AND N''80'' '
           ,N
'20000101'
           ,N
'县旗')INSERT INTO [Edit].[行政区类型情况]
           (
[类型ID]
           ,
[范围]
           ,
[起始日期]
           ,
[备注])
     
VALUES
           (
6
           ,N
'三级 BETWEEN N''81'' AND N''99'' '
           ,N
'20000101'
           ,N
'省直辖县级市')

 如果自己理解错了,可以随时改正。

现在定义两个函数和一个存储(感冒了,话不多说也是好事吧)

USE [RegionalCodeWorks]
GO
/****** 对象:  UserDefinedFunction [FUNCTION].[行政区类型情况]    脚本日期: 09/20/2006 23:08:49 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [FUNCTION].[行政区类型情况] 
(    
     
@当前时间    [Base].[RegionalDate]    = N'Current'
)
RETURNS TABLE 
AS
RETURN 
(
    
SELECT a.*
    
FROM [Edit].[行政区类型情况] a
    
RIGHT OUTER JOIN
    (
        
SELECT    [类型ID]
                ,
MIN(DISTINCT [截止日期])AS 查询时间
        
FROM    [Edit].[行政区类型情况]
        
WHERE   @当前时间 BETWEEN [起始日期] AND [截止日期] 
        
GROUP BY[类型ID]
    ) b
    
ON a.类型ID = b.类型ID AND a.截止日期 = b.查询时间
)

USE [RegionalCodeWorks]
GO
/****** 对象:  UserDefinedFunction [Action].[行政区情况]    脚本日期: 09/20/2006 23:10:00 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [Action].[行政区情况] 
(    
     
@当前时间    [Base].[RegionalDate]    = N'Current'
)
RETURNS TABLE 
AS
RETURN 
(
    
SELECT     a.区划码ID
            ,a.区划码
            ,b.名称
            ,a.一级
            ,a.二级
            ,a.三级
            ,b.截止日期
            ,b.起始日期
    
FROM [Base].[区划码] a
    
INNER JOIN [FUNCTION].[区划码情况](@当前时间) b
    
ON a.区划码ID = b.区划码ID 
)

存储过程,取区划码对应的类型ID.

USE [RegionalCodeWorks]
GO
/****** 对象:  StoredProcedure [Action].[区划码类型情况]    脚本日期: 09/20/2006 23:11:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
--
 Author:        LzmTW
--
 Create date: 20060920
--
 Description:    取区划码的类型ID
--
 =============================================
CREATE PROCEDURE [Action].[区划码类型情况] 
     
@当前时间    [Base].[RegionalDate]    = N'Current'
AS
BEGIN
    
--通过临时表来处理数据

    
IF EXISTS
    (
        
SELECT 1 FROM tempdb.dbo.sysobjects
        
WHERE [name] =  N'##区划码类型情况'  AND xtype=N'U'
    )
        
DROP TABLE ##区划码类型情况CREATE TABLE ##区划码类型情况 
        (
             区划码ID    
smallint
            ,类型ID    
smallint
        )
--取类型定义为未知的ID
    DECLARE @未知ID smallintSELECT    @未知ID = 类型ID
    
FROM    [Base].行政区类型
    
WHERE    类型 = N'未知'--所有区划码的类型初始化为未知
    INSERT INTO ##区划码类型情况
    
SELECT   区划码ID
            ,
@未知ID as 类型ID
    
FROM [FUNCTION].区划码情况(@当前时间)--以下处理的正确性取决于类型定义不存在交集!!
    DECLARE  @Building    nvarchar(MAX)
            ,
@SQL        nvarchar(MAX)
            ,
@类型ID    smallint
            ,
@范围        nvarchar(MAX)SET @Building = N'
        UPDATE ##区划码类型情况
        SET 类型ID = b.类型ID
        FROM ##区划码类型情况 a
        INNER JOIN 
        (
            SELECT   区划码ID
                    ,{类型ID} AS 类型ID
            FROM    [Action].[行政区情况](
''' + @当前时间 + N''')
            WHERE    {WHERE} 
        ) b
        ON a.区划码ID = b.区划码ID 
'--遍历类型定义表更新区划码类型
    DECLARE 行政区类型_Cursor CURSOR FOR
    
SELECT   类型ID
            ,范围
    
FROM  [FUNCTION].行政区类型情况(@当前时间)
    
OPEN 行政区类型_CursorFETCH NEXT 
    
FROM 行政区类型_Cursor 
    
INTO @类型ID@范围WHILE (@@fetch_status<>-1)
    
BEGINIF (@@fetch_status<>-2)
        
BEGIN
                        
            
SET @SQL = REPLACE(@Building, N'{类型ID}'@类型ID)
            
SET @SQL = REPLACE(@SQL, N'{WHERE}'@范围)EXEC (@SQL)FETCH NEXT 
            
FROM 行政区类型_Cursor 
            
INTO @类型ID@范围
        
ENDENDCLOSE 行政区类型_Cursor
    
DEALLOCATE 行政区类型_Cursor    SELECT * 
    
FROM ##区划码类型情况
END

最后建个存储过程测试一下:

USE [RegionalCodeWorks]
GO
/****** 对象:  StoredProcedure [Program].[Test类型情况]    脚本日期: 09/20/2006 23:12:39 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
--
 Author:        <Author,,Name>
--
 Create date: <Create Date,,>
--
 Description:    <Description,,>
--
 =============================================
CREATE PROCEDURE [Program].[Test类型情况]
     
@当前时间    [Base].[RegionalDate]    = N'Current'
AS
BEGIN
    
SET NOCOUNT ON;DECLARE @类型情况 TABLE
    (
         区划码ID    
smallint
        ,类型ID        
smallint
    )
INSERT INTO @类型情况
    
EXEC [Action].[区划码类型情况] @当前时间SELECT    TOP 100 PERCENT
             d.区划码ID
            ,d.区划码
            ,d.名称
            ,a.类型
            ,b.级别
            ,d.一级
            ,d.二级
            ,d.三级
            ,d.截止日期
            ,d.起始日期
            ,a.类型ID
            ,b.级别ID
    
FROM    Base.行政区类型 AS a 
    
INNER JOIN Base.行政区级别 AS b 
    
ON a.级别ID = b.级别ID 
    
INNER JOIN @类型情况 AS c 
    
ON a.类型ID = c.类型ID
    
INNER JOIN [Action].行政区情况(@当前时间AS d 
    
ON d.区划码ID = c.区划码ID 
    
ORDER BY d.一级, d.二级, d.三级
END

 下一篇数据库的最后一篇,取全名。