威尼斯www.9778.com-威尼斯正版官方网站

Node.js与Sails~Model数据模型

日期:2020-02-14编辑作者:数据库

写在前面

本来这个东西,我是不想在这里总结的,今天有初学者的朋友问我了,那就不得不说说了,你肯定也踩过这样的坑,没遇到,说明你运气好,编码习惯好。那还是言归正传吧。避免你中枪,还是扫一眼这篇文章吧。

回到目录

内容回顾

mysql默认端口号:3306
mysql中的超级用户:root
创建数据库:CREATE DATABASE
修改数据库:ALTER DATABASE
删除数据库:DROP DATABASE

一个例子

测试环境:sqlserver2012,vs2013

下面看一个简单的例子,例子非常简单,就不再写注释了。一个测试的数据表TB_UserInfo:

图片 1

一个再简单不过的表,自增的id,用户名字,注册时间,从上图你也看到了,是允许为空的。

再弄一个简单的测试程序。

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Data; 7 using System.Data.SqlClient; 8 namespace Wolfy.SQLDateTimeDemo 9 {10   class Program11   {12     static void Main(string[] args)13     {14       string strConn = "server=.;database=test;uid=sa;pwd=sa;";15       string strSql = "insert into TB_userInfo values(@Name,@RegDateTime)";16       UserInfo user = new UserInfo() { Name = "wolfy" };17       try18       {19         using (SqlConnection conn = new SqlConnection(strConn))20         {21           using (SqlCommand cmd = new SqlCommand(strSql, conn))22           {23             cmd.Parameters.Add(new SqlParameter("@Name", user.Name));24             cmd.Parameters.Add(new SqlParameter("@RegDateTime", user.RegDateTime));25             conn.Open();26             if (cmd.ExecuteNonQuery() > 0)27             {28               Console.WriteLine("注册成功");29             }30             else31             {32               Console.WriteLine("注册失败");33             }34           }35         }36       }37       catch (Exception ex)38       {39         throw ex;40       }41     }42   }43   /// <summary>44   /// 用户信息类45   /// </summary>46   class UserInfo47   {48     /// <summary>49     /// 编号50     /// </summary>51     public int Id { set; get; }52     /// <summary>53     /// 姓名54     /// </summary>55     public string Name { set; get; }56     /// <summary>57     /// 注册时间58     /// </summary>59     public DateTime RegDateTime { set; get; }60   }61 }

我们知道,如果在使用类的属性的时候,你不为他赋值,则采用默认值。

图片 2

可见它是有默认值的。

那我们继续往下走,再看看

图片 3

出现了,这个异常,想必很多人都遇到过吧。

可以看出,vs中datetime类型的默认值与sqlserver中的datetime类型范围的确存在冲突。突然有这样的想法,为什么这两种默认值不兼容呢?考虑到现在的软件都会和数据库相结合,这样设计是不是有点不合理了?这东西,咱也是无法改变了,也只能选择接收了。尽量做到规范设计吧。

有两种做法可以解决这个问题:

方案一:

在添加数据的时候,为datetime类型的值赋值为当前时间。

1  UserInfo user = new UserInfo() { Name = "wolfy", RegDateTime=DateTime.Now };

方案二:

创建数据表的时候给时间类型的字段添加默认值约束

1 语法:2 ALTER TABLE table_name3 ADD CONSTRAINT constraint_name4 DEFAULT constant_expression [FOR column_name]5 参数说明:6  table_name:要创建默认约束的表名称。7  constraint_name:默认约束名称。8 constant_expression:默认值。



1 alter table tb_userinfo add constraint default_RegDateTime default getdate() for [RegDateTime]

 这种做法比较保险。推荐!

对于Sails来说,它的Model与数据库对应,不过它并没有采用目前比较流行的poco贫血模型,而是采用了类似DDD的充血模型,即它的数据实体里即有数据库字段(属性)而且还有方法,而模型里的方法主要用来修饰它的属性,如属性的有效性,属性的赋值,插入前和更新前的动作等等,下面我们通过具体的实例代码来说一下sails实体模型的用法。

数据类型之整型

** 数据类型:数据类型是指列、存储过程参数、表达式和局部变量的数据特征,它决定了数据的存储格式,代表了不同的信息类型。**

图片 4

整形所占空间

合理选择数据类型,节省存储空间(选择最合适的为不是最大的数据类型)

总结

这个知识点再容易不过了,估计很多初学者都会踩这样的坑,不过还好,踩过了就长记性了,也是有好处的。为什么会有这样的问题?可能你对伙伴比较信任,潜意识觉得他肯定会在数据库中添加默认约束的。到最后中枪的还是自己。所以在设计程序,编写代码的时候,一定要严谨!

一 定义一个Person实体

module.exports = {
    autoPK:true,//这是默认值,可以省略
    tableName: 'UserInfo',
    attributes: {
        name: {
            type: 'string',
            size: 255
        },
        sex: {
            type: 'integer',
            defaultsTo: 0
        },
        updateCount:{
            type:'integer',
            defaultsTo: 0
        }

    }

};

数据类型之浮点型

图片 5

浮点型

M表示数字总位数(整数部分和小数部分)D表示小数的位数

二 对model相关参数的说明

通过上面的代码我们知道了在sails中数据模型的类型,除了上面的string,integer,还有以下数据类型

  • float
  • text
  • date
  • datetime
  • boolean
  • binary
  • array
  • json

除了数据类型外,还有以下几个知识点需要我们知道的

tableName:表示数据库中数据表的名称

defaultsTo:表示属性的默认值

size:表示数据长度

email:可以添加对emial字段的约束,email:true

unique:表示这个字段在数据表中是唯一的标示,如用户表,有些业务要求用户名是唯一的,我们就可以利用unique这个特性,

primaryKey:可以让我们把某个字段定义成数据表的主键,但在使用它时,要确保model的autoPK为false否则会有冲突(默认为true)

autoPK:是否自动生成主键字段id,true表示自动生成主键,false不生成,sails为各种数据库订制了主键生成规则,由mysql,sqlserver为自增主键,而mongodb为objectid主键

autoCreateAt:自动生成createAt字段,即添加时间

``autoUpdateAt:自动生成updateAt字段,即当记录有更新时,这个时间被自动更新

enum:表示某个字段可以以枚举的形式保存,它所存储的值为这个枚举的某个元素

图片 6

columnName:为实体指定特殊的数据表列名,这类似于tableName

数据类型之日期时间型

图片 7

Paste_Image.png

TIMESTAMP:1970.1.1-2037.(时间戳:从1970.1.1.0:00::00到当前时间的秒数2^31)
DATA:1000.1.1-999912.31
DATATIME:1000.1.1.00:00-9999.12.31.23:59:5 9
TIME:-8385959-8385959
YEAR:1970-2069
实际开发日期时间类型用的不多,存在时区的问题,大多采用数字类型取代(以时间戳的格式存储)

三 beforeUpdate和beforeCreate的作用

通过上面代码我们可以在数据添加前和更新上做一些事情,这也是充血模型的优势,它将与属性本身有关的逻辑写到了属性内容,而不是写在service方法里,这有效的提高了对象的内聚性,也是面向对象的体现,下面的代码在记录更新时,对updateCount字段进行加1操作,代码很简单,但可以说明它的作用。

 beforeCreate: function (values, next) {
        values.password =  md5(values.password,"zzl");//添加记录时,为密码进行加密策略,这由于属于密码本身的特性,所以写在这里比在业务代码更合适/
        next();
    }
  beforeUpdate: function (values, next) {//values这个对象是从前台传过来的对象
        values.updateCount+=1;
        next();
    }

这里要注意一点,你的values对象是前台传给service层的对象,不是从数据表里取出来的原始对象,这点要注意,有些想通过这个功能实现数据追踪的,无法简单实现!

 回到目录

数据类型之字符型

图片 8

Paste_Image.png

char(M):定长,如果字节数少于M,存储时会在字符串后边增加空格补齐.如:char(5),存放abc,存储时会在后边加两个空格
varchar(M):变长是多上就存多少
enum:枚举类型,只能选一个
set:集合类型,可以选一个,也可以选多个

创建数据表

** 概述:数据表(或称表)是数据库最重要的组成部分之一,是其他对象的基础**

行:记录、元组
列:字段、属性

数据表存在于数据库中,要想使用数据表,首先要打开数据库,可使用use命令打开数据库。用法:use databasename use后加数据库名打开数据库。

  • 回顾:打开mysql的命令:mysql -uroot -proot -P3306 -h127.0.0.1 -u后是用户名,-p后是密码,-P后是端口号,-h后是主机地址(127.0.0.1表示本机) *

如何查看当前所打开的数据库:SELECT DATABASE();

创建数据表:

CREATE TABLE [IF NOT EXISTS] table_name(
column_name data_type,
......
)

IF NOT EXISTS 可以省略,column_name 是列名,data_type是数据类型,可以从刚才的数据类型中选择,“,”是列与列之间的分隔符,最后一列可以不写。
** 数据表的建立不能脱离项目,要根据项目需要建立 **
例:

CREATE TABLE tb1(
username VARCAHR(20),
age TINYINT UNSIGNED,
salary FLOAT(8,2) UNSIGNED
);

UNSIGNED:无符号(非负)
FLOAT(8,2):浮点型,总8位,小数点后2位
salary:工资

查看数据表

查看数据表命令:SHOW TABLES;
不仅可以查看当前数据库的数据表,还可以查看其他数据库数据表,命令:SHOW TABLES FROM dbname

  • SHOW TABLES [FROM db_name] [LIKE 'pattern' | WHERE expr]

** 查看后当前数据库不会改变。 **

查看数据表结构

查看数据表结构命令:SHOW COLUMNS FROM tbl_name
或者:DESC tbl_name

记录的插入与查找

  • 插入记录:INSERT [INTO] tbl_name [(col_name,...)] VALUES(val,...)

中括号里的可以省略,列名可以省略,省略后默认为所有列,需要为所有列赋值
例:
INSERT tb1 VALUES('Tom',25,7867.4);
省略列名,为所有字段赋值
INSERT tb1(username,salary) VALUES('John',4440.5);
不省略列名,为部分字段赋值

  • 简单的SELECT命令:SELECT expr,... FROM tbl_name

SELECT * FROM tb1;

  • 没有赋值的字段会显示为null *

空值与非空

  • NULL,字段值可以为空
  • NOT NULL,字段值禁止为空

两个不能同时用到一个字段上,原因你懂的

例:

CREATE TABLE tb2(
username VARCHAR(20) NOT NULL,
age TINYINT UNSIGNED NULL
);

NULL可以不写,因为默认就是null(可以为空)
当插入记录时如果不为NOT NULL(不为空)的列赋值,会报错的哦

自动编号

在需要保证某一记录的唯一性(在数据表中这条记录不存在重复),这时,可以为字段添加AUTO_INCREMENT
** 可以为整数,也可以是浮点数,浮点数要保证小数位数为0 **
AUTO_INCREMENT:

  • 自动编号,且必须与主键组合只用
  • 默认情况下,起始值为1,每次的增量为1

例:

CREATE TABLE tb3(
id SMALLINT UNSIGNED AUTO_INCREMENT,
username VARCHAR(30) NOT NUL
);

会报错,因为自动编号的字段必须定义为主键

初涉主键约束

主键PRIMARY KEY

  • 主键约束
  • 每张数据表只能存在一个主键
  • 主键保证记录的唯一性
  • 逐渐自动为NUT NULL

主键约束的字段不能为空,建表时会自动加上,自己手动加也不会出错

例:

CREATE TABLE tb3(
id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(30) NOT NUL
);

主键既可以写成KEY也可以写成PRIMARY KEY

设为自动编号的字段不用赋值
例:

INSERT tb3(username) VALUES('Tom');
INSERT tb3(username) VALUES('John');
INSERT tb3(username) VALUES('Rsoe');
INSERT tb3(username) VALUES('Dimitar');

使用SELECT查看后看到id自动加上了

AUTO_INCREMENT必须和主键一起使用,但是PRIMARY KEY不一定要和自动编号一起使用

CREATE TABLE tb4(
id SMALLINT UNSIGNED PRIMARY KEY,
username VARCHAR(20) NOT NULL
);

主键允许赋值,但是不允许存在相同的值

初涉唯一约束

主键只能存在一个,如果还想保证数据的唯一性,可以用唯一约束

UNIQUE KEY:

  • 唯一约束
  • 唯一约束可以保证记录的唯一性
  • 唯一约束的字段可以为空值
  • 每张数据表可以存在多个唯一约束

唯一约束不约束空值(可以存在多个NULL)
例:

CREATE TABLE tb5(
id SMALLINT UNSIGNED AUTO INCREMENT KEY,
username VARCHAR(20) NOT NULL UNIQUE KEY,
age TINYINT UNSIGNED
);

表结构:

图片 9

Paste_Image.png

初涉默认约束

DEFAULT:

  • 默认值
  • 当插入记录时,如果没有明确为字段赋值,则自动赋予默认值。
CREATE TABLE tb6(
id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20) NOT NULL UNIQUE KEY,
sex ENUM('1','2','3') DEFAULT '3'
);

图片 10

表结构

没有赋值时系统会使用默认值

总结

本节知识点

  • 数据类型
    • 字符型
    • 整型
    • 浮点型
  • 数据表操作
    • 插入记录
    • 查找记录
  • 记录操作
    • 创建数据表
    • 约束的使用

本文由威尼斯www.9778.com发布于数据库,转载请注明出处:Node.js与Sails~Model数据模型

关键词:

小写金额转换成大写

我们日常开发业务系统中,作为统计报表中,特别是财务报表,显示中文金额经常遇到。 转换大小写的方法有很多,...

详细>>

Atitit.sqlwhere条件表达式的原理attilax概括

Atitit.sql where条件表达式的原理  attilax概括     1. 数据查询接口sql api标准化1 2. Sql接口的问题2 2.1. 虽然sql是结构...

详细>>

那些年我们一起做过的[分组查询]

学习数据库那么长日子了,对与分组查询也终归有一点领会了,带我们一起来回看下大家的分组查询 分组查询 在分组查...

详细>>

我们分组玩的游戏 还记得吗

use Myschool--------------------上机练习1---------------------查询每个年级的总学时数,并按照升序排列select gradeid as 年级,sum(C...

详细>>