MySQL數據類型與操作


內容提要:

  1. 建表完整語法規范(create table 表格(字段名1 類型 (寬度) 約束條件))

  2. MySQL數據庫數據類型(整型、浮點型、字符類型(char與varchar)、日期類型、枚舉與集合)

  3. 約束條件(primary key、unique key、not null、foreign key)

一、創建表的完整語法

語法:

create table 表名(

字段名1 類型 (寬度) 約束條件,

字段名2 類型 (寬度) 約束條件,

字段名3 類型 (寬度) 約束條件);

特別注意:

  • 在同一張表中,字段名不能相同
  • 寬度和約束條件為可選項,但是字段名和類型必須有
  • 最后一個字段添加完畢后后面不能加逗號!

補充:1、這里的寬度是對存儲數據的一種限制,在不同MySQL版本里面可能會出現不同的結果,這里只是不同版本的默認約束條件不一樣導致,在最新版本5,7中如果輸入數據

寬度超出限制,則會報錯。

   2、類型與約束條件的區別:類型是限制字段必須以什么樣的數據類型存儲,二約束條件是在這一類型之上添加一種額外的限制。

二、MySQL基本數據類型

  • 整型(int)

    • 分類:tinyint  smallint  mediumint  int  bigint
    • 作用:儲存年齡、等級、id、各種號碼等
    • 類型存儲范圍:
    • 驗證整型字段有無符號及范圍
      int類型默認是有符號的,也就是說默認支持輸入負數到正數
      mysql> reate table t1(id tinyint);
      mysql> insert into t1 values(128),(-129);
      #結果:ERROR 1264 (22003): Out of range value for column 'id' at row 1
      # 因為tinyint類型最大正整數限制為127,輸入128超出范圍。報錯
      
      create table t2(id tinyint unsigned);  # unsigned表示這里類型設置為無符號(無正負號)
      mysql> insert into t2 values (0),(255);
      #這里類型約束為無符號,所以輸入負數就會報錯,輸入超過255的數也會報錯。tinyint無符號范圍是0-255。
      
      以下同理:
      create table t3(id int unsigned);
      mysql> insert into t3 values (4294967296);
      ERROR 1264 (22003): Out of range value for column 'id' at row 1
      mysql> insert into t3 values (4294967295);
      Query OK, 1 row affected (0.01 sec)
      
      強調:對於整型來說,數據類型之后的寬度並不是存儲限制,而是現實寬度限制,所以在創建表的時候,
      如果字段采用的是整型類型,完全無需指定顯示寬度,因為默認的顯示寬度(11),一般情況下,就足夠顯示完整的數據。        
  • 浮點型(分為float、double、decimal)

    • 應用場景:身高、體重、薪資
    • 字符限制特點(5,3),前一位表示所有的位數,后一位表示小數個數
    • 區別對比:
      # 存儲限制
      float(255,30)
      double(255,30)
      decimal(65,30)
      
      # 精確度驗證
      mysql> create table t9(x float(255,30));
      mysql> create table t10(x double(255,30));
      mysql> create table t11(x decimal(65,30));
      
      mysql> insert into t9 values(1.111111111111111111111111111111);
      mysql> insert into t10 values(1.111111111111111111111111111111);
      mysql> insert into t11 values(1.111111111111111111111111111111);
      mysql> select * from t9;
      +----------------------------------+
      | x                                |
      +----------------------------------+
      | 1.111111164093017600000000000000 |
      +----------------------------------+
      1 row in set (0.00 sec)
      
      mysql> select * from t10;
      +----------------------------------+
      | x                                |
      +----------------------------------+
      | 1.111111111111111200000000000000 |
      +----------------------------------+
      1 row in set (0.00 sec)
      
      mysql> select * from t11;
      +----------------------------------+
      | x                                |
      +----------------------------------+
      | 1.111111111111111111111111111111 |
      +----------------------------------+
      1 row in set (0.00 sec)
      
      從上面的查詢創建的表中數據可以看出:
      精度對比:decimal的精度最高,其次是double,最后是float,
      但是就算是精度最低的float它的精度也有16位,所以一般使用完全能夠應付99%的數據場景。
  • 字符類型(char定長與varchar變長)

    • 作用:姓名、地址、描述類信息
    • 理解通過實際使用來描述:
      char:
      mysql> create table t12(name char(4));
      mysql> insert into t12 values ('hello');
      ERROR 1406 (22001): Data too long for column 'name' at row 1 # 超出限制范圍會報錯。
      mysql> insert into t12 values ('hell');
      Query OK, 1 row affected (0.01 sec)
      mysql> insert into t12 values ('he');
      Query OK, 1 row affected (0.00 sec)
      mysql> select * from t12;
      +------+
      | name |
      +------+
      | hell |         # 4個字符正好填滿
      | he   |         #不夠4個字符空格補全
      +------+
      --------------------------------------------------------------
      varchar:
      mysql> create table t13(name varchar(4));
      mysql> insert into t13 values ('hello');
      ERROR 1406 (22001): Data too long for column 'name' at row 1         # 超出范圍,報錯
      mysql> insert into t13 values ('hell');
      Query OK, 1 row affected (0.00 sec)
      mysql> insert into t13 values ('he');
      Query OK, 1 row affected (0.01 sec)
      mysql> select * from t13;
      +------+
      | name |
      +------+
      | hell |     # 正好4個,填滿
      | he   |    # 不夠4個,按實際寬度占位。(這里看不出來,但是一定要記住,varchar是變長,所以不夠4個肯定按實際寬度存儲)
      
      +------+
      #####
      TIP:
      select char_length(name) from t12
      select char_length(name) from t13  # 仍然無法查看到真正的結果
      
      """首先應該肯定的是在硬盤上存的絕對是真正的數據,但顯示的時候mysql會自動將末尾的空格取掉"""
      # 如果不想讓mysql幫你做自動去除末尾空格的操作,需要再添加一個模式
      set global sql_mode="strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH";
      # 退出客戶端重新登陸
      select char_length(x) from t12; #4
      select char_length(y) from t13; #1
      
      # 針對char類型,mysql在存儲時會將數據用空格補全存放到硬盤中。但是會在讀出結果的時候自動取掉末尾的空格
      ####
    • char 與 varchar 的使用區別
      • name char(5)
        • 優點:浪費空間,每個name信息都是按照5個字符存,這樣如果不夠5個的也會用空格補全,造成存儲空間浪費
        • 缺點:存取速度很快,因為存儲數據的結構固定,所以存取速度快。
        • egon alex lxx  jxx  txx  存用5個字符5個字符存,取的話也是5個字符為一部分取,准確快捷
      • name varchar(5)
        • 缺點:存取速度慢,每個name信息按照可變長的形式去存,同時存的時候要在前面加入該字符長度的報頭,一並存入,取的時候按照報頭里的長度數據去取數據,比char多了好幾步,所以存取數據相比較char會慢些。
        • 優點:節省空間,通過可變長來存入,加上報頭數據也不會造成空間的太多浪費
        • 1bytes+egon 1bytes+alex 1bytes+lxx  1bytes+jxx  1bytes+txx 
  • 時間類型

    • 分類:
      • date:2019-05-13
      • time:11:11:11
      • datetime:2019-05-13 11:11:11
      • year:2019
    • 測試:
      mysql> create table stu(id int,name char(16),birth_d date,study_time time,reg_time datetime);  # 創建表
      mysql> insert into stu values(1,'jason','2019-05-09','11:11:11','2019-11-11 11:11"11');   #插入表數據
      Query OK, 1 row affected (0.00 sec)
      
      mysql> select * from stu;   # 顯示表內容
      +------+-------+------------+------------+---------------------+
      | id   | name  | birth_d    | study_time | reg_time            |
      +------+-------+------------+------------+---------------------+
      |    1 | jason | 2019-05-09 | 11:11:11   | 2019-11-11 11:11:11 |
      +------+-------+------------+------------+---------------------+
      1 row in set (0.00 sec)
  • 枚舉與集合類型:

    • 分類  
      • 枚舉enum 多選一
      • 集合set 多選  一或多
    • 示例:
      enum枚舉:
      mysql> create table usr(id int,name char(16),gender enum('male','female','others'));
      Query OK, 0 rows affected (0.05 sec)
      mysql> insert into usr values(1001,'jsson','xxx');
      ERROR 1265 (01000): Data truncated for column 'gender' at row 1
      mysql> insert into usr values(1001,'jsson','male');
      Query OK, 1 row affected (0.01 sec)
      mysql> insert into usr values(1002,'egon','female');
      Query OK, 1 row affected (0.01 sec)
      mysql> select * from usr;
      +------+-------+--------+
      | id   | name  | gender |
      +------+-------+--------+
      | 1001 | jsson | male   |
      | 1002 | egon  | female |
      +------+-------+--------+
      2 rows in set (0.00 sec)
      -----------------------------------------------------------------
      set集合:
      mysql> create table tea(id int,name char(16),gender enum('male','female','other'),hobby set('read','sleep','dbj'));
      Query OK, 0 rows affected (0.04 sec)
      mysql> insert into tea values(10011,'egon','female','read,dbj');
      Query OK, 1 row affected (0.01 sec)
      mysql> insert into tea values(10012,'alex','male','dbj');
      Query OK, 1 row affected (0.05 sec)
      mysql> select * from tea;
      +-------+------+--------+----------+
      | id    | name | gender | hobby    |
      +-------+------+--------+----------+
      | 10011 | egon | female | read,dbj |
      | 10012 | alex | male   | dbj      |
      +-------+------+--------+----------+
      2 rows in set (0.00 sec)
  • 約束條件

    • 類型
      PRIMARY KEY (PK)    標識該字段為該表的主鍵,可以唯一的標識記錄
      FOREIGN KEY (FK)    標識該字段為該表的外鍵
      NOT NULL            標識該字段不能為空
      UNIQUE KEY (UK)     標識該字段的值是唯一的
      AUTO_INCREMENT      標識該字段的值自動增長(整數類型,而且為主鍵)
      DEFAULT             為該字段設置默認值
      UNSIGNED            無符號
      ZEROFILL            使用0填充not null + defaultnot null:不為空

      • not null + default

      • mysql> create table us(id int,name char(16));
        Query OK, 0 rows affected (0.05 sec)
        
        mysql> insert into us values (1,null);
        Query OK, 1 row affected (0.01 sec)
        
        mysql> desc us;
        +-------+----------+------+-----+---------+-------+
        | Field | Type     | Null | Key | Default | Extra |
        +-------+----------+------+-----+---------+-------+
        | id    | int(11)  | YES  |     | NULL    |       |
        | name  | char(16) | YES  |     | NULL    |       |
        +-------+----------+------+-----+---------+-------+
        
        mysql> delete from us where id=1;   # 先清空存入的null數據
        Query OK, 1 row affected (0.01 sec)
        
        mysql> alter table us modify name char(16) not null; # 將name輸入的數據限制為非空
        Query OK, 0 rows affected (0.05 sec)
        Records: 0  Duplicates: 0  Warnings: 0
        
        mysql> desc us;  # 查看表格式:
        +-------+----------+------+-----+---------+-------+
        | Field | Type     | Null | Key | Default | Extra |
        +-------+----------+------+-----+---------+-------+
        | id    | int(11)  | YES  |     | NULL    |       |
        | name  | char(16) | NO   |     | NULL    |       |
        +-------+----------+------+-----+---------+-------+
        
        mysql> insert into us values(002,null);  # 此時再輸入null就會報錯了,因為我們限制了name必須輸入未非空的字符。
        ERROR 1048 (23000): Column 'name' cannot be null
        default  默認值
        mysql> create table st(id int,name char(16) not null,gender enum('male','female') default 'male');  # 為gender字段設置默認值‘male,前面指定輸入字段不包含gender時候,這時候的默認字段名就會生效。
        Query OK, 0 rows affected (0.03 sec)
        
        mysql> insert into st(id,name) values (1001,'lxx');
        Query OK, 1 row affected (0.01 sec)
        
        mysql> select * from st;
        +------+------+--------+
        | id   | name | gender |
        +------+------+--------+
        | 1001 | lxx  | male   |
        +------+------+--------+
        1 row in set (0.00 sec)
      • unique  某個字段對應的值在當前表中是唯一的,不能重復

        ###單列唯一:
        mysql> create table user1(id int unique,name char(16));
        Query OK, 0 rows affected (0.04 sec)
        
        mysql> insert into user1 values (1,'js'),(1,'eg'); #報錯
        ERROR 1062 (23000): Duplicate entry '1' for key 'id'
        mysql> insert into user1 values (1,'js'),(2,'eg'); #不報錯
        Query OK, 2 rows affected (0.00 sec)
        Records: 2  Duplicates: 0  Warnings: 0
        
        ###聯合唯一:多個字段如果同時有相同的輸入時,會報錯
        mysql> create table server(id int,ip char(16),port int,unique(ip,port));
        Query OK, 0 rows affected (0.04 sec)
        
        mysql> desc server;
        +-------+----------+------+-----+---------+-------+
        | Field | Type     | Null | Key | Default | Extra |
        +-------+----------+------+-----+---------+-------+
        | id    | int(11)  | YES  |     | NULL    |       |
        | ip    | char(16) | YES  | MUL | NULL    |       |
        | port  | int(11)  | YES  |     | NULL    |       |
        +-------+----------+------+-----+---------+-------+
        3 rows in set (0.00 sec)
        
        mysql> insert into server values (1,'127.0.0.1',8080);
        Query OK, 1 row affected (0.01 sec)
        
        mysql> insert into server values (2,'127.0.0.1',8080);   #ip和port都相同,報錯
        ERROR 1062 (23000): Duplicate entry '127.0.0.1-8080' for key 'ip'  
        
        mysql> insert into server values (2,'127.0.0.2',8080); # 僅僅是port相同不會報錯
        Query OK, 1 row affected (0.00 sec)
        
        mysql> insert into server values (3,'127.0.0.1',8081); #僅僅是ip相同也不會報錯
        Query OK, 1 row affected (0.00 sec)
        
        mysql> select * from server;  查看結果:
        +------+-----------+------+
        | id   | ip        | port |
        +------+-----------+------+
        |    1 | 127.0.0.1 | 8080 |
        |    2 | 127.0.0.2 | 8080 |
        |    3 | 127.0.0.1 | 8081 |
        +------+-----------+------+
        3 rows in set (0.00 sec)
      • primary key+auto_increment(mysql數據類型及約束條件的重點內容,必須要掌握)

        # 單從約束角度來說 primary key 等價於not null + unique
        mysql> create table tt1(id int primary key);  # 設置id主鍵唯一
        Query OK, 0 rows affected (0.04 sec)
        
        mysql> desc tt1;
        +-------+---------+------+-----+---------+-------+
        | Field | Type    | Null | Key | Default | Extra |
        +-------+---------+------+-----+---------+-------+
        | id    | int(11) | NO   | PRI | NULL    |       |
        +-------+---------+------+-----+---------+-------+
        1 row in set (0.00 sec)
        
        mysql> insert into tt1 values (1),(1);   # 主鍵不唯一,報錯
        ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
        mysql> insert into tt1 values (1),(2);  #唯一,不報錯
        Query OK, 2 rows affected (0.00 sec)
        Records: 2  Duplicates: 0  Warnings: 0
        -----------------------------------------------------------------
        重點內容:
        一、一張表中必須有且只有一個主鍵,如果你沒有設置主鍵,那么會從上到下搜索直到遇到一個非null且unique的字段自動將其設為主鍵。
        mysql> create table ts1(id int,name char(16),age int not null unique,addr char(16) not null unique)engine=innodb;
        Query OK, 0 rows affected (0.04 sec)
        
        mysql> desc ts1;
        +-------+----------+------+-----+---------+-------+
        | Field | Type     | Null | Key | Default | Extra |
        +-------+----------+------+-----+---------+-------+
        | id    | int(11)  | YES  |     | NULL    |       |
        | name  | char(16) | YES  |     | NULL    |       |
        | age   | int(11)  | NO   | PRI | NULL    |       |
        | addr  | char(16) | NO   | UNI | NULL    |       |
        +-------+----------+------+-----+---------+-------+
        ------------------------------------------------------------------
        二、如果表里面沒有指定的任何可以設置的主鍵字段,那么innodb存儲引擎會采用自己的默認的一個隱藏的字段作為主鍵,隱藏意味着你在查詢的時候無法根據主鍵字段加速查詢了
        ------------------------------------------------------------------
        三、一張表中通常都應該有一個id字段,並且通常將id字段設為主鍵
        ------------------------------------------------------------------
        額外知識點:
        #聯合主鍵:與聯合唯一字段一個道理,即多個字段聯合起來作為表的主鍵,本質上將多個字段總體看為一個主鍵
        mysql> create table ts2(ip char(16),port int,primary key(ip,port));
        Query OK, 0 rows affected (0.04 sec)
        
        mysql> desc ts2;     # 2個字段合為一個主鍵。
        +-------+----------+------+-----+---------+-------+
        | Field | Type     | Null | Key | Default | Extra |
        +-------+----------+------+-----+---------+-------+
        | ip    | char(16) | NO   | PRI | NULL    |       |
        | port  | int(11)  | NO   | PRI | NULL    |       |
        +-------+----------+------+-----+---------+-------+
        auto_increment  自增約束
        mysql> create table ts3(id int primary key auto_increment,name char(16));
        Query OK, 0 rows affected (0.05 sec)
        
        mysql> insert into ts3(name) values ('jason'),('alex'),('lxx');    #只輸入name字段信息
        Query OK, 3 rows affected (0.01 sec)
        Records: 3  Duplicates: 0  Warnings: 0
        
        mysql> select * from ts3;   # 查看自增結果
        +----+-------+
        | id | name  |
        +----+-------+
        |  1 | jason |
        |  2 | alex  |
        |  3 | lxx   |
        +----+-------+
        ------------------------------------------------------------------
        補充:
        接着上面的例子,如果我將其中一個字段比如lxx,刪除后再添加字段,會出現:
        mysql> delete from ts3 where id=3;
        Query OK, 1 row affected (0.01 sec)
        
        mysql> insert into ts3(name) values ('xxxx');
        Query OK, 1 row affected (0.01 sec)
        
        mysql> select * from ts3;
        +----+-------+
        | id | name  |
        +----+-------+
        |  1 | jason |
        |  2 | alex  |
        |  4 | xxxx  |       # 此時序號居然還是接着自增。
        +----+-------+
        3 rows in set (0.00 sec)
        
        tip:如果要清楚繼續自增,從頭開始的話,就必須清空表,才行。
        mysql> truncate ts3;  # 將整張表重置,id重新從0開始記錄。
        Query OK, 0 rows affected (0.03 sec)
        
        mysql> insert into ts3(name) values ('eeeee');
        Query OK, 1 row affected (0.01 sec)
        
        mysql> select * from ts3;
        +----+-------+
        | id | name  |
        +----+-------+
        |  1 | eeeee |
        +----+-------+  

-------------------------------------------------------------------------------------------------------------------------------------------

  • 嚴格模式補充

  我們剛剛在上面設置了char,tinyint,存儲數據時超過它們的最大存儲長度,發現數據也能正常存儲進去,只是mysql幫我們自動截取了最大長度。但在實際情況下,我們應該盡量減少數據庫的操作,緩解數據庫的壓力,讓它僅僅只管理數據即可,這樣的情況下就需要設置安全模式

show variables like "%mode%";  # 查看數據庫配置中變量名包含mode的配置參數
# 修改安全模式
set session # 只在當前操作界面有效
set global  # 全局有效

set global sql_mode ='STRICT_TRANS_TABLES'
# 修改完之后退出當前客戶端重新登陸即可

 

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM