1. 程式人生 > >MySQL學習筆記(三)-約束和多表查詢

MySQL學習筆記(三)-約束和多表查詢

MySQL學習筆記(三)

1 完整性約束

完整性約束是為了表的資料的正確性!如果資料不正確,那麼一開始就不能新增到表中。

1.1 主鍵

當某一列添加了主鍵約束後,那麼這一列的資料就不能重複出現。這樣每行記錄中其主鍵列的值就是這一行的唯一標識。例如學生的學號可以用來做唯一標識,而學生的姓名是不能做唯一標識的,因為學生有可能同名。

主鍵列的值不能為NULL,也不能重複!指定主鍵約束使用PRIMARY KEY關鍵字。

  • 建立表:定義列時指定主鍵 :

    CREATE TABLE stu(
    		sid	    CHAR(6) PRIMARY KEY,
    		sname	VARCHAR(20),
    		age		INT
    , gender VARCHAR(10) );
  • 建立表:定義列之後獨立指定主鍵:

    CREATE TABLE stu(
    		sid	    CHAR(6),
    		sname	VARCHAR(20),
    		age		INT,
    		gender	VARCHAR(10),
    		PRIMARY KEY(sid)
    );
    
  • 修改表時指定主鍵 :

    ALTER TABLE stu
    ADD PRIMARY KEY(sid);
    或者
    ALTER TABLE stu MODIFY sid CHAR(6) PRIMARY KEY;
    
  • 刪除主鍵(只是刪除主鍵約束,而不會刪除主鍵列)

    ALTER TABLE stu DROP
    PRIMARY KEY

1.2 主鍵自增長

MySQL提供了主鍵自動增長的功能!這樣使用者就不用再為是否有主鍵是否重複而煩惱了。當主鍵設定為自動增長後,在沒有給出主鍵值時,主鍵的值會自動生成,而且是最大主鍵值+1,也就不會出現重複主鍵的可能了。

  • 建立表時設定主鍵自增長(主鍵必須是整型才可以自增長):

    CREATE TABLE stu(
    		sid INT PRIMARY KEY AUTO_INCREMENT,
    		sname	VARCHAR(20),
    		age		INT,
    		gender	VARCHAR(10)
    );
    
    
  • 修改表時設定主鍵自增長:

    ALTER TABLE stu CHANGE sid sid INT
    AUTO_INCREMENT;
  • 修改表時刪除主鍵自增長:

    ALTER TABLE stu CHANGE sid sid INT;
    

1.3 非空約束

指定非空約束的列不能沒有值,也就是說在插入記錄時,對添加了非空約束的列一定要給值;在修改記錄時,不能把非空列的值設定為NULL。

指定非空約束 :

CREATE TABLE stu(
		sid INT PRIMARY KEY AUTO_INCREMENT,
		sname VARCHAR(10) NOT NULL,
		age		INT,
		gender	VARCHAR(10)
);

當為sname欄位指定為非空後,在向stu表中插入記錄時,必須給sname欄位指定值,否則會報錯 。

1.4 唯一約束

還可以為欄位指定唯一約束!當為欄位指定唯一約束後,那麼欄位的值必須是唯一的。這一點與主鍵相似!例如給stu表的sname欄位指定唯一約束:

CREATE TABLE tab_ab(
	sid INT PRIMARY KEY AUTO_INCREMENT,
	sname VARCHAR(10) UNIQUE
);
INSERT INTO sname(sid, sname) VALUES(1001, 'zs');
INSERT INTO sname(sid, sname) VALUES(1002, 'zs');

當兩次插入相同的名字時,MySQL會報錯!

1.5 外來鍵約束

主外來鍵是構成表與表關聯的唯一途徑!

外來鍵是另一張表的主鍵!例如員工表與部門表之間就存在關聯關係,其中員工表中的部門編號欄位就是外來鍵,是相對部門表的外來鍵。

  • 建立時指定外來鍵

    CREATE TABLE emp(#僱員表
    	empno		INT,#員工編號
    	ename		VARCHAR(50),#員工姓名
    	job		VARCHAR(50),#員工工資
    	mgr		INT,#領導編號
    	hiredate	DATE,#入職日期
    	sal		DECIMAL(7,2),#月薪
    	comm		decimal(7,2),#獎金
    	deptno		INT,#部門編號
        CONSTRAINT fk_dept FOREIGN KEY(deptno) REFERENCES dept(deptno)
    ) ;
    
  • 修改時指定外來鍵

    alter table emp add constraint fk_dept FOREIGN KEY(deptno) references dept(deptno);
    
  • 修改時刪除外來鍵

    alter table emp drop foreign key fk_dept;
    

1.6 表與表之間的關係

  • 一對一:例如t_person表和t_card表,即人和身份證。這種情況需要找出主從關係,即誰是主表,誰是從表。人可以沒有身份證,但身份證必須要有人才行,所以人是主表,而身份證是從表。設計從表可以有兩種方案:
    1. 在t_card表中新增外來鍵列(相對t_user表),並且給外來鍵新增唯一約束;
    2. 給t_card表的主鍵新增外來鍵約束(相對t_user表),即t_card表的主鍵也是外來鍵。
  • 一對多(多對一):最為常見的就是一對多!一對多和多對一,這是從哪個角度去看得出來的。t_user和t_section的關係,從t_user來看就是一對多,而從t_section的角度來看就是多對一!這種情況都是在多方建立外來鍵!
  • 多對多:例如t_stu和t_teacher表,即一個學生可以有多個老師,而一個老師也可以有多個學生。這種情況通常需要建立中間表來處理多對多關係。例如再建立一張表t_stu_tea表,給出兩個外來鍵,一個相對t_stu表的外來鍵,另一個相對t_teacher表的外來鍵。

2 編碼

2.1 MySQL編碼

mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

  • character_set_client:你傳送的資料必須與client指定的編碼一致!!!伺服器會使用該編碼來解讀客戶端傳送過來的資料;
  • character_set_connection:通過該編碼與client一致!該編碼不會導致亂碼!當執行的是查詢語句時,客戶端傳送過來的資料會先轉換成connection指定的編碼。但只要客戶端傳送過來的資料與client指定的編碼一致,那麼轉換就不會出現問題;
  • character_set_database:資料庫預設編碼,在建立資料庫時,如果沒有指定編碼,那麼預設使用database編碼;
  • character_set_server:MySQL伺服器預設編碼;
  • character_set_results:響應的編碼,即查詢結果返回給客戶端的編碼。這說明客戶端必須使用result指定的編碼來解碼;

2.2 控制檯編碼

修改character_set_client、character_set_results、character_set_connection為GBK,就不會出現亂碼了。但其實只需要修改character_set_client和character_set_results。

控制檯的編碼只能是GBK,而不能修改為UTF8,這就出現一個問題。客戶端傳送的資料是GBK,而character_set_client為UTF8,這就說明客戶端資料到了伺服器端後一定會出現亂碼。既然不能修改控制檯的編碼,那麼只能修改character_set_client為GBK了。

伺服器傳送給客戶端的資料編碼為character_set_result,它如果是UTF8,那麼控制檯使用GBK解碼也一定會出現亂碼。因為無法修改控制檯編碼,所以只能把character_set_result修改為GBK。

  • 修改character_set_client變數:set character_set_client=gbk;
  • 修改character_set_results變數:set character_set_results=gbk;

設定編碼只對當前連線有效,這說明每次登入MySQL提示符後都要去修改這兩個編碼,但可以通過修改配置檔案來處理這一問題。

2.3 MySQL工具

使用MySQL工具是不會出現亂碼的,因為它們會每次連線時都修改character_set_client、character_set_results、character_set_connection的編碼。這樣對my.ini上的配置覆蓋了,也就不會出現亂碼了。

3 備份和恢復資料

3.1 備份資料

在控制檯使用mysqldump命令可以用來生成指定資料庫的指令碼文字,但要注意,指令碼文字中只包含資料庫的內容,而不會存在建立資料庫的語句!所以在恢復資料時,還需要自已手動建立一個數據庫之後再去恢復資料。

mysqldump –u使用者名稱 –p密碼 資料庫名>生成的指令碼檔案路徑
mysqldump -uroot -proot mydb1>stu.sql

注意,mysqldump命令是在控制檯下執行,無需登入mysql!!!

3.2 恢復資料

執行SQL指令碼需要登入mysql,然後進入指定資料庫,才可以執行SQL指令碼!!!

執行SQL指令碼不只是用來恢復資料庫,也可以在平時編寫SQL指令碼,然後使用執行SQL 指令碼來操作資料庫!大家都知道,在黑屏下編寫SQL語句時,就算髮現了錯誤,可能也不能修改了。所以我建議大家使用指令碼檔案來編寫SQL程式碼,然後執行之!

#登入mysql後執行下面程式碼
source stu.sql
或者
mysql -uroot -p123 mydb1<stu.sql

注意,在執行指令碼時需要先行核查當前資料庫中的表是否與指令碼檔案中的語句有衝突!例如在指令碼檔案中存在create table a的語句,而當前資料庫中已經存在了a表,那麼就會出錯!

4 多表查詢

多表查詢有如下幾種:

  • 合併結果集;
  • 連線查詢

​ 內連線

​ 外連線

​ 左外連線

​ 右外連線

​ 全外連線(MySQL不支援)

​ 自然連線

  • 子查詢

4.1 合併結果集

  1. 作用:合併結果集就是把兩個select語句的查詢結果合併到一起!
  2. 合併結果集有兩種方式:
    • UNION:去除重複記錄,例如:SELECT * FROM t1 UNION SELECT * FROM t2;
    • UNION ALL:不去除重複記錄,例如:SELECT * FROM t1 UNION ALL SELECT * FROM t2。
  3. 要求:被合併的兩個結果:列數、列型別必須相同。

t1表

a b
1 a
2 b
3 c
4 d

t2表

c d
3 c
4 d
5 e

執行SELECT * FROM t1 UNION ALL SELECT * FROM t2

結果:

a b
1 a
2 b
3 c
3 c
4 d
4 d
5 e

4.2 連線查詢

連線查詢就是求出多個表的乘積,例如t1連線t2,那麼查詢出的結果就是t1*t2。

mysql> select * from t1,t2;
+------+------+------+------+
| a    | b    | c    | d    |
+------+------+------+------+
|    1 | a    |    3 | c    |
|    1 | a    |    4 | d    |
|    1 | a    |    5 | e    |
|    2 | b    |    3 | c    |
|    2 | b    |    4 | d    |
|    2 | b    |    5 | e    |
|    3 | c    |    3 | c    |
|    3 | c    |    4 | d    |
|    3 | c    |    5 | e    |
|    4 | d    |    3 | c    |
|    4 | d    |    4 | d    |
|    4 | d    |    5 | e    |
+------+------+------+------+
12 rows in set (0.00 sec)

連線查詢會產生笛卡爾積,假設集合A={a,b},集合B={0,1,2},則兩個集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以擴充套件到多個集合的情況。

那麼多表查詢產生這樣的結果並不是我們想要的,那麼怎麼去除重複的,不想要的記錄呢,當然是通過條件過濾。通常要查詢的多個表之間都存在關聯關係,那麼就通過關聯關係去除笛卡爾積。

你能想像到emp和dept表連線查詢的結果麼?emp一共14行記錄,dept表一共4行記錄,那麼連線後查詢出的結果是56行記錄。

也就你只是想在查詢emp表的同時,把每個員工的所在部門資訊顯示出來,那麼就需要使用主外來鍵來去除無用資訊了。

例項

DROP DATABASE IF EXISTS exam;
CREATE DATABASE IF NOT EXISTS exam;

USE exam;

/*建立部門表*/
CREATE TABLE dept(
	deptno		INT 	PRIMARY KEY,
	dname		VARCHAR(50),
	loc 		VARCHAR(50)
);

/*建立僱員表*/
CREATE TABLE emp(
	empno		INT 	PRIMARY KEY,
	ename		VARCHAR(50),
	job		VARCHAR(50),
	mgr		INT,
	hiredate	DATE,
	sal		DECIMAL(7,2),
	COMM 		DECIMAL(7,2),
	deptno		INT,
	CONSTRAINT fk_emp FOREIGN KEY(mgr) REFERENCES emp(empno)
);

/*建立工資等級表*/
CREATE TABLE salgrade(
	grade		INT 	PRIMARY KEY,
	losal		INT,
	hisal		INT
);

/*建立學生表*/
CREATE TABLE stu(
	sid		INT 	PRIMARY KEY,
	sname		VARCHAR(50),
	age		INT,
	gander		VARCHAR(10),
	province	VARCHAR(50),
	tuition		INT
);







/*插入dept表資料*/
INSERT INTO dept VALUES (10, '教研部', '北京');
INSERT INTO dept VALUES (20, '學工部', '上海');
INSERT INTO dept VALUES (30, '銷售部', '廣州');
INSERT INTO dept VALUES (40, '財務部', '武漢');

/*插入emp表資料*/
INSERT INTO emp VALUES (1009, '曾阿牛', '董事長', NULL, '2001-11-17', 50000, NULL, 10);
INSERT INTO emp VALUES (1004, '劉備', '經理', 1009, '2001-04-02', 29750, NULL, 20);
INSERT INTO emp VALUES (1006, '關羽', '經理', 1009, '2001-05-01', 28500, NULL, 30);
INSERT INTO emp VALUES (1007, '張飛', '經理', 1009, '2001-09-01', 24500, NULL, 10);
INSERT INTO emp VALUES (1008, '諸葛亮', '分析師', 1004, '2007-04-19', 30000, NULL, 20);
INSERT INTO emp VALUES (1013, '龐統', '分析師', 1004, '2001-12-03', 30000, NULL, 20);
INSERT INTO emp VALUES (1002, '黛綺絲', '銷售員', 1006, '2001-02-20', 16000, 3000, 30);
INSERT INTO emp VALUES (1003, '殷天正', '銷售員', 1006, '2001-02-22', 12500, 5000, 30);
INSERT INTO emp VALUES (1005, '謝遜', '銷售員', 1006, '2001-09-28', 12500, 14000, 30);
INSERT INTO emp VALUES (1010, '韋一笑', '銷售員', 1006, '2001-09-08', 15000, 0, 30);
INSERT INTO emp VALUES (1012, '程普', '文員', 1006, '2001-12-03', 9500, NULL, 30);
INSERT INTO emp VALUES (1014, '黃蓋', '文員', 1007, '2002-01-23', 13000, NULL, 10);
INSERT INTO emp VALUES (1011, '周泰', '文員', 1008, '2007-05-23', 11000, NULL, 20);


INSERT INTO emp VALUES (1001, '甘寧', '文員', 1013, '2000-12-17', 8000, NULL, 20);


/*插入salgrade表資料*/
INSERT INTO salgrade VALUES (1, 7000, 12000);
INSERT INTO salgrade VALUES (2, 12010, 14000);
INSERT INTO salgrade VALUES (3, 14010, 20000);
INSERT INTO salgrade VALUES (4, 20010, 30000);
INSERT INTO salgrade VALUES (5, 30010, 99990);

/*插入stu表資料*/
INSERT INTO `stu` VALUES ('1', '王永', '23', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('2', '張雷', '25', '男', '遼寧', '2500');
INSERT INTO `stu` VALUES ('3', '李強', '22', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('4', '宋永合', '25', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('5', '敘美麗', '23', '女', '北京', '1000');
INSERT INTO `stu` VALUES ('6', '陳寧', '22', '女', '山東', '2500');
INSERT INTO `stu` VALUES ('7', '王麗', '21', '女', '北京', '1600');
INSERT INTO `stu` VALUES ('8', '李永', '23', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('9', '張玲', '23', '女', '廣州', '2500');
INSERT INTO `stu` VALUES ('10', '啊歷', '18', '男', '山西', '3500');
INSERT INTO `stu` VALUES ('11', '王剛', '23', '男', '湖北', '4500');
INSERT INTO `stu` VALUES ('12', '陳永', '24', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('13', '李雷', '24', '男', '遼寧', '2500');
INSERT INTO `stu` VALUES ('14', '李沿', '22', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('15', '王小明', '25', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('16', '王小麗', '23', '女', '北京', '1000');
INSERT INTO `stu` VALUES ('17', '唐寧', '22', '女', '山東', '2500');
INSERT INTO `stu` VALUES ('18', '唐麗', '21', '女', '北京', '1600');
INSERT INTO `stu` VALUES ('19', '啊永', '23', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('20', '唐玲', '23', '女', '廣州', '2500');
INSERT INTO `stu` VALUES ('21', '敘剛', '18', '男', '山西', '3500');
INSERT INTO `stu` VALUES ('22', '王累', '23', '男', '湖北', '4500');
INSERT INTO `stu` VALUES ('23', '趙安', '23', '男', '北京', '1500');
INSERT INTO `stu` VALUES (
            
           

相關推薦

MySQL學習筆記()-約束查詢

MySQL學習筆記(三) 1 完整性約束 完整性約束是為了表的資料的正確性!如果資料不正確,那麼一開始就不能新增到表中。 1.1 主鍵 當某一列添加了主鍵約束後,那麼這一列的資料就不能重複出現。這樣每行記錄中其主鍵列的值就是這一行的唯一標識。例如學生的學號可以

MySQL學習、分組查詢查詢

一、分組查詢1.MySQL查詢函式    函式的分類:    1,單行函式:將每條資料進行獨立的計算,然後每條資料得到一條結果。    2,多行函式:多條資料同時計算,最終得到一條結果資料。也成為聚集函式、分組函式, 主要用於完成一些統計功能。2.什麼是分組?    針對於班

MYSQL學習筆記:日期時間函數

div content minute name top fonts table hmm 指定 MYSQL學習筆記三:日期和時間函數 1. 獲取當前日期的函數和獲取當前時間的函數 /*獲取當前日期的函數和獲取當前時間的函數。將日期以‘YYYY-MM-DD‘或者’YYYYM

MySQL約束條件查詢方式詳解

left join 思考 mar 提高 詳解 union 存儲 class mys 一、約束什麽是約束?簡述:除了數據類型以外的約束的為什麽使用約束?簡述:為了保證數據的合法性 完整性;二、約束分類:  not null 跟整型時使用其作用是限制插入數據不能為空 crea

【JAVAEE學習筆記】hibernate03:操作,級聯練習:添加聯系人

row tac 默認值 rac user except pro intra com 一、一對多|多對一 1、關系表達  表中的表達      實體中的表達      orm元數據中表達     一對多 <!-- 集合,一對多關系,在配置文件中配置 -

MySQL學習筆記:生成時間維度2

RM -- date con xxx delet mage set 維度表   實現目的:      測試: # 測試 加一秒 SELECT DATE_SUB(DATE_ADD(CURRENT_DATE(), INTERVAL 1 SECOND), INTERVAL 1

csdn學習筆記:meta元、元方法 __index, __newindex、rawset、rawget

重要:在表和元表的__index 和 __newindex 都沒有需要操作的key時,賦值table操作會呼叫__newindex, 取值操作會呼叫__index    元表設定setmetatable t1 = {}; t2 = {}; print("t1=",

mysql之單查詢查詢

註釋:單表查詢就是記錄的詳細操作(增刪查,改的需求以及方法比較多) 一,複製表(索引和自增的屬性不能複製,需要自己新增) 拷貝結構以及資料 create table 新表名 select * from 舊錶名; 例:create table copy_customer

MySQL查詢語句查詢(重點)

一、單表查詢: 1.簡單查詢 –查詢所有的欄位:      select * from 表名 ; - - 查詢指定的欄位:      select 欄位1,欄位2… from 表名 ; - - 表別名 : 別名中

csdn學習筆記:meta元、元方法 __index, __newindex、rawset、rawget

重要:在表和元表的__index 和 __newindex 都沒有需要操作的key時,賦值table操作會呼叫__newindex, 取值操作會呼叫__index  元表設定setmetatable t1 = {}; t2 = {}; print("t1=",t1);

SSM框架學習-MyBatis篇 SQL對映檔案——實現高階結果對映查詢

SSM框架學習-MyBatis篇 SQL對映檔案——實現高階結果對映(多表查詢) 問題情境:比如有張表,使用者和使用者詳情,這兩張表裡面沒長表都有一個id欄位,這兩個表的id欄位都是對應的。 實體類裡面分別對應兩個實體類,user和userdetail,還有一個很重要的實

mysql學習筆記--關於索引

就是 扇區 性能 滿足 效率 而是 緩存 memcach 掃描 當一個表的數據量達到一定程度時,查詢速度會急速下降,這時候就需要適當地添加索引來加快查詢速度。雖然在日常工作中會經常接觸到索引,上周翼賽用戶登錄部分,當通過oauth_id查詢race_user_oauth_t

SQL筆記一:單查詢查詢

軟體相關不可避免的要用到資料庫相關技巧,對於測試來說最重要的是掌握資料庫的查詢技巧。 1.單表查詢 1.1無條件查詢特定欄位 語法:select 欄位A,欄位B……,欄位N from 表名 ,例如:select id,name from student      在stud

c++學習筆記(13) 繼承

繼承:從已有的類派生出新類 基類和派生類 不同的類之間可能有很多共通的屬性和行為,這些屬性和行為允許在一個類中通用化並被其他類所共享。類C1從類C2擴充套件而來,則C1稱為派生類,C2稱為基類,基類也稱為父類或者超類,派生類稱為子類,一個子類繼承了其父類所有可訪問的資料域和函式。同時可以增加

mysql學習(5):之間的關係

mysql相互關聯的表之間存在一對一,一對多(多對一),多對多的關係。 1,一對一的關係 這種關係即多個表具有相同的主鍵,實際中用的並不多,因為完全可以將這種關係的合併為同一張表。 2,一對多(多對一)的關係 其中表1的主鍵是表2的外來鍵(即表1的某欄位作為主鍵,表2的相同

MYSQL學習筆記——資料庫的基本操作

1.      建立資料庫  MySQL安裝完成後,會在其data目錄下建立幾個必需的資料庫,可以用“show databases;”檢視當前存在的所有資料庫。 1.1建立資料庫是在系統磁碟上劃分一塊區域用於資料的儲存和管理。 1.2MySQL中建立資料庫的基本SQL語法:

mysql新建查詢,練習題

DROP TABLE IF EXISTS  cart; CREATE TABLE  cart(  id int primary key auto_increment, memberId int,  comment test , ); 假如cart表存在就清除表

GO 學習筆記 () : method interface

為了面向物件(首先你得有個物件) method 定義一個method type Person struct { name string age int } func (p

SSM學習筆記(一)——聯查

在剛剛接觸SSM的時候,最初遇到的難題便是多表聯查的問題。mybatis由於他的特性一般情況下對映的結果與pojo(entity)實體類裡面的屬性都是一一對應的。所以如果是多張表聯合查詢然後返回結果集的話,由於存在pojo裡面的屬性不全的問題無法完成對映,因為這個問題糾結了

Oracle子查詢查詢

左外連接 查詢 sele 多表查詢 字段 ora 需要 avg lar 多表查詢需要用到表的連接 連接可以分為:(自行百度)   交叉連接(數字邏輯的笛卡爾積,不做解釋)     等值連接       例如:select * from t_a, t_b where t_a.