Chinaunix首页 | 论坛 | 博客
  • 博客访问: 18670525
  • 博文数量: 7460
  • 博客积分: 10434
  • 博客等级: 上将
  • 技术积分: 78178
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-02 22:54
文章分类

全部博文(7460)

文章存档

2011年(1)

2009年(669)

2008年(6790)

分类: 数据库开发技术

2008-05-28 15:01:22

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]
GO

INSERT 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]
GO

INSERT 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 smallint

    
SELECT    @未知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 行政区类型_Cursor

    
FETCH NEXT 
    
FROM 行政区类型_Cursor 
    
INTO @类型ID@范围

    
WHILE (@@fetch_status<>-1)
    
BEGIN

        
IF (@@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@范围
        
END

    
END

    
CLOSE 行政区类型_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:        
--
 Create date: 
--
 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

 

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

阅读(984) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~