精华内容
下载资源
问答
  • 说的数据库设计,大家都知道数据库设计三范式与逆范式。 简单的回顾一下。 1.第一范式(确保每列保持原子性) 2.第二范式(确保中的每列都和主键相关) 3.第三范式(确保每列都和主键列直接相关,而不是间接相关)...

    说的数据库设计,大家都知道数据库设计三范式与逆范式。

    简单的回顾一下。

    1.第一范式(确保每列保持原子性)

    2.第二范式(确保表中的每列都和主键相关)

    3.第三范式(确保每列都和主键列直接相关,而不是间接相关)

    逆范式:
    就是有的时候拆分的太细致了, 让连表产生了很多. 这个时间, 如果有一个字段经常被两个地方使用到, 我们就会把这个字段放在第二个表字段里面。


    除了上面说的这几个,本人还总结了一个技巧。

    就是要数据库字段设计的时候,让某个字段具有高可用性(暂且这么叫吧)。充分挖掘该字段的第二层含义。

    第一个例子:

    is_super这个字段 ,通常用的 管理员表中,用于区分当前用户是否是超级管理员,

    通常的做法是设置成 布尔类型或者 tinyint,用0或1表示 是不是超管。

    但是如果你把该字段设计成int,把他当成一个pid使用的话,是不是 同时还包含了 如果非管理员,能对该管理员进行溯源。

    比如超管的id是5,普通用户的is_super是5的话,就代表了该用户 是非超管,同时是由id=5 的超管创建的用户。

     

    第二个例子:

    vip字段的设计,这个字段 一般用于标识 当前用户是否是vip用户,0和1两种状态。

    但是细想一下,如果 把字段的值 拓展成 0和 1、2、3、4....两种情况的话,是不是 就可以代表两个含义?

    第一种,当前用户是不是vip用户,第二种,当前用户 的vip级别是多少。

     

    第三个例子:

    is_delete 字段 ,这个字段 通常表示 是否被软删除,分为0和1的两种情况。

    但是细想一下,如果把该字段设计成int(10),当大于0的时候,代表删除,把删除时间的时间戳代替1。

    是不是 同时给该字段赋予了第二层含义,就是 不仅知道该字段已经被软删除了,同时知道是什么时间删除的。

     

    所以在设计一个布尔类型的字段的时候,转动一个脑筋,挖掘布尔类型字段更深一层次的含义。

    谢谢浏览。

     

     

     

     

     

    展开全文
  • MySQL数据库四种数据类型:布尔类型、微整型、枚举类型和集合类型,都逐一分析这四种数据类型的特性,以及针对每种数据类型做相应的深入分析和案例测试,挖掘出MySQL手册没有详细写清楚的部分,相关技术文章可以考虑...

    【导读

    MySQL数据库四种数据类型:布尔类型、微整型、枚举类型和集合类型,都逐一分析这四种数据类型的特性,以及针对每种数据类型做相应的深入分析和案例测试,挖掘出MySQL手册没有详细写清楚的部分,相关技术文章可以考虑从数据类型系列第一篇文章MySQL数据库数据类型之ENUM、SET、BOOL/BOOLEAN、TINYINT特性介绍开始阅读。

    本文内容属于基于在此之前分享的6篇关于四种数据类型的文章之上,我们结合实际的业务场景和生产环境维护成本等多个角度进行分析,阐述什么样的业务场景,适合使用布尔类型、枚举类型和集合类型?使用这三种数据类型之后,又回给我们带来哪些麻烦?如何规避这三种数据类型带来的弊端等问题,将会逐一解答。

    (1).     布尔类型

    MySQL数据库之数据类型BOOL/BOOLEAN与TINYINT测试总结一文的测试过程和结论,非常清晰地告诉我们:MySQL数据库的布尔类型BOOL或称布尔类型BOOLEAN,等同于微整型TINYINT(1)。MySQL数据库数据类型分类中确实存在布尔类型,但是MySQL数据库并没有真正实现布尔类型,而是借助微整型的方式实现,并且创建数据库表结构的时候,即使字段定义属性设置为布尔类型BOOL或布尔类型BOOLEAN,都会被默认改写成TINYINT(1)。

    建议:

    MySQL数据库产品没有真正实现对布尔类型的支持,建议大家不要使用MySQL布尔类型BOOL或布尔类型BOOLEAN,而是使用数据库类型微整型TINYINT替代。

    (2).     枚举类型ENUM

    对枚举类型字段存储数据的数据测试案例分享和总结文章为MySQL数据库数据类型之枚举类型ENUM数据测试总结,对枚举类型字段进行DDL变更操作支持的案例分享和总结文章为MySQL数据库之枚举数据类型ENUM的DDL变更测试,通过详尽的测试对比过程,对MySQL枚举类型的特点非常清晰,我们再简要综合地回顾枚举类型的优缺点:

    l  优点

    1)         MySQL枚举类型的枚举元素允许最大65535个,基本够绝大多数业务场景使用;

    2)         引入枚举类型数据存储,有利于缩减数据库存储数据的容量,尤其能达到减少数据库瓶颈最大的物理IO,逻辑IO也能减小,提高主机的处理能力;

    3)         引入枚举类型数据存储,有利于简化工程师的代码复杂度、工作量,增加代码的可读性和可维护性;

    4)         可以通过枚举类型元素值访问数据,也可以根据枚举类型元素编号进行访问数据;

    l  缺点

    1)         MySQL数据库枚举类型的引入,可能给软件程序的版本发布,存在遗忘数据库结构变更的隐患;

    2)         MySQL数据库枚举类型字段的元素增加,必须以尾部追加的方式,否则影响数据库提供数据服务;

    3)         枚举类型字段不再需要的元素,也不能进行删除,否则影响数据库提供数据服务;

    4)         MySQL数据库枚举类型的字段定义属性元素值,不能随意调整其顺序,否则影响数据库提供数据服务;

    建议:

    MySQL数据库枚举类型是一种有应用场景广泛的数据类型,若是抛开网站程序或软件版本发布,可能会导致开发工程师与数据库维护人员之间没有配合好的问题,非常推荐大家把枚举类型引入到生产环境的数据库应用中,对企业而言也可以起到节省人力、物理等成本。建议大家使用枚举类型的时候,尽量把可能需要用到的枚举元素,都写到MySQL数据库表字段的定义属性中,减少出现漏做DDL变更的故障。

    (3).     集合类型SET

    MySQL数据库数据类型之集合类型SET数据测试总结MySQL数据库之集合类型SET的DDL变更测试总结文章,有完整的测试过程,充分总结MySQL数据库集合类型的优缺点,我们再简要地回顾集合类型的优缺点。

    l  优点

    1)         数据库的数据存储容量相应缩小,利于减少数据操纵的逻辑IO和物理IO;

    2)         集合类型的数据读取方便,可根据字符串值,也可以根据字符串集合的顺序编号;

    3)         集合类型字段的定义属性维护与其他数据类型类似,并不特殊化;

    4)         开发工程师,不需要借助额外的集合元素编码表或程序中使用编号替代集合的字符串元素,达到减少开发成本、提高代码的可读性和可维护性;

    l  缺点

    1)         集合类型字段的集合元素限制最大为64个;

    2)         集合类型字段的定义属性的集合元素,删除导致锁表而影响数据服务提供;

    3)         集合类型字段的定义属性的集合元素增加,只能以尾部追加的方式,若是此特性没有掌握,则会导致数据服务提供受影响;

    MySQL数据库支持集合类型,对解决一些特殊的业务场景提供了非常好的解决方案,经典应用场景案例:

    人才招聘网站的用户,设置工作意向城市一项,则往往会选择1-3个城市,甚至更多城市,采用集合类型字段作为数据存储结果的话,将可以大量简化程序复杂度,以及大规模降低数据存储的容量,唯一的遗憾则是集合元素限制为64个,会导致无法满足招聘网站后期业务发展需要。

    电子商务等行业特点:

    1)         数据分类的种类较多,往往超过总数64的限制;

    2)         公司或产品开发维护的技术工程师更迭频繁;

    3)         电子商务、招聘网站等行业的产品运营周期长;

    4)         多数公司的软件程序版本发布流程不健全;

    5)         数据库维护人员和开发工程师的工作配合,容易出现信息同步不到位或不周全的情况;

    6)         用户的数据安全性和正确性,对企业非常重要,往往都是花费较贵的推广费用吸引而来的;

    MySQL数据库中采用集合类型存储数据,生产环境的网站程序或软件版本更新发布时,一旦出现数据库维护人员没有优先更新数据库表字段的定义属性,则会导致重大的数据丢失事故,给企业造成直接的经济损失。

    网络游戏行业的特点

    1)         有大量业务是分类不多的数据需要存储(注:往往是几个分类,最多不超过30个分类);

    2)         网络游戏行业要求开发成本降低、开发速度快等特点;

    3)         网络游戏公司采用的数据库服务器的硬件配置差,甚至单硬盘的主机支撑多个数据库提供数据服务,主机的存储空间也有限;

    4)         网络游戏产品的生命周期绝大部分不超过5年,一般的网络游戏产品运营1年以上就很少再更新软件的版本;

    网络游戏产品使用MySQL数据库集合类型字段存储业务数据,是非常值得推荐的方式,对开发人员而言,跟使用其他数据类型是一样的,也无额外学习成本,还可以为企业降低开发成本、硬件资源成本。

    (4).     总结

    系统地分析了布尔类型、枚举类型、集合类型,MySQL数据库没有实现布尔类型,只是借助微整型TINYINT(1)间接实现,为此可以理解MySQL数据库没有布尔类型;集合类型与枚举类型,都各自存在一个非常可怕的弊端 — 数据库结构变更没有做,网站程序或软件版本发布已上线,导致用户数据丢失的问题,那么我们不使用枚举类型或集合类型,能否获得这2种数据类型的优点,规避这2种数据类型的缺陷,为此我们各举一个实际应用案例。

    l  取代集合类型应用场景—求职者工作意向城市

    1)         创建存储城市信息的表City(注:假设只有一个字段:城市名称)

    ?
    1
    2
    3
    4
    5
    CREATE TABLE city(
    ID MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
                       City_Name VARCHAR (20) NOT NULL DEFAULT '' ,
                       PRIMARY KEY (ID),
                       UNIQUE INDEX idx_city_name(City_Name)
                      )ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE 'utf8_general_ci' ;

    2)         创建存储城市编号与求职者ID编号的对照关系表

    ?
    1
    2
    3
    4
    CREATE TABLE user_work_city(
    UID INT UNSIGNED NOT NULL AUTO_INCREMENT,
                       CityID MEDIUMINT NOT NULL DEFAULT 0 ,
                       PRIMARY KEY(UID,CityID)
                      )ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE 'utf8_general_ci' ;

    3)         写入几条测试数据

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    INSERT INTO city(City_Name) VALUES ( '上海' ),( '北京' ),( '深圳' ),( '广州' ),( '杭州' ),( '武汉' );
    INSERT INTO user_work_city(UID,CityID) VALUES (8263638,1),(8263638,3),(8263638,5);
     
    root@localhost : mysqlops 04:09:17> SELECT * FROM city;
    + ----+-----------+
    | ID | City_Name |
    + ----+-----------+
    |  1 | 上海      |
    |  2 | 北京      |
    |  4 | 广州      |
    |  5 | 杭州      |
    |  6 | 武汉      |
    |  3 | 深圳      |
    + ----+-----------+
    6 rows in set (0.00 sec)
     
    root@localhost : mysqlops 04:09:28> SELECT * FROM user_work_city;
    + ---------+--------+
    | UID     | CityID |
    + ---------+--------+
    | 8263638 |      1 |
    | 8263638 |      3 |
    | 8263638 |      5 |
    + ---------+--------+
    3 rows in set (0.00 sec)

    4)         通过SQL语句获得求职者意向城市信息

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    root@localhost : mysqlops 04:09:35> SELECT UC.UID,GROUP_CONCAT(City_Name) FROM city C ,user_work_city UC
         -> WHERE  UC.UID=8263638 AND C.ID=UC.CityID
         -> GROUP BY UC.UID ORDER BY NULL ;
    + ---------+-------------------------+
    | UID     | GROUP_CONCAT(City_Name) |
    + ---------+-------------------------+
    | 8263638 | 上海,深圳,杭州          |
    + ---------+-------------------------+
    1 row in set (0.00 sec)

    小结

    求职者可挑选工作意向城市列表,可以通过后台程序进行编辑,并且存储在City表中,可以任意进行添加、修改、删除,都不会造成网站程序版本的更新,也不会影响数据库提供的数据服务,且城市名称等信息的变更,只要修改City表即可。另外,通过简便的内连接SQL查询语句,就可以符合MySQL支持的JOIN连接算法—嵌套循环算法,效率非常高,也不需要程序进行特殊处理,完全可以取代集合类型的作用,唯一遗憾就是需要多写点代码。

    l  电子商务行网站的商品分类目录

    1)       创建存储商品分类信息表

    ?
    1
    2
    3
    4
    5
    6
    CREATE TABLE product_class(
    ID MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
                               Product_Description VARCHAR (40) NOT NULL DEFAULT '' ,
                               Parent_Flag TINYINT NOT NULL DEFAULT 0,
                               PRIMARY KEY (ID),
                               UNIQUE INDEX idx_Product_Desc(Product_Description)
                             )ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE 'utf8_general_ci' ;

    2)       创建存储商品分类目录之间的上下级关系表

    ?
    1
    2
    3
    4
    5
    6
    CREATE TABLE pc_parent_child(
    ID MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
                                Parent_ID MEDIUMINT NOT NULL DEFAULT 0,
                                Child_ID  MEDIUMINT NOT NULL DEFAULT 0,
                                PRIMARY KEY (ID),
                                INDEX idx_pid_cid(Parent_ID,Child_ID)
                              )ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE 'utf8_general_ci' ;

    3)       写入测试数据

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    INSERT INTO product_class(Product_Description)
     
    VALUES ( '大家电' ),( '平板电视' ),( '洗衣机' ),( '冰箱' );
     
    INSERT INTO product_class(Product_Description)
     
    VALUES ( '生活电器' ),( '取暖器' ),( '加湿器' ),( '净化器' );
     
    INSERT INTO pc_parent_child(Parent_ID,Child_ID)  VALUES (1,2);
     
    INSERT INTO pc_parent_child(Parent_ID,Child_ID)  VALUES (1,3);
     
    INSERT INTO pc_parent_child(Parent_ID,Child_ID)  VALUES (5,8);

    4)商品分类数据查询

    商品分类目录的数据读取,都是先读取父节点的信息,再根据父节点信息读取其下子节点的数据信息。

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    root@localhost : mysqlops 05:28:41> SELECT M.Product_Description
         -> FROM product_class M
         ->       INNER JOIN pc_parent_child N  ON M.ID=N.Child_ID
         -> WHERE N.Parent_ID=1 ;
    + ---------------------+
    | Product_Description |
    + ---------------------+
    | 平板电视            |
    | 洗衣机              |
    + ---------------------+
    2 rows in set (0.00 sec)

    小结:

    若是采用枚举类型存储商品分类信息,我们则可以简便地创建一张表,2个字段即可实现上述的做法,最大的缺陷是子节点升级为父节点的时候,则需要发布网站程序与做数据库结构变更。修改枚举类型字段的定义属性,必须以尾部追加的方式,才不影响数据库提供的数据服务。使用我们介绍的替代办法,则需要工程师编写更多的代码实现,可以借助图形化管理工具轻松完成,各自都有优缺点。

    一句话总结:任何解决方案,必须从技术、开发成本、维护成本、可靠性等多个角度综合论证,寻找最适合团队、业务场景的方案。

    数据类型系列讲解文章列表:
    MySQL数据库数据类型之ENUM、SET、BOOL/BOOLEAN、TINYINT

    MySQL数据库之数据类型BOOL/BOOLEAN与TINYINT测试总结

    MySQL数据库数据类型之枚举类型ENUM数据测试总结

    MySQL数据库数据类型之集合类型SET数据测试总结

    MySQL数据库之数据类型集合类型和枚举类型测试环境

    MySQL数据库之枚举类型ENUM的DDL变更测试

    MySQL数据库之集合类型SET的DDL变更测试总结

    展开全文
  • 请不要理解为数据库中表的一个列,这不是一个概念,它是指一个字段对象,充当着实体对象的属性,也是一个列表类型类型化数据对象,当本系列提到“字段field”一般均是指字段对象或字段定义对象,而数据库表中的...

    “字段”概念
    在drupal中提到“字段”这个概念时,请不要理解为数据库中表的一个列,这不是一个概念,它是指一个字段对象,充当着实体对象的属性,也是一个列表类型的类型化数据对象,当本系列提到“字段field”一般均是指字段对象或字段定义对象,而数据库表中的字段列,则将其称为“列column”;一个字段对象可以包含数据库表中的多个列(取决于字段类型定义中的schema),这些列称为字段对象的属性,这样的字段叫做多属性字段;由于字段对象是列表类型的数据因此可包含数据库表中的多行数据,具体可以有多少行由字段定义对象中的基数参数决定,每行对应列表中的一个元素,当基数大于一或无限时,这样的字段称为多值字段(注意和多属性字段的区别)。关于字段对象的储存,可以多个字段储存在一张表中,也可以一个字段独立储存在一张属于她的专用表中,在一些特殊情况下一个字段对象还可以被储存在几张数据表中。

    储存结构概述:
    在一些cms系统中,是先设计数据库表结构,然后再围绕这个结构去开发程序,这很直观,但不够灵活,也不够强大,当需要额外的表时系统不能代为建立和感知,而drupal则不同,在drupal中内容管理主要是基于实体,实体又基于字段,系统是先找出实体所有的字段对象,再根据她们的储存定义自动计算出需要多少数据库表及每个字段应该放置在哪张表中,字段对象和她在数据库中的储存数据表的对应信息由表映射对象托管,而怎么决定这种映射关系,可以参看sql内容实体储存处理器中的getTableMapping方法(见下文),她是系统关于字段和储存表的默认映射规则。

    表映射对象:
    类:Drupal\Core\Entity\Sql\DefaultTableMapping
    接口:\Drupal\Core\Entity\Sql\TableMappingInterface
    该对象保存着实体字段对象到数据库表之间的映射信息,该类实例化后是一个没有数据的空对象,必须借助sql内容实体储存处理器为她注入数据,本质上该对象只是一个保存者,决定这种映射关系的逻辑代码实际位于sql内容实体储存处理器的getTableMapping方法中,我们明白了这个方法也就明白了内容实体的表结构。

    默认内容实体数据库表结构:
    为什么是默认呢?这是因为字段对象我们可以为其定义自定义储存,在默认情况下也是大多数情况下是用系统提供的储存机制,这里我们仅关注默认情况,要知道数据库表结构,需要先明白字段对象和数据库表的对应逻辑,核心代码位于:
    Drupal\Core\Entity\Sql\SqlContentEntityStorage::getTableMapping(array $storage_definitions = NULL);
    下文我们将详细分析该逻辑,这种对应逻辑适用于所有的内容实体,也就是说所有的内容实体类型的储存数据表遵循共有的规则(如表如何命名、哪些字段放哪个表、有哪些额外附加的列等),在系统中最主要的内容实体类型是节点实体,我们以它作为列子,然后你可以推及到其他内容实体,如用户user实体等。

     

     

    要建立数据库表,需要知道内容实体的所有字段信息,这从实体字段管理器中获取(见本系列该主题),建表后再将这些字段分门别类的放到这些表中,一个内容实体类型的所有字段,系统使用五种类型的数据库表来储存,她们是:

     

     

    基本表:
    每个内容实体都必须存在的表,表名在实体类释文键“base_table”中指定,无指定则为实体类型id,比如节点实体类型表名为“node”
    版本表:
    仅在内容实体类型是可版本化时才存在,表名在实体释文键“revision_table”中指定,无指定则为实体类型id+'_revision',比如节点实体类型为“node_revision”
    数据表:
    仅在内容实体类型是可翻译的时才存在,表名在实体释文键“data_table”中指定,无指定则为实体类型id+'_field_data',比如节点实体类型为“node_field_data”
    版本数据表:
    仅在内容实体类型是可版本化且是可翻译的时才存在,该表存在时数据表必然存在,表名在实体释文键“revision_data_table”中指定,无指定则为实体类型id+'_field_revision',比如节点实体类型为“node_field_revision”
    字段专用表:
    当字段需要独立储存时为其建立的专用数据表,表名为:实体类型id+分隔符+字段名,字段专用表的分隔符为双下划线“__”,如果字段是可版本化的,那么还有字段版本专用表,命名规则一样,仅分隔符为“_revision__”,如果表名大于48个字符,那么做哈希处理,具体见上文表映射对象的generateFieldTableName方法,在系统管理后台:结构/内容类型管理中添加的字段,就是字段专用表来储存的,添加的字段名称被强制加上了“field_”前缀

    注意以上提到的表名并不包括在数据库连接信息中指定的表前缀,如有指定需要加上才是数据库中真实的表名。

    那么在一个内容实体中哪些字段存放在哪张表中呢?我们来详细分析上文提到的得到表映射方法:
    Drupal\Core\Entity\Sql\SqlContentEntityStorage::getTableMapping(array $storage_definitions = NULL);
    默认情况是从实体字段管理器(见本系列实体字段管理器主题)中获取一个内容实体类型所有的字段储存定义,然后首先找出可以和其他字段共同储存在一张数据表中的那些字段,她们被称为可共享储存字段,这些可共享储存表的字段必须同时满足三个规则:
    1、非自定义储存,也就是使用系统默认储存
    2、是基本字段,不能为bundle字段
    3、不可多值储存,也就是一个字段对象只需要一行数据,不需要多行
    该规则定义在以下方法中:
    Drupal\Core\Entity\Sql\DefaultTableMapping::allowsSharedTableStorage
    然后初始化以下变量并将可共享储存字段分类:
    $key_fields:
    关键字段,唯一标识一条信息的必要字段,是所有内容实体共有的字段,她们为:实体id、版本id、bundle、uuid、语言id,他们的字段名和存在性由实体类型决定
    $all_fields:
    全部可共享储存字段,包含关键字段且关键字段排序靠前
    $revisionable_fields:
    可共享储存字段中可版本化的字段
    $revision_metadata_fields:
    可版本化元数据字段(主要用于添加版本标注),字段名定义在实体释文的revision_metadata_keys键中

    然后根据内容实体类型是否可版本化和可翻译性分四种情况,将可共享储存字段放入四种非专用表中,如下:
    1、 不可版本化且不可翻译
    所有可共享储存字段$all_fields全部放在基本表中,此时不会有版本id和语言id字段,也没有其他共享表
    2、 可版本化但不可翻译
    只建立基本表和版本表,全部可共享储存字段$all_fields排除版本元字段$revision_metadata_fields后放入基本表中,在版本表中放入可共享储存字段$all_fields中的可版本化字段,并加入版本关键字段:实体id和版本id
    3、 不可版本化但可翻译
    只建立基本表和数据表,基本表中只储存关键字段$key_fields,全部可共享储存字段$all_fields放入数据表中(但uuid字段除外)。user实体类型即属于此情况,可查看数据库表:“users”为基本表,“users_field_data”为数据表
    4、 可版本化且可翻译
    四种非专用表全部建立,节点实体即属于该种情况,基本表只储存关键字段$key_fields;可共享储存字段$all_fields排除uuid及版本化元字段$revision_metadata_fields后放入数据表中;实体id、版本id、语言id和版本化元字段一起放入版本表中;从可版本化字段$revisionable_fields中排除版本元字段及语言代码字段后和实体id、版本id、语言代码字段一起放入版本数据表中,这里排除语言代码字段又合并它是为了排序。
    通过以上逻辑就将可共享储存表的所有字段划分到了四种共享储存数据表中,然后处理需要独立储存的字段,判断字段是否需要专用储存表的规则如下(同时满足):
    1、 非自定义储存,也就是使用系统默认储存的字段
    2、 可共享储存字段以外的全部字段
    该规则定义在如下方法中:
    Drupal\Core\Entity\Sql\DefaultTableMapping::requiresDedicatedTableStorage
    字段储存专用表只有数据表和版本表两种,如果字段不是可版本化的则没有版本表,她们的表名按前文所述规则计算得出。

    所有字段专用数据表都被附加了以下列:
    ['bundle','deleted','entity_id','revision_id','langcode','delta']
    注意是“列”而不是字段,所有字段会被转化成为列然后和附加的列一起构成数据表的“列”。

    字段对象转化为列的规则:
    先需要明白字段的属性,她对应于字段储存定义对象的getColumns方法返回数组的键名,默认情况下在字段类型类的schema方法中定义。
    在共享表中如果字段仅有一个属性,那么列名为字段名,注意此时不会理会字段的属性名,这将影响传递给实体类构造函数参数$values的结构,通常只有一个属性的字段属性名设置为“value”,如果多于一个属性名则列名为:$field_name . '__' . $property_name,注意是双下划线,在读取时系统根据列名是否有双下划线去判断该列是否为一个字段的属性。
    在字段专用表中,如果字段属性为“%delta”那么列名为“delta”,如果属性名在系统保留列名(见补充)中,那么列名为属性名,其他情况则列名为$field_name . '_' . $property_name,这和共享表不一样,在字段只有一个属性的情况下并不以字段名命名,且注意是单下划线
    以上字段转换成列的规则定义在以下方法中:
    Drupal\Core\Entity\Sql\DefaultTableMapping::getColumnNames($field_name)


    补充资料:
    1、保留列名:用于系统功能,目前仅有“deleted”(表示实体是否已被删除),在字段类型设计中不能使用保留列名做字段列(字段属性)。
    2、在后台录入信息时,默认情况下,录入信息的语言并不是根据当前界面的语言来自动识别的,而是语言选择器中输入,但该逻辑可以在管理内容类型的结构时在语言选项中指定,可以指定默认为界面语言


    节点实体数据字典:
    通过以上学习您应该明白了内容实体在数据库中的表结构,以下列出系统中最重要的节点内容实体的表结构,及其表中的列含义,俗称cms开发的“数据字典”(版本:drupal 8.4.0):

    节点基本表(表名“node”),字段含义如下:
    nid:节点id,或叫做节点内容实体的实体id
    vid:版本id,在该表中储存节点当前版本(也是最新版本,版本的回退是在回退版本中复制数据形成新版本)
    type:节点bundle名,也就是内容类型机器名
    uuid:全局通用识别id,见本系列UUID主题,用于跨系统唯一标识一个信息对象
    langcode :该节点该版本的源语言代码,未指定则为“und”,不适用则为“zxx”见本系列语言主题

    节点版本表(表名“node_revision”),字段含义如下:
    nid:同上
    vid:该节点的各版本id
    langcode:同上,该节点该版本的源语言代码
    revision_timestamp:版本建立时的unix时间戳,非修改时间
    revision_uid:进行版本建立操作的用户id
    revision_log:版本注释(版本标识日志)

    节点数据表(表名“node_field_data”),字段含义如下:
    该表储存节点实体最新版本的所有翻译信息
    nid:同上
    vid:节点最新版本id
    type:同上
    langcode:该节点最新版本的各语言代码
    status:布对外尔值,发表状态,1为已发表,0位未发表
    title:节点标题,也是节点实体的label
    uid:建立第一个版本时的用户id
    created:该节点第一个版本建立时的时间戳,而不是当前版本的
    changed:该节点最后一个版本的修改时间
    promote:布尔值,是否推荐到首页,1为推荐
    sticky:布尔值,是否置顶,1为置顶
    revision_translation_affected:当该节点有多个翻译时,新建版本后,本语言是否已经进行了翻译更新,1为是
    default_langcode:该节点的该版本的该语言,是否为源语言(一个版本的源语言只有一个,可修改)
    content_translation_source:本翻译来自的源语言,如果本翻译就是源语言,那么值为“und”
    content_translation_outdated:在内容翻译模块启用时才存在,布尔值,表示翻译是否已经过期,1为过期

    节点版本数据表(表名“node_field_revision”),字段含义如下:
    该表储存节点实体所有版本的所有翻译信息
    nid:同上
    vid:同上
    langcode:该节点该版本的语言代码
    status:同上
    title:同上
    uid:同上,注意在此表中,该字段表示第一个版本的创建用户,而不是指当前版本的创建用户
    created:同上,注意是该节点第一个版本建立时的时间戳,而不是当前版本的建立时间
    changed:同上
    promote:同上
    sticky:同上
    revision_translation_affected:同上
    default_langcode:同上
    content_translation_source:同上
    content_translation_outdated:同上

    节点专用表列举,字段名“node__body”,字段含义如下(其他专用表类似):
    bundle:通用附加列,储存bundle,也就是内容类型
    deleted:通用附加列,表示内容是否已经被删除
    entity_id:通用附加列,实体id
    revision_id:通用附加列,实体版本id
    langcode:通用附加列,语言代码
    delta:通用附加列,当字段包含多值时,本条信息的数组下标,起到排序作用
    body_value:字段body对应的value属性
    body_summary:字段body对应的summary属性,表示摘要信息
    body_format :字段body对应的format属性,表示字段允许的标签类型:受限制、基本的、完整的HTML

     

     

    我是云客,【云游天下,做客四方】,联系方式见主页,欢迎转载,但须注明出处

     

     

     

     

    展开全文
  • 来自it界的小学生,请多多指教 ...DB First 数据库里先创建数据库表结构,根据表结构生成类,根据类操作数据库 Code First 先写代码,执行代码创建数据库表结构 主流的orm都是code first。django 的or...

    来自it界的小学生,请多多指教

    1、简介
    ORM:关系对象映射。定义一个类自动生成数据库的表结构。
    创建数据库的时候,一般有以下几种常用数据类型:数字、字符串以及时间。
    ORM分为两种:
    DB First 数据库里先创建数据库表结构,根据表结构生成类,根据类操作数据库
    Code First 先写代码,执行代码创建数据库表结构
    主流的orm都是code first。django 的orm也是code first,所以学的时候,本质就分为两块:
    根据类自动创建数据库表
    根据类对数据库表中的数据进行各种操作
    2、创建数据库 表结构
    先写类:
    app下models.py文件:
    from django.db import models

    class UserInfo(models.Model): # 必须继承models.Model

    不写则,django默认创建ID列,自增,主键

    用户名列,字符串类型,指定长度

    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    1234567
    注册APP
    执行命令python manage.py makemigrations,会提示No changes detected,这是因为:执行命令时会找所有models,但是django不知道找哪个,所有需要指定一下。
    settings.py,
    INSTALLED_APPS = [
    ‘django.contrib.admin’,
    ‘django.contrib.auth’,
    ‘django.contrib.contenttypes’,
    ‘django.contrib.sessions’,
    ‘django.contrib.messages’,
    ‘django.contrib.staticfiles’,
    ‘app01’, # 这里添加app
    ]
    123456789
    执行命令生成表结构
    python manage.py makemigrations # 生成migrations临时文件
    python manage.py migrate # 根据migrations直接生成数据库
    12
    执行后,从migrations便会产生操作记录。生成数据库,默认情况下用的sqlite3。可以用navicat等软件直接打开。
    db.sqlite3里面包含缓存、session、cookie、静态文件以及后台管理。像咱们创建的表名叫:app01_userinfo
    连接mysql数据库
    如果不使用sqlite,使用mysql数据库。代码不用改、命令也不用改,只需要改下配置文件。

    https://docs.djangoproject.com/en/1.10/ref/settings/#databases 官网文档# DATABASES = { # sqlite 默认# ‘default’: {# ‘ENGINE’: ‘django.db.backends.sqlite3’,# ‘NAME’: os.path.join(BASE_DIR, ‘db.sqlite3’),# }# }

    DATABASES = { # mysql
    ‘default’: {
    ‘ENGINE’: ‘django.db.backends.mysql’,
    ‘NAME’: ‘mydatabase’,
    ‘USER’: ‘mydatabaseuser’,
    ‘PASSWORD’: ‘mypassword’,
    ‘HOST’: ‘127.0.0.1’,
    ‘PORT’: ‘3306’,
    }
    }
    1234567891011121314151617
    注意:
    数据库名django不能创建,需要自己提前创建
    Django默认使用MySQLdb模块链接MySQL,但python3现在还没有MySQLdb,所以改为用pymysql去连。在project项目名下的init.py里面
    import pymysql
    pymysql.install_as_MySQLdb()
    12
    二、Django ORM基本增删改查
    1、表数据增删改查
    urls.py
    url(r’^orm/’, views.orm),
    1
    app01/views.py
    from app01 import models # 导入models模块def orm(request):# 创建数据

    第一种方式

    models.UserInfo.objects.create(username=”root”,password=”123”)

    第二种方式

    obj = models.UserInfo(username=’fzh’, password=”iajtag”)

    obj.save()

    第三种方式

    dic = {‘username’:’fgf’, ‘password’:’666’}

    models.UserInfo.objects.create(**dic)

    查询数据

    result = models.UserInfo.objects.all() # 查询所有,为QuerySet类型,可理解成列表

    result = models.UserInfo.objects.filter(username=”fgf”,password=”666”) # 列表

    result = models.UserInfo.objects.filter(username=”fgf”).first() # 对象

    条件查询。filter 相当于where查询条件,里面的”,”会组成and条件

    for row in result: # 打印查询到数据。

    print(row.id,row.username,row.password)

    查看QuerySet类型具体做了什么事情,可以: print(result.query)

    删除数据

    models.UserInfo.objects.all().delete() # 删除所有

    models.UserInfo.objects.filter(id=4).delete() # 删除所有

    更新数据

    models.UserInfo.objects.all().update(password=8888)

    models.UserInfo.objects.filter(id=3).update(password=888888)

    return HttpResponse(‘orm’)
    12345678910111213141516171819202122232425262728293031
    2、表结构修改
    修改列
    把最初定义的类中字段password = models.CharField(max_length=64)改为password = models.CharField(max_length=60)。重新执行python manage.py makemigrations,python manage.py migrate,则数据表结构更改了。如果列内内容超过定义大小,则数据就丢了。
    增加一列
    类中增加一列,执行命令,会有提示信息,因为默认情况下是不允许为空的。这里提供两个选项。
    输入一个值,新增列已存在的行默认加上输入的内容。
    email = models.CharField(max_length=32, null=True),允许为空
    查看表结构变化时,刷新看不出来,需要重新打开表看效果。
    删除列
    类内删掉相应的字段,执行命令即可。
    三、Django ORM 字段类型
    1、字段类型介绍
    Django ORM 字段类型中,有CharField、EmailField、URLField、GenericIPAddressField等,实际上在数据库里都是字符串。不能做检查语法,做不了验证。那这个有什么用呢?
    这些是给Django 的 admin 用的。在admin那个网页上做验证。如果不用admin,那那些都是字符串,效果都一样。
    自定义自增列:models.AutoField(primary_key=True)
    1、models.AutoField  自增列 = int(11)
      如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
    2、models.CharField  字符串字段
      必须 max_length 参数
    3、models.BooleanField  布尔类型=tinyint(1)
      不能为空,Blank=True4、models.ComaSeparatedIntegerField  用逗号分割的数字=varchar
      继承CharField,所以必须 max_lenght 参数
    5、models.DateField  日期类型 date
      对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
    6、models.DateTimeField  日期类型 datetime
      同DateField的参数
    7、models.Decimal  十进制小数类型 = decimal
      必须指定整数位max_digits和小数位decimal_places
    8、models.EmailField  字符串类型(正则表达式邮箱) =varchar
      对字符串进行正则表达式
    9、models.FloatField  浮点类型 = double
    10、models.IntegerField  整形
    11、models.BigIntegerField  长整形
      integer_field_ranges = {
        ‘SmallIntegerField’: (-32768, 32767),
        ‘IntegerField’: (-2147483648, 2147483647),
        ‘BigIntegerField’: (-9223372036854775808, 9223372036854775807),
        ‘PositiveSmallIntegerField’: (0, 32767),
        ‘PositiveIntegerField’: (0, 2147483647),
      }
    12、models.IPAddressField  字符串类型(ip4正则表达式)(已弃用,用13、)
    13、models.GenericIPAddressField  字符串类型(ip4和ip6是可选的)
      参数protocol可以是:both、ipv4、ipv6
      验证时,会根据设置报错
    14、models.NullBooleanField  允许为空的布尔类型
    15、models.PositiveIntegerFiel  正Integer16、models.PositiveSmallIntegerField  正smallInteger
    17、models.SlugField  减号、下划线、字母、数字
    18、models.SmallIntegerField  数字
      数据库中的字段有:tinyint、smallint、int、bigint
    19、models.TextField  字符串=longtext
    20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]]
    21、models.URLField  字符串,地址正则表达式
    22、models.BinaryField  二进制
    23、models.ImageField 图片
    24、models.FilePathField 文件
    123456789101112131415161718192021222324252627282930313233343536373839404142
    如上那么多的字段,可大致分为 字符串、数字、时间、二进制、自增(primary_key=True)几类。
    2、字段参数介绍
    数据库中的字段参数
    null # 是否可以为空
    default # 默认值
    primary_key # 主键
    db_column # 列名
    db_index # 索引(db_index=True)
    unique # 唯一索引(unique=True)
    unique_for_date # 只对日期索引
    unique_for_month # 只对月份索引
    unique_for_year # 只对年做索引
    auto_now # 创建时,自动生成时间
    auto_now_add # 更新时,自动更新为当前时间
    1234567891011

    更新时间不支持这种

    obj = UserGroup.objects.filter(id=1).update(caption=’CEO’)
    obj = UserGroup.objects.filter(id=1).first() # 自动更新时间需要这样写
    obj.caption = “CEO”
    obj.save()
    12345
    以下是只针对admin的字段参数
    choices # 作用:1、django admin中显示下拉框;2、避免连表查询
    1
    user_type_choices = ( # 数据库只存1、2、3,后面的信息存在内存里。
    (1, ‘超级用户’),
    (2, ‘普通用户’),
    (3, ‘普普通用户’),
    )
    user_type_id = models.IntegerField(choices=user_type_choices,default=1)
    123456
    blank # django admin是否可以为空
    verbose_name # django admin显示字段中文
    editable # django admin是否可以被编辑
    error_messages # 错误信息

    error_messages={“required”:”密码不能为空”,} # 注意必须有逗号

    help_text # django admin提示
    validators # django form ,自定义错误信息

    python manage.py createsuperuser # 创建 Django 用户
    123456789
    3、Django ORM 外键操作
    连表关系之一对多,models.ForeignKey(ColorDic)
    models.py
    表关联
    class UserGroup(models.Model):
    uid = models.AutoField(primary_key=True)
    caption = models.CharField(max_length=32,unique=True)
    ctime = models.DateTimeField(auto_now_add=True, null=True)
    uptime = models.DateTimeField(auto_now=True, null=True)

    class UserInfo(models.Model):
    username = models.CharField(max_length=32,blank=True,verbose_name=’用户名’)
    password = models.CharField(max_length=60, help_text=’pwd’)
    email = models.CharField(max_length=60)
    test = models.EmailField(max_length=19,null=True,error_messages={‘invalid’: ‘请输入密码’,})

    UserInfo表中没有user_group字段,而是 user_group_id 列 值为 uid 数字

    user_group = models.ForeignKey(“UserGroup”,to_field=’uid’) # 外键关联 ****
    12345678910111213
    数据查询
    user_list = Userinfo.objects.all() # 获取Userinfo对象for row in user_list: #
    print(row.user_group_id) # 数据库里真实存在的数据

    user_group:代指UserGroup对象。类UserGroup对象里封装了(uid,catption,ctime,uptime)

    print(row.user_group.uid) # 通过对象获取uid,和user_group_id一样
    print(row.user_group.caption) # 通过对象获取caption
    123456
    创建数据
    UserInfo表创建数据,怎么写呢?
    models.UserInfo.objects.create(
    username=’root1’,
    password=’123’,
    email=”asdfasdf”,
    test=”asdfasdf”,
    # 第一种方式:再次查询数据库,不推荐
    # user_group = models.UserGroup.objects.filter(id=1).first()
    # 第二种方式:通过 外键字段_id
    user_group_id = 1
    )

    展开全文
  • ThingBoard数据库表结构

    千次阅读 2019-05-20 17:03:41
    文章目录admin_settings 系统设置alarm 警报asset 资产attribute_kv 属性audit_log 审计日志component_descriptorcustomer 客户dashboard 仪表盘device 设备device_credentials 设备凭据entity_view 实体信息event...
  • Postgresql数据库布尔类型的介绍
  • 1、文件类型 数据库在磁盘上是以文件为单位存储的,由数据文件和事务日志文件组成。一个数据库至少应该包含一个数据文件和一个事务日志文件。 主数据文件:主数据文件包含数据库的启动信息,指向数据库中的其他...
  • bit 存储布尔数据类型 【注】 1个字节=8bit nchar(1) 就表示一个长度,可以是字符‘男’、可以是数字1 char(2) 表示可以写2个字符,即2个数字,一个中文汉字 可以的写法:varchar(max) decimal(20,6) 表示一共20位...
  • Java基础知识面试题(2020最新版)

    万次阅读 多人点赞 2020-02-19 12:11:27
    文章目录Java概述何为编程什么是Javajdk1.5之后的三大版本JVM、JRE和JDK的关系什么是跨平台性?原理是什么Java语言有哪些...Java和C++的区别Oracle JDK 和 OpenJDK 的对比基础语法数据类型Java有哪些数据类型switc...
  • 商品表结构分析

    千次阅读 2019-05-26 10:07:52
    文章目录引言表结构分析 引言 先引入两个概念: SPU:Standard Product Unit (标准产品单位) ,一组具有共同属性的商品集 SKU:Stock Keeping Unit(库存量单位),SPU商品集因具体特性不同而细分的每个商品 ...
  • MySQL命令大全

    2018-01-15 11:19:17
    2、获取表结构 命令:desc 表名,或者show columns from 表名 mysql>DESCRIBE MyClass mysql> desc MyClass; mysql> show columns from MyClass; 3、删除表 命令:drop table <表名> 例如:删除表名为 ...
  • ORACLE数据库数据类型

    千次阅读 2019-11-28 17:51:42
    1、字符类型 • CHAR:一个定长字符串,当位数不足自动用空格填充来达到其最大长度。如非NULL的CHAR(12)总是包含12字节信息。CHAR字段最多可以存储2,000字节的 信息。 • VARCHAR2:目前这也是VARCHAR 的同义词。这...
  • DB2是IBM一种分布式数据库解决方案。说简单点:DB2就是IBM开发的一种大型...DB2数据库核心又称作db2公共服务器,采用多进程多线索体系结构,可以运行于多种操作系统之上,并分别根据相应平台环境作了调整和优化,以便
  • camunda目前我使用的版本中,它有47张表。 camunda一共有五类,通过名称来分别它们的不同。... act_ge_schema_log:数据库脚本执行日志。 二、然后是有关历史的,以"act_hi_"开头的: act_hi_actins
  • openfire数据库表结构

    千次阅读 2011-11-18 10:05:30
    导言 This document outlines the data type conventions and tables in the Openfire database schema. Some information, like column indexes...该文件概述了公约和数据类型中的Openfire数据库架构。一些信息,比
  • 电商项目数据库设计-客户 会员等级 现在很多电商平台都有自己的会员制度,甚至现在线下的商场都是会员制的,而且不同的会员够买商品的价格也不一样,所以我们在设计客户之前先设计一个客户等级 先看看字段: ...
  • 数据库系统概论》复习

    千次阅读 多人点赞 2019-05-27 12:13:27
    数据库系统概论》复习 第一章 绪论 1.1 数据库系统概述 1、数据库系统的四个基本概念 数据(Data):描述事物的符号记录称为数据,数据是数据库存储的基本对象。 数据库(DB):长期存储在计算机内、有组织的...
  • 前提前边一篇文章详细分析了如何在Windows10系统下搭建ClickHouse的开发环境,接着需要详细学习一下此数据库的数据定义,包括数据类型、DDL和DML。ClickHouse作为...
  • 本文主要用于介绍如何使用copy或者\copy命令将postgresql数据库的数据导出为excel格式,方便用户查看编辑。 copy命令同\copy命令语法上相同,区别在于copy必须使用能够超级用户使用,copy … to file 中的文件都...
  • 字符串类型的字段在各关系数据库中均占有重要地位。比如Oracle数据库中用于存储字符串类型数据的字段类型就超过了5种。...本文将辨析Oracle数据库中表示字符串的各字段类型以及设计表结构时字段类型的选择依据。
  • 【知识图谱】知识图谱的基础概念与构建流程

    千次阅读 多人点赞 2019-11-09 18:46:49
    3.1知识图谱的逻辑结构 3.2知识图谱的体系架构 4、代表性知识图谱库 5、知识图谱构建的关键技术 5.1 知识提取 5.2 知识表示 5.3 知识融合 【导读】知识图谱技术是人工智能技术的组成部分,其强大的语义处理和...
  • 离散数学在计算机科学中的应用

    万次阅读 多人点赞 2018-02-03 11:56:44
    数据结构中将操作对象间的关系分为四类:集合、线性结构、树形结构、图状结构或网状结构。数据结构研究的主要内容是数据的逻辑结构,物理存储结构以及基本运算操作。其中逻辑结构和基本运算操作来源于离散
  • 测试开发笔记

    万次阅读 多人点赞 2019-11-14 17:11:58
    32 、字段、类型 33 查询 35 批量处理? 40 视图/虚 view 41 索引 42 存储过程 procedure 42 事务 transaction 43 触发器 trigger 46 练习 46 一、单查询练习 46 二、聚合函数练习 47 三、分组查询练习 47 四...
  • (1)为什么很多人使用传统的数据库用惯了,觉得存储过程就不是那么重要?存储过程到底有什么用呢?...建立员工档案管理的表结构(1)首先在连接完数据库后,自己创建数据库:----创建数据库create database Em...
  • EMPLOYEES表用户存放所有员工的信息,表结构如下: 1 实现步骤 连接数据库 连接数据库成功后显示如下: 2 创建表空间TBS 打开表空间菜单,鼠标右键单击,选择“新建表空间”菜单: 进入新建表空间的对话框中,...
  • 数据库的逻辑结构设计

    万次阅读 多人点赞 2018-06-30 23:21:51
    逻辑结构是独立于任何一种数据模型的,在实际应用中,一般所用的数据库环境已经给定(如SQL Server或Oracle或MySql)。由于目前使用的数据库基本上都是关系数据库,因此首先需要将E-R图转换为关系模型,然后根据具体...
  • Python基础教程,Python入门教程

    万次阅读 多人点赞 2019-07-15 10:23:21
    Python bool布尔类型 6. Python len()函数:获取字符串长度或字节数 7. Python input()函数:获取用户输入的字符串 8. Python print()函数高级用法 9. Python格式化字符串 10. Python转义字符 11....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 45,003
精华内容 18,001
关键字:

数据库表结构布尔类型