1

我计划通过将 Locations 表中的 locationID 提供给 User 表中的每个用户来规范化,而不是为共享同一位置的多个用户输入重复的用户位置,这样我就不必在 User 中重复输入 Country、State、City表,所以我节省了磁盘空间。(美国,康涅狄格州,伍德黑文)

在几个用户说第 12 个用户可能进入 USA、NY、Albany 之后,该条目被输入到 Locations Table 的第 12 行中。当用户输入他的位置信息(国家、州、城市)时,我需要在位置表中检查该记录是否存在,然后再输入新记录。问题是您无法索引 State 和 City 列,因为它与国家(阿富汗、阿拉巴马州、阿齐尔本、国家、州和城市分别不匹配)。

有没有一种有效的方式可以对国家和城市进行排序,使其与按字母顺序索引的国家名称保持一致(我希望阿富汗以 A 开头的国家和以 A 开头的城市以阿富汗国家作为第一行,依此类推假设阿富汗是国家列表中的第一个国家。

我相信即使具有单独的 Locations 表的规范化方法可以节省磁盘空间,搜索记录的时间,如果还没有在 Locations 表中插入,然后在用户表中插入 LocationsID 在时间方面成本更高。我的断言正确吗?

4

5 回答 5

4

这是数据库中规范化的一个典型缺陷:仅仅为了空间而规范化。

空间很便宜。

从函数依赖的角度考虑:元组 (Country, State, City) 应该是函数依赖,但你没有任何依赖它的信息,也没有它的组件(至少你没有告诉我们)。或者,您可能具有某些功能依赖关系,例如 State->Country,或 City -> Coutry,State(但您已经知道全局数据库并非如此)。

您同样可以将其作为单个属性“国家;州;城市”,它不会影响您的设计(从功能依赖的角度来看;从搜索数据的角度来看)。

换句话说,如果您有任何特定于元组(国家、州、城市)的信息,或者您希望在元组本身内强制执行功能依赖关系,则您可能希望对该表进行规范化。

如果你不这样做,那么不要仅仅为了空间而对其进行标准化。空间从来都不是标准化背后的主要动机(更新/插入/删除异常是主要原因)。

这么说吧。你会为了节省空间而规范一个人的名字和姓氏吗?

如果您仍然想这样做,那么不必担心索引如何对数据进行排序。这不应该是你的担心。您可以在 (Country, State, City) 上创建一个基于树的索引(默认设置),然后您可以搜索给定的国家,或国家/地区,或国家/地区,州,城市(您始终可以使用基于树的索引中的前缀)。您可以在具有任意属性组合的表上创建任意数量的索引。但这会占用空间,并且会减慢插入速度,但我怀疑无论如何您在该表中不会有很多。

我的建议,不要规范化这些数据。

--dmg

于 2013-05-20T17:48:35.457 回答
1

不确定“索引”是您的问题。如果我对您的理解正确,您将有 2 个表:

USERS
 - UserID
 - ....
 - LocationID


LOCATIONS
 - LocationID
 - City
 - State
 - Country

您可以预先填充“位置”,从类似这样的内容,或者在用户输入新位置时将新位置插入表中。就像是:

insert into Locations
values
(null, $city, $state, $country)
where not exists
(select * from locations 
  where city = $city 
  and country = $country 
  and state = $state) 

然后找到匹配相同条件的 locationID 插入到用户表中。

于 2013-05-20T17:41:57.203 回答
1

在大多数(几乎所有)情况下,规范化形式是最好的形式。在您的示例中,我建议您SELECT对城市、州、国家/地区的组合进行组合,并查看新值是否已经存在,如果不存在,则在添加用户之前创建行。这在插入时间上的成本稍高(因为您将有两个查询),但会减少您的磁盘使用和选择时间。

不过,您应该在城市、州和国家表上放置一个索引。

请注意,这样您将在同一个地方有重复的条目(因为Munich, Bavaria, Germany与 相同München, Bayern, Deutschland,但您将没有机会知道。

于 2013-05-20T17:37:12.570 回答
0

我计划通过将 Locations 表中的 locationID 提供给 User 表中的每个用户来规范化,而不是为共享同一位置的多个用户输入重复的用户位置,这样我就不必在 User 中重复输入 Country、State、City表,所以我节省了磁盘空间。(美国,康涅狄格州,伍德黑文)

您所描述的不是标准化。

如果您尝试对原始表进行规范化,您将在原始表中识别出函数依赖、多值依赖或连接依赖,然后通过投影删除该依赖。

但你没有那样做。您只需选择三个密切相关的列,并用重复的 ID 号替换重复的文本。这不是正常化。

鉴于您告诉我们的很少,唯一可能的依赖是 {city, state->country}。该依赖项是否成立是依赖于应用程序的,但它不在全球范围内成立。如果我没记错的话,几年前在一些阿拉伯国家和一些拉丁美洲国家有重复。

另一方面,如果您想要一个可用于提高数据完整性的附加表,并且该应用程序代码可用于向用户呈现排序的可能性,那么这非常简单。但这与数据完整性有关,与规范化无关。

您可以像这样存储国家、州和城市。我不建议您完全这样;这是一个例子。在实践中,您应该认真考虑使用 ISO 国家/地区代码。

.

create table countries (
  country_name varchar(35) not null,
  primary key (country_name)
);

create table states (
  country_name varchar(35) not null,
  state_name varchar(35) not null,
  primary key (country_name, state_name),
  foreign key (country_name) 
    references countries (country_name)
);

create table cities (
  country_name varchar(35) not null,
  state_name varchar(35) not null,
  city_name varchar(35) not null,
  primary key (country_name, state_name, city_name),
  foreign key (country_name, state_name)
    references states (country_name, state_name)
);

将表中的外键引用设置为表“城市”。

于 2013-05-20T19:43:11.090 回答
0

您也可以尝试不使用 ajax 调用和数据库管理:

<html>
<head> 
<title>Demo by kishan Radadiya</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
  <script type="text/javascript">
    $(document).ready(function(){
        // Countries
        var country_arr = new Array("Select Country","AUSTRALIA","INDIA","NEW ZEALAND","USA","UAE","MAURITIUS");

        $.each(country_arr, function (i, item) {
            $('#country').append($('<option>', {
                value: i,
                text : item,
            }, '</option>' ));
        });

        // States
        var s_a = new Array();
        s_a[0]="Select State";
        s_a[1]="Select State|QUEENSLAND|VICTORIA";
        s_a[2]="Select State|ANDHRAPRADESH|KARNATAKA|TAMILNADU|DELHI|GOA|W-BENGAL|GUJARAT|MADHYAPRADESH|MAHARASHTRA|RAJASTHAN";
        s_a[3]="Select State|AUCKLAND";
        s_a[4]="Select State|NEWJERSEY|ILLINOIS";
        s_a[5]="Select State|DUBAI";
        s_a[6]="Select State|MAURITIUS";

        // Cities
        var c_a = new Array();
        c_a['QUEENSLAND']="BRISBANE";
        c_a['VICTORIA']="MELBOURNE";
        c_a['ANDHRAPRADESH']="HYDERABAD";
        c_a['KARNATAKA']="BANGLORE";
        c_a['TAMILNADU']="CHENNAI";
        c_a['DELHI']="DELHI";
        c_a['GOA']="GOA";
        c_a['W-BENGAL']="KOLKATA";
        c_a['GUJARAT']="AHMEDABAD1|AHMEDABAD2|AHMEDABAD3|BARODA|BHAVNAGAR|MEHSANA|RAJKOT|SURAT|UNA";
        c_a['MADHYAPRADESH']="INDORE";
        c_a['MAHARASHTRA']="MUMBAI|PUNE";
        c_a['RAJASTHAN']="ABU";
        c_a['AUCKLAND']="AUCKLAND";
        c_a['NEWJERSEY']="EDISON";
        c_a['ILLINOIS']="CHICAGO";
        c_a['MAURITIUS']="MAURITIUS";
        c_a['DUBAI']="DUBAI";


        $('#country').change(function(){
            var c = $(this).val();
            var state_arr = s_a[c].split("|");
            $('#state').empty();
            $('#city').empty();
            if(c==0){
                $('#state').append($('<option>', {
                    value: '0',
                    text: 'Select State',
                }, '</option>'));
            }else {
                $.each(state_arr, function (i, item_state) {
                    $('#state').append($('<option>', {
                        value: item_state,
                        text: item_state,
                    }, '</option>'));
                });
            }
            $('#city').append($('<option>', {
                value: '0',
                text: 'Select City',
            }, '</option>'));
        });

        $('#state').change(function(){
            var s = $(this).val();
            if(s=='Select State'){
                $('#city').empty();
                $('#city').append($('<option>', {
                    value: '0',
                    text: 'Select City',
                }, '</option>'));
            }
            var city_arr = c_a[s].split("|");
            $('#city').empty();

            $.each(city_arr, function (j, item_city) {
                $('#city').append($('<option>', {
                    value: item_city,
                    text: item_city,
                }, '</option>'));
            });


        });
    });
</script>
</head>
<body>
<select name="country" id="country"></select> <br>
<select name="state" id="state"></select> <br>
<select name="city" id="city"></select>
</body>
</html>
于 2016-08-18T16:48:08.457 回答