本節內容
1、數據庫介紹
2、mysql管理
3、mysql數據類型
4、常用mysql命令
創建數據庫
外鍵
增刪改查表
5、事務
6、索引
7、python 操作mysql
8、ORM sqlachemy學習
1、數據庫介紹
什么是數據庫?
數據庫(Database)是按照數據結構來組織、存儲和管理數據的倉庫,
每個數據庫都有一個或多個不同的API用於創建,訪問,管理,搜索和復制所保存的數據。
我們也可以將數據存儲在文件中,但是在文件中讀寫數據速度相對較慢。
所以,現在我們使用關系型數據庫管理系統(RDBMS)來存儲和管理的大數據量。所謂的關系型數據庫,是建立在關系模型基礎上的數據庫,借助於集合代數等數學概念和方法來處理數據庫中的數據。
RDBMS即關系數據庫管理系統(Relational Database Management System)的特點:
1.數據以表格的形式出現
2.每行為各種記錄名稱
3.每列為記錄名稱所對應的數據域
4.許多的行和列組成一張表單
5.若干的表單組成database
RDBMS 術語
在我們開始學習MySQL 數據庫前,讓我們先了解下RDBMS的一些術語:
- 數據庫: 數據庫是一些關聯表的集合。.
- 數據表: 表是數據的矩陣。在一個數據庫中的表看起來像一個簡單的電子表格。
- 列: 一列(數據元素) 包含了相同的數據, 例如郵政編碼的數據。
- 行:一行(=元組,或記錄)是一組相關的數據,例如一條用戶訂閱的數據。
- 冗余:存儲兩倍數據,冗余可以使系統速度更快。(表的規范化程度越高,表與表之間的關系就越多;查詢時可能經常需要在多個表之間進行連接查詢;而進行連接操作會降低查詢速度。例如,學生的信息存儲在student表中,院系信息存儲在department表中。通過student表中的dept_id字段與department表建立關聯關系。如果要查詢一個學生所在系的名稱,必須從student表中查找學生所在院系的編號(dept_id),然后根據這個編號去department查找系的名稱。如果經常需要進行這個操作時,連接查詢會浪費很多的時間。因此可以在student表中增加一個冗余字段dept_name,該字段用來存儲學生所在院系的名稱。這樣就不用每次都進行連接操作了。)
- 主鍵:主鍵是唯一的。一個數據表中只能包含一個主鍵。你可以使用主鍵來查詢數據。
- 外鍵:外鍵用於關聯兩個表。
- 復合鍵:復合鍵(組合鍵)將多個列作為一個索引鍵,一般用於復合索引。
- 索引:使用索引可快速訪問數據庫表中的特定信息。索引是對數據庫表中一列或多列的值進行排序的一種結構。類似於書籍的目錄。
- 參照完整性: 參照的完整性要求關系中不允許引用不存在的實體。與實體完整性是關系模型必須滿足的完整性約束條件,目的是保證數據的一致性。
Mysql數據庫
Mysql是最流行的關系型數據庫管理系統,在WEB應用方面MySQL是最好的RDBMS(Relational Database Management System:關系數據庫管理系統)應用軟件之一。由瑞典MySQL AB公司開發,目前屬於Oracle公司。MySQL是一種關聯數據庫管理系統,關聯數據庫將數據保存在不同的表中,而不是將所有數據放在一個大倉庫內,這樣就增加了速度並提高了靈活性。
- Mysql是開源的,所以你不需要支付額外的費用。
- Mysql支持大型的數據庫。可以處理擁有上千萬條記錄的大型數據庫。
- MySQL使用標准的SQL數據語言形式。
- Mysql可以允許於多個系統上,並且支持多種語言。這些編程語言包括C、C++、Python、Java、Perl、PHP、Eiffel、Ruby和Tcl等。
- Mysql對PHP有很好的支持,PHP是目前最流行的Web開發語言。
- MySQL支持大型數據庫,支持5000萬條記錄的數據倉庫,32位系統表文件最大可支持4GB,64位系統支持最大的表文件為8TB。
- Mysql是可以定制的,采用了GPL協議,你可以修改源碼來開發自己的Mysql系統。
2、mysql管理
MySQL 用戶設置
如果你需要添加 MySQL 用戶,你只需要在 mysql 數據庫中的 user 表添加新用戶即可。
以下為添加用戶的的實例,用戶名為lisi,密碼為12345678,並授權用戶可進行 SELECT, INSERT 和 UPDATE操作權限:
1 insert into user(host,user,password,select_priv,insert_priv,update_priv) values ('localhost','lisi',password('12345678'),'y','y','y');
1 flush privileges;
管理MySQL的命令
以下列出了使用Mysql數據庫過程中常用的命令:
-
USE 數據庫名 :選擇要操作的Mysql數據庫,使用該命令后所有Mysql命令都只針對該數據庫。
-
SHOW DATABASES: 列出 MySQL 數據庫管理系統的數據庫列表。
-
SHOW TABLES: #顯示指定數據庫的所有表,使用該命令前需要使用 use命令來選擇要操作的數據庫。
-
SHOW COLUMNS FROM 數據表: #顯示數據表的屬性,屬性類型,主鍵信息 ,是否為 NULL,默認值等其他信息。
-
create database testdb charset "utf8"; #創建一個叫testdb的數據庫,且讓其支持中文
-
drop database testdb; #刪除數據庫
-
SHOW INDEX FROM 數據表:顯示數據表的詳細索引信息,包括PRIMARY KEY(主鍵)。
3、mysql數據類型
MySQL中定義數據字段的類型對你數據庫的優化是非常重要的。
MySQL支持多種類型,大致可以分為三類:數值、日期/時間和字符串(字符)類型。
數值類型
MySQL支持所有標准SQL數值數據類型。
這些類型包括嚴格數值數據類型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似數值數據類型(FLOAT、REAL和DOUBLE PRECISION)。
關鍵字INT是INTEGER的同義詞,關鍵字DEC是DECIMAL的同義詞。
BIT數據類型保存位字段值,並且支持MyISAM、MEMORY、InnoDB和BDB表。
作為SQL標准的擴展,MySQL也支持整數類型TINYINT、MEDIUMINT和BIGINT。下面的表顯示了需要的每個整數類型的存儲和范圍。
類型 | 大小 | 范圍(有符號) | 范圍(無符號) | 用途 |
---|---|---|---|---|
TINYINT | 1 字節 | (-128,127) | (0,255) | 小整數值 |
SMALLINT | 2 字節 | (-32 768,32 767) | (0,65 535) | 大整數值 |
MEDIUMINT | 3 字節 | (-8 388 608,8 388 607) | (0,16 777 215) | 大整數值 |
INT或INTEGER | 4 字節 | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整數值 |
BIGINT | 8 字節 | (-9 233 372 036 854 775 808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 極大整數值 |
FLOAT | 4 字節 | (-3.402 823 466 E+38,1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 單精度 浮點數值 |
DOUBLE | 8 字節 | (1.797 693 134 862 315 7 E+308,2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 雙精度 浮點數值 |
DECIMAL | 對DECIMAL(M,D) ,如果M>D,為M+2否則為D+2 | 依賴於M和D的值 | 依賴於M和D的值 | 小數值 |
日期和時間類型
表示時間值的日期和時間類型為DATETIME、DATE、TIMESTAMP、TIME和YEAR。
每個時間類型有一個有效值范圍和一個"零"值,當指定不合法的MySQL不能表示的值時使用"零"值。
TIMESTAMP類型有專有的自動更新特性,將在后面描述。
類型 | 大小 (字節) |
范圍 | 格式 | 用途 |
---|---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 時間值或持續時間 |
YEAR | 1 | 1901/2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和時間值 |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2037 年某時 | YYYYMMDD HHMMSS | 混合日期和時間值,時間戳 |
字符串類型
字符串類型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。該節描述了這些類型如何工作以及如何在查詢中使用這些類型。
類型 | 大小 | 用途 |
---|---|---|
CHAR | 0-255字節 | 定長字符串 |
VARCHAR | 0-65535 字節 | 變長字符串 |
TINYBLOB | 0-255字節 | 不超過 255 個字符的二進制字符串 |
TINYTEXT | 0-255字節 | 短文本字符串 |
BLOB | 0-65 535字節 | 二進制形式的長文本數據 |
TEXT | 0-65 535字節 | 長文本數據 |
MEDIUMBLOB | 0-16 777 215字節 | 二進制形式的中等長度文本數據 |
MEDIUMTEXT | 0-16 777 215字節 | 中等長度文本數據 |
LONGBLOB | 0-4 294 967 295字節 | 二進制形式的極大文本數據 |
LONGTEXT | 0-4 294 967 295字節 | 極大文本數據 |
CHAR和VARCHAR類型類似,但它們保存和檢索的方式不同。它們的最大長度和是否尾部空格被保留等方面也不同。在存儲或檢索過程中不進行大小寫轉換。
BINARY和VARBINARY類類似於CHAR和VARCHAR,不同的是它們包含二進制字符串而不要非二進制字符串。也就是說,它們包含字節字符串而不是字符字符串。這說明它們沒有字符集,並且排序和比較基於列值字節的數值值。
BLOB是一個二進制大對象,可以容納可變數量的數據。有4種BLOB類型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它們只是可容納值的最大長度不同。
有4種TEXT類型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。這些對應4種BLOB類型,有相同的最大長度和存儲需求
4、常用mysql命令
創建數據庫
語法
1 CREATE TABLE table_name (column_name column_type);
創建一個student表
create table student(stu_id int not null auto_increment, name char(32) not null, age int not null, register_date date, primary key (stu_id));
實例解析:
- 如果你不想字段為 NULL 可以設置字段的屬性為 NOT NULL, 在操作數據庫時如果輸入該字段的數據為NULL ,就會報錯。
- AUTO_INCREMENT定義列為自增的屬性,一般用於主鍵,數值會自動加1。
- PRIMARY KEY關鍵字用於定義列為主鍵。 您可以使用多列來定義主鍵,列間以逗號分隔。
MySQL 插入數據
語法
1 INSERT INTO table_name ( field1, field2,...fieldN ) 2 VALUES 3 ( value1, value2,...valueN );
1 mysql> insert into student (name,age,register_date) values ("zhangsan",22,"2016-10-26"); 2 Query OK, 1 row affected (0.00 sec) 3 4 mysql> select * from student; 5 +--------+----------+-----+---------------+ 6 | stu_id | name | age | register_date | 7 +--------+----------+-----+---------------+ 8 | 1 | zhangsan | 22 | 2016-10-26 | 9 +--------+----------+-----+---------------+ 10 1 row in set (0.00 sec)
MySQL 查詢數據
語法
1 SELECT column_name,column_name 2 FROM table_name 3 [WHERE Clause] 4 [OFFSET M ][LIMIT N]
1 mysql> select * from student; 2 +--------+-----------+-----+---------------+ 3 | stu_id | name | age | register_date | 4 +--------+-----------+-----+---------------+ 5 | 1 | zhangsan | 22 | 2016-10-26 | 6 | 2 | zhangsan1 | 23 | 2016-10-27 | 7 | 3 | zhangsan2 | 24 | 2016-10-28 | 8 | 4 | zhangsan3 | 25 | 2016-10-29 | 9 +--------+-----------+-----+---------------+ 10 4 rows in set (0.00 sec) 11 12 方法一: 13 mysql> select name from student where name="zhangsan2"; 14 +-----------+ 15 | name | 16 +-----------+ 17 | zhangsan2 | 18 +-----------+ 19 1 row in set (0.00 sec) 20 21 方法二: 22 mysql> select name,age from student where name="zhangsan2" and age=24; 23 +-----------+-----+ 24 | name | age | 25 +-----------+-----+ 26 | zhangsan2 | 24 | 27 +-----------+-----+ 28 1 row in set (0.00 sec)
- 查詢語句中你可以使用一個或者多個表,表之間使用逗號(,)分割,並使用WHERE語句來設定查詢條件。
- SELECT 命令可以讀取一條或者多條記錄。
- 你可以使用星號(*)來代替其他字段,SELECT語句會返回表的所有字段數據
- 你可以使用 WHERE 語句來包含任何條件。
- 你可以通過OFFSET指定SELECT語句開始查詢的數據偏移量。默認情況下偏移量為0。
- 你可以使用 LIMIT 屬性來設定返回的記錄數。
1 mysql> select * from student; 2 +--------+-----------+-----+---------------+ 3 | stu_id | name | age | register_date | 4 +--------+-----------+-----+---------------+ 5 | 1 | zhangsan | 22 | 2016-10-26 | 6 | 2 | zhangsan1 | 23 | 2016-10-27 | 7 | 3 | zhangsan2 | 24 | 2016-10-28 | 8 | 4 | zhangsan3 | 25 | 2016-10-29 | 9 +--------+-----------+-----+---------------+ 10 4 rows in set (0.00 sec)
1 #limit相當於從表中的第幾條開始查詢,offset代表從前面第幾條開始計算的第幾條數據。(包含limit那行) 2 方法一: 3 mysql> select * from student limit 2 offset 1; 4 +--------+-----------+-----+---------------+ 5 | stu_id | name | age | register_date | 6 +--------+-----------+-----+---------------+ 7 | 2 | zhangsan1 | 23 | 2016-10-27 | 8 | 3 | zhangsan2 | 24 | 2016-10-28 | 9 +--------+-----------+-----+---------------+ 10 2 rows in set (0.00 sec) 11 12 13 #下面這個少了個offset,完全就變了。下面說明是從limit指定條開始讀,后面1代表讀幾行。 14 方法二: 15 mysql> select * from student limit 2,1; 16 +--------+-----------+-----+---------------+ 17 | stu_id | name | age | register_date | 18 +--------+-----------+-----+---------------+ 19 | 3 | zhangsan2 | 24 | 2016-10-28 | 20 +--------+-----------+-----+---------------+ 21 1 row in set (0.00 sec)
MySQL where 子句
語法
1 SELECT field1, field2,...fieldN FROM table_name1, table_name2... 2 [WHERE condition1 [AND [OR]] condition2.....
以下為操作符列表,可用於 WHERE 子句中。
下表中實例假定 A為10 B為20
操作符 | 描述 | 實例 |
---|---|---|
= | 等號,檢測兩個值是否相等,如果相等返回true | (A = B) 返回false。 |
<>, != | 不等於,檢測兩個值是否相等,如果不相等返回true | (A != B) 返回 true。 |
> | 大於號,檢測左邊的值是否大於右邊的值, 如果左邊的值大於右邊的值返回true | (A > B) 返回false。 |
< | 小於號,檢測左邊的值是否小於右邊的值, 如果左邊的值小於右邊的值返回true | (A < B) 返回 true。 |
>= | 大於等於號,檢測左邊的值是否大於或等於右邊的值, 如果左邊的值大於或等於右邊的值返回true | (A >= B) 返回false。 |
<= | 小於等於號,檢測左邊的值是否小於於或等於右邊的值, 如果左邊的值小於或等於右邊的值返回true | (A <= B) 返回 true。 |
使用主鍵來作為 WHERE 子句的條件查詢是非常快速的。
1 mysql> select * from student where age > 24; 2 +--------+-----------+-----+---------------+ 3 | stu_id | name | age | register_date | 4 +--------+-----------+-----+---------------+ 5 | 4 | zhangsan3 | 25 | 2016-10-29 | 6 +--------+-----------+-----+---------------+ 7 1 row in set (0.00 sec)
MySQL UPDATE 查詢
語法
1 mysql> select * from student; 2 +--------+-----------+-----+---------------+ 3 | stu_id | name | age | register_date | 4 +--------+-----------+-----+---------------+ 5 | 1 | zhangsan | 22 | 2016-10-26 | 6 | 2 | zhangsan1 | 23 | 2016-10-27 | 7 | 3 | zhangsan2 | 24 | 2016-10-28 | 8 | 4 | zhangsan3 | 25 | 2016-10-29 | 9 +--------+-----------+-----+---------------+ 10 4 rows in set (0.00 sec) 11 12 mysql> update student set age=28 where name="zhangsan3" and age="25"; 13 Query OK, 1 row affected (0.00 sec) 14 Rows matched: 1 Changed: 1 Warnings: 0 15 16 mysql> select * from student; 17 +--------+-----------+-----+---------------+ 18 | stu_id | name | age | register_date | 19 +--------+-----------+-----+---------------+ 20 | 1 | zhangsan | 22 | 2016-10-26 | 21 | 2 | zhangsan1 | 23 | 2016-10-27 | 22 | 3 | zhangsan2 | 24 | 2016-10-28 | 23 | 4 | zhangsan3 | 28 | 2016-10-29 | 24 +--------+-----------+-----+---------------+ 25 4 rows in set (0.00 sec)
MySQL DELETE 語句
語法:
1 DELETE FROM table_name [WHERE Clause]<br><br>delete from student where stu_id=5;
例如:
1 mysql> delete from student where name="zhangsan3" and age=28; 2 Query OK, 1 row affected (0.00 sec) 3 4 mysql> select * from student; 5 +--------+-----------+-----+---------------+ 6 | stu_id | name | age | register_date | 7 +--------+-----------+-----+---------------+ 8 | 1 | zhangsan | 22 | 2016-10-26 | 9 | 2 | zhangsan1 | 23 | 2016-10-27 | 10 | 3 | zhangsan2 | 24 | 2016-10-28 | 11 +--------+-----------+-----+---------------+ 12 3 rows in set (0.00 sec)
MySQL LIKE 子句
語法:
1 SELECT field1, field2,...fieldN table_name1, table_name2... 2 WHERE field1 LIKE condition1 [AND [OR]] filed2 = 'somevalue' 3 4 5 select *from student where name binary like "%Li"; 6 select *from student where name binary like binary "%Li"; #只匹配大寫
例如:
1 mysql> select * from student where name like "zhang%"; 2 +--------+-----------+-----+---------------+ 3 | stu_id | name | age | register_date | 4 +--------+-----------+-----+---------------+ 5 | 1 | zhangsan | 22 | 2016-10-26 | 6 | 2 | zhangsan1 | 23 | 2016-10-27 | 7 | 3 | zhangsan2 | 24 | 2016-10-28 | 8 | 5 | zhangsan3 | 25 | 2016-10-29 | 9 +--------+-----------+-----+---------------+ 10 4 rows in set (0.00 sec) 11 12 mysql> select * from student where age like "24"; 13 +--------+-----------+-----+---------------+ 14 | stu_id | name | age | register_date | 15 +--------+-----------+-----+---------------+ 16 | 3 | zhangsan2 | 24 | 2016-10-28 | 17 +--------+-----------+-----+---------------+ 18 1 row in set (0.00 sec)
MySQL 排序
1 SELECT field1, field2,...fieldN from table_name1, table_name2... 2 ORDER BY field1, [field2...] [ASC [DESC]] 3 使用 ASC 或 DESC 關鍵字來設置查詢結果是按升序或降序排列。 默認情況下,它是按升序排列。
例如:
1 mysql> select * from student; 2 +--------+-----------+-----+---------------+ 3 | stu_id | name | age | register_date | 4 +--------+-----------+-----+---------------+ 5 | 1 | zhangsan | 22 | 2016-10-26 | 6 | 2 | zhangsan1 | 23 | 2016-10-27 | 7 | 3 | zhangsan2 | 24 | 2016-10-28 | 8 | 5 | zhangsan3 | 25 | 2016-10-29 | 9 | 6 | ZHANGSAN4 | 26 | 2016-10-30 | 10 +--------+-----------+-----+---------------+ 11 5 rows in set (0.00 sec) 12 13 mysql> select age from student order by age DESC; 14 +-----+ 15 | age | 16 +-----+ 17 | 26 | 18 | 25 | 19 | 24 | 20 | 23 | 21 | 22 | 22 +-----+ 23 5 rows in set (0.00 sec) 24 25 mysql> select age from student order by age asc; 26 +-----+ 27 | age | 28 +-----+ 29 | 22 | 30 | 23 | 31 | 24 | 32 | 25 | 33 | 26 | 34 +-----+ 35 5 rows in set (0.00 sec)
MySQL GROUP BY 語句
1 SELECT column_name, function(column_name) 2 FROM table_name 3 WHERE column_name operator value 4 GROUP BY column_name;
例如:
mysql> select * from student; +--------+-----------+-----+---------------+ | stu_id | name | age | register_date | +--------+-----------+-----+---------------+ | 1 | zhangsan | 22 | 2016-10-26 | | 2 | zhangsan1 | 23 | 2016-10-27 | | 3 | zhangsan2 | 24 | 2016-10-28 | | 5 | zhangsan3 | 25 | 2016-10-29 | | 6 | ZHANGSAN4 | 26 | 2016-10-30 | | 7 | zhangsan2 | 24 | 2016-10-25 | +--------+-----------+-----+---------------+ 6 rows in set (0.00 sec) #接下來我們使用 GROUP BY 語句 將數據表按名字進行分組,並統計每個人有多少條記錄: mysql> select name,count(*) from student group by name; +-----------+----------+ | name | count(*) | +-----------+----------+ | zhangsan | 1 | | zhangsan1 | 1 | | zhangsan2 | 2 | | zhangsan3 | 1 | | ZHANGSAN4 | 1 | +-----------+----------+ 5 rows in set (0.00 sec)
1 #使用 WITH ROLLUP
#我們模擬stu_id 就登陸數,統計一下總登錄量
2 mysql> select coalesce(name,"總數"), sum(stu_id) as singin_conut from student group by name with rollup; 3 +-------------------------+--------------+ 4 | coalesce(name,"總數") | singin_conut | 5 +-------------------------+--------------+ 6 | zhangsan | 1 | 7 | zhangsan1 | 2 | 8 | zhangsan2 | 10 | 9 | zhangsan3 | 5 | 10 | ZHANGSAN4 | 6 | 11 | 總數 | 24 | 12 +-------------------------+--------------+ 13 6 rows in set (0.00 sec) 14 15 其中記錄 NULL 表示所有人的登錄次數。<br> 16 我們可以使用 coalesce 來設置一個可以取代 NUll 的名稱,coalesce 語法: 17 mysql> select coalesce(name,"總數"), sum(stu_id) as singin_conut from student group by name with rollup;
MySQL ALTER命令
我們需要修改數據表名或者修改數據表字段時,就需要使用到MySQL ALTER命令。
刪除,添加或修改表字段
刪除字段:
1 mysql> alter table student drop register_date; 2 Query OK, 6 rows affected (0.01 sec) 3 Records: 6 Duplicates: 0 Warnings: 0 4 5 mysql> select * from student; 6 +--------+-----------+-----+ 7 | stu_id | name | age | 8 +--------+-----------+-----+ 9 | 1 | zhangsan | 22 | 10 | 2 | zhangsan1 | 23 | 11 | 3 | zhangsan2 | 24 | 12 | 5 | zhangsan3 | 25 | 13 | 6 | ZHANGSAN4 | 26 | 14 | 7 | zhangsan2 | 24 | 15 +--------+-----------+-----+ 16 6 rows in set (0.00 sec)
添加字段:
1 mysql> alter table student add singin int(32) not null; 2 Query OK, 6 rows affected (0.01 sec) 3 Records: 6 Duplicates: 0 Warnings: 0 4 5 mysql> select * from student; 6 +--------+-----------+-----+--------+ 7 | stu_id | name | age | singin | 8 +--------+-----------+-----+--------+ 9 | 1 | zhangsan | 22 | 0 | 10 | 2 | zhangsan1 | 23 | 0 | 11 | 3 | zhangsan2 | 24 | 0 | 12 | 5 | zhangsan3 | 25 | 0 | 13 | 6 | ZHANGSAN4 | 26 | 0 | 14 | 7 | zhangsan2 | 24 | 0 | 15 +--------+-----------+-----+--------+ 16 6 rows in set (0.00 sec)
修改字段類型及名稱
如果需要修改字段類型及名稱, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句 。
例如,把字段 c 的類型從 CHAR(1) 改為 CHAR(10),可以執行以下命令:
1 mysql> ALTER TABLE testalter_tbl MODIFY c CHAR(10);
使用 CHANGE 子句, 語法有很大的不同。 在 CHANGE 關鍵字之后,緊跟着的是你要修改的字段名,然后指定新字段名及類型。嘗試如下實例:
1 mysql> ALTER TABLE testalter_tbl CHANGE i j BIGINT; 3 mysql> ALTER TABLE testalter_tbl CHANGE j j INT;
ALTER TABLE 對 Null 值和默認值的影響
當你修改字段時,你可以指定是否包含只或者是否設置默認值。
以下實例,指定字段 j 為 NOT NULL 且默認值為100 。
1 mysql> ALTER TABLE testalter_tbl 2 -> MODIFY j BIGINT NOT NULL DEFAULT 100;
修改表名
1 mysql> ALTER TABLE testalter_tbl RENAME TO alter_tbl;
關於外鍵
外鍵,一個特殊的索引,用於關鍵2個表,只能是指定內容
1 mysql> create table class( 2 -> id int not null primary key, 3 -> name char(16)); 4 Query OK, 0 rows affected (0.02 sec) 5 6 7 CREATE TABLE `student2` ( 8 `id` int(11) NOT NULL, 9 `name` char(16) NOT NULL, 10 `class_id` int(11) NOT NULL, 11 PRIMARY KEY (`id`), 12 KEY `fk_class_key` (`class_id`), 13 CONSTRAINT `fk_class_key` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`) 14 ) 31 此時如果class 表中不存在id 1,student表也插入不了,這就叫外鍵約束 32 mysql> insert into student2(id,name,class_id) values(1,'alex', 1); 33 ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`testdb`.`student2`, CONSTRAINT `fk_class_key` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)) 34 35 36 37 mysql> insert into class(id,name) values(1,"linux"); 38 Query OK, 1 row affected (0.01 sec) 39 40 mysql> insert into student2(id,name,class_id) values(1,'alex', 1); 41 Query OK, 1 row affected (0.00 sec) 42 43 44 #如果有student表中跟這個class表有關聯的數據,你是不能刪除class表中與其關聯的紀錄的 45 mysql> delete from class where id =1; 46 ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`testdb`.`student2`, CONSTRAINT `fk_class_key` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))
MySQL NULL 值處理
我們已經知道MySQL使用 SQL SELECT 命令及 WHERE 子句來讀取數據表中的數據,但是當提供的查詢條件字段為 NULL 時,該命令可能就無法正常工作。
為了處理這種情況,MySQL提供了三大運算符:
IS NULL: 當列的值是NULL,此運算符返回true。
IS NOT NULL: 當列的值不為NULL, 運算符返回true。
<=>: 比較操作符(不同於=運算符),當比較的的兩個值為NULL時返回true。
關於 NULL 的條件比較運算是比較特殊的。你不能使用 = NULL 或 != NULL 在列中查找 NULL 值 。
在MySQL中,NULL值與任何其它值的比較(即使是NULL)永遠返回false,即 NULL = NULL 返回false 。
MySQL中處理NULL使用IS NULL和IS NOT NULL運算符。
Mysql 連接(left join, right join, inner join ,full join)
我們已經學會了如果在一張表中讀取數據,這是相對簡單的,但是在真正的應用中經常需要從多個數據表中讀取數據。
本章節我們將向大家介紹如何使用 MySQL 的 JOIN 在兩個或多個表中查詢數據。
你可以在SELECT, UPDATE 和 DELETE 語句中使用 Mysql 的 JOIN 來聯合多表查詢。
JOIN 按照功能大致分為如下三類:
- INNER JOIN(內連接,或等值連接):獲取兩個表中字段匹配關系的記錄。
- LEFT JOIN(左連接):獲取左表所有記錄,即使右表沒有對應匹配的記錄。
- RIGHT JOIN(右連接): 與 LEFT JOIN 相反,用於獲取右表所有記錄,即使左表沒有對應匹配的記錄。
Inner join(交集):
#交集 mysql> select * from A inner join B on A.id = B.id; +----+----+ | id | id | +----+----+ | 3 | 3 | | 4 | 4 | +----+----+ 2 rows in set (0.00 sec)
LEFT JOIN(差集)
1 mysql> select * from A left join B on A.id = B.id; 2 +----+------+ 3 | id | id | 4 +----+------+ 5 | 1 | NULL | 6 | 2 | NULL | 7 | 3 | 3 | 8 | 4 | 4 | 9 +----+------+ 10 4 rows in set (0.00 sec) 11 12 mysql> select * from B left join A on B.id = A.id; 13 +----+------+ 14 | id | id | 15 +----+------+ 16 | 3 | 3 | 17 | 4 | 4 | 18 | 5 | NULL | 19 | 6 | NULL | 20 | 7 | NULL | 21 | 8 | NULL | 22 +----+------+ 23 6 rows in set (0.00 sec)
Right join(其實就是left join相反)
1 mysql> select * from A right join B on A.id = B.id; 2 +------+----+ 3 | id | id | 4 +------+----+ 5 | 3 | 3 | 6 | 4 | 4 | 7 | NULL | 5 | 8 | NULL | 6 | 9 | NULL | 7 | 10 | NULL | 8 | 11 +------+----+ 12 6 rows in set (0.00 sec)
Full join(並集)
mysql 並不直接支持full join,but 總是難不到我們
1 mysql> select * from A left join B on A.id = B.id union select * from A right join B on A.id = B.id; 2 +------+------+ 3 | id | id | 4 +------+------+ 5 | 1 | NULL | 6 | 2 | NULL | 7 | 3 | 3 | 8 | 4 | 4 | 9 | NULL | 5 | 10 | NULL | 6 | 11 | NULL | 7 | 12 | NULL | 8 | 13 +------+------+ 14 8 rows in set (0.00 sec)
5、事務
MySQL 事務主要用於處理操作量大,復雜度高的數據。比如說,在人員管理系統中,你刪除一個人員,你即需要刪除人員的基本資料,也要刪除和該人員相關的信息,如信箱,文章等等,這樣,這些數據庫操作語句就構成一個事務!
- 在MySQL中只有使用了Innodb數據庫引擎的數據庫或表才支持事務
- 事務處理可以用來維護數據庫的完整性,保證成批的SQL語句要么全部執行,要么全部不執行
- 事務用來管理insert,update,delete語句
一般來說,事務是必須滿足4個條件(ACID): Atomicity(原子性)、Consistency(穩定性)、Isolation(隔離性)、Durability(可靠性)
- 1、事務的原子性:一組事務,要么成功;要么撤回。
- 2、穩定性 : 有非法數據(外鍵約束之類),事務撤回。
- 3、隔離性:事務獨立運行。一個事務處理后的結果,影響了其他事務,那么其他事務會撤回。事務的100%隔離,需要犧牲速度。
- 4、可靠性:軟、硬件崩潰后,InnoDB數據表驅動會利用日志文件重構修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit選項 決定什么時候吧事務保存到日志里。
重要:
我們知道mysql的引擎分為ISAM,MyIASM(ISAM的升級版),InnoDB。
1/ISAM
ISAM是一個定義明確且歷經時間考驗的數據表格管理方法,它在設計之時就考慮到數據庫被查詢的次數要遠大於更新的次數。因此,ISAM執行讀取操作的速度很快,而且不占用大量的內存和存儲資源。ISAM的兩個主要不足之處在於,它不支持事務處理,也不能夠容錯:如果你的硬盤崩潰了,那么數據文件就無法恢復了。如果你正在把ISAM用在關鍵任務應用程序里,那就必須經常備份你所有的實時數據,通過其復制特性,MySQL能夠支持這樣的備份應用程序。
2/InnoDB
它提供了事務控制能力功能,它確保一組命令全部執行成功,或者當任何一個命令出現錯誤時所有命令的結果都被回退,可以想像在電子銀行中事務控制能力是非常重要的。支持COMMIT、ROLLBACK和其他事務特性。最新版本的Mysql已經計划移除對BDB的支持,轉而全力發展InnoDB。
MyIASM是IASM表的新版本,有如下擴展:
二進制層次的可移植性。
NULL列索引。
對變長行比ISAM表有更少的碎片。
支持大文件。
更好的索引壓縮。
更好的鍵嗎統計分布。
更好和更快的auto_increment處理。
以下是一些細節和具體實現的差別:
1.InnoDB不支持FULLTEXT類型的索引。
2.InnoDB中不保存表的
具體行數,也就是說,執行select count(*) from
table時,InnoDB要掃描一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出保存好的行數即可。注意的是,當count(*)語句包含
where條件時,兩種表的操作是一樣的。
3.對於AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中,可以和其他字段一起建立聯合索引。
4.DELETE
FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。
5.LOAD TABLE FROM
MASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,導入數據后再改成InnoDB表,但是對於使用的額外的InnoDB特性(例如外鍵)的表不適用。
另外,InnoDB表的行鎖也不是絕對的,如果在執行一個SQL語句時MySQL不能確定要掃描的范圍,InnoDB表同樣會鎖全表,例如update
table set num=1 where name like “�a%”
任何一種表都不是萬能的,只用恰當的針對業務類型來選擇合適的表類型,才能最大的發揮MySQL的性能優勢.
MySQL
Administrator建數據庫的時候,表缺省是InnoDB類型。
InnoDB,MyISAM
兩種類型有什么區別:MyISAM類型不支持事務處理等高級處理,而InnoDB類型支持。
MyISAM類型的表強調的是性能,其執行數度比InnoDB類型更快,但是不提供事務支持,而InnoDB提供事務支持,外鍵等高級數據庫功能。
MyISAM類型的二進制數據文件可以在不同操作系統中遷移。也就是可以直接從Windows系統拷貝到linux系統中使用。
1 查看系統支持的存儲引擎
show engines;
2 查看表使用的存儲引擎
兩種方法:
a、show table status from db_name where name='table_name';
b、show create table table_name;
如果顯示的格式不好看,可以用\g代替行尾分號
有人說用第二種方法不准確,我試了下,關閉掉原先默認的Innodb引擎后根本無法執行show create table table_name指令,因為之前建的是Innodb表,關掉后默認用MyISAM引擎,導致Innodb表數據無法被正確讀取。
3 修改表引擎方法
alter table table_name engine=innodb;
4 關閉Innodb引擎方法
關閉mysql服務: net stop mysql
找到mysql安裝目錄下的my.ini文件:
找到default-storage-engine=INNODB 改為default-storage-engine=MYISAM
找到#skip-innodb 改為skip-innodb
啟動mysql服務:net start mysql
1 mysql> show create table C; 2 +-------+-----------------------------------------------------------------------------------------------------+ 3 | Table | Create Table | 4 +-------+-----------------------------------------------------------------------------------------------------+ 5 | C | CREATE TABLE `C` ( 6 `a` int(11) NOT NULL, 7 PRIMARY KEY (`a`) 8 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | 9 +-------+-----------------------------------------------------------------------------------------------------+ 10 1 row in set (0.00 sec) 11 12 mysql> begin; 13 Query OK, 0 rows affected (0.00 sec) 14 15 mysql> insert into C(a)values(1); 16 Query OK, 1 row affected (0.00 sec) 17 18 mysql> select * from C; 19 +---+ 20 | a | 21 +---+ 22 | 1 | 23 +---+ 24 1 row in set (0.00 sec) 25 26 mysql> rollback; 27 Query OK, 0 rows affected (0.00 sec) 28 29 mysql> select * from C; 30 Empty set (0.00 sec) 31 32 mysql>
注意: 如果開始一個事務的時候,直接commit;了就已經提交了,如果再想rollback就回不去了。
6、索引
MySQL索引的建立對於MySQL的高效運行是很重要的,索引可以大大提高MySQL的檢索速度。
打個比方,如果合理的設計且使用索引的MySQL是一輛蘭博基尼的話,那么沒有設計和使用索引的MySQL就是一個人力三輪車。
索引分單列索引和組合索引。單列索引,即一個索引只包含單個列,一個表可以有多個單列索引,但這不是組合索引。組合索引,即一個索包含多個列。
創建索引時,你需要確保該索引是應用在 SQL 查詢語句的條件(一般作為 WHERE 子句的條件)。
實際上,索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄。
上面都在說使用索引的好處,但過多的使用索引將會造成濫用。因此索引也會有它的缺點:雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對表進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數據,還要保存一下索引文件。建立索引會占用磁盤空間的索引文件。
普通索引
創建索引
這是最基本的索引,它沒有任何限制。它有以下幾種創建方式:
1 CREATE INDEX indexName ON mytable(username(length));
如果是CHAR,VARCHAR類型,length可以小於字段實際長度;如果是BLOB和TEXT類型,必須指定 length。
修改表結構
1 ALTER mytable ADD INDEX [indexName] ON (username(length))
創建表的時候直接指定
1 CREATE TABLE mytable( 2 3 ID INT NOT NULL, 4 5 username VARCHAR(16) NOT NULL, 6 7 INDEX [indexName] (username(length)) 8 9 );
刪除索引的語法
1 DROP INDEX [indexName] ON mytable;
唯一索引
它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創建方式:
創建索引

1 創建索引 2 CREATE UNIQUE INDEX indexName ON mytable(username(length)) 3 4 5 修改表結構 6 ALTER mytable ADD UNIQUE [indexName] ON (username(length)) 7 8 9 創建表的時候直接指定 10 CREATE TABLE mytable( 11 12 ID INT NOT NULL, 13 14 username VARCHAR(16) NOT NULL, 15 16 UNIQUE [indexName] (username(length)) 17 18 );
使用ALTER 命令添加和刪除索引

1 有四種方式來添加數據表的索引: 2 ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 該語句添加一個主鍵,這意味着索引值必須是唯一的,且不能為NULL。 3 ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 這條語句創建索引的值必須是唯一的(除了NULL外,NULL可能會出現多次)。 4 ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出現多次。 5 ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):該語句指定了索引為 FULLTEXT ,用於全文索引。 6 7 8 以下實例為在表中添加索引。 9 mysql> ALTER TABLE testalter_tbl ADD INDEX (c); 10 你還可以在 ALTER 命令中使用 DROP 子句來刪除索引。嘗試以下實例刪除索引: 11 mysql> ALTER TABLE testalter_tbl DROP INDEX (c);
使用 ALTER 命令添加和刪除主鍵

1 主鍵只能作用於一個列上,添加主鍵索引時,你需要確保該主鍵默認不為空(NOT NULL)。實例如下: 2 mysql> ALTER TABLE testalter_tbl MODIFY i INT NOT NULL; 3 mysql> ALTER TABLE testalter_tbl ADD PRIMARY KEY (i); 4 5 你也可以使用 ALTER 命令刪除主鍵: 6 mysql> ALTER TABLE testalter_tbl DROP PRIMARY KEY;
顯示索引信息
1 SHOW INDEX FROM table_name\G
mysql練習題 http://www.cnblogs.com/wupeiqi/articles/5729934.html
更多mysql知識,請看http://www.cnblogs.com/wupeiqi/articles/5713323.html
7、python 操作mysql
pymsql是Python中操作MySQL的模塊,其使用方法和MySQLdb幾乎相同。
安裝
1 easy_install pymysql
使用操作
1、執行SQL
1 import pymysql 2 3 # 創建連接 4 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1') 5 # 創建游標 6 cursor = conn.cursor() 7 8 # 執行SQL,並返回收影響行數 9 effect_row = cursor.execute("update hosts set host = '1.1.1.2'") 10 11 # 執行SQL,並返回受影響行數 12 #effect_row = cursor.execute("update hosts set host = '1.1.1.2' where nid > %s", (1,)) 13 14 # 執行SQL,並返回受影響行數 15 #effect_row = cursor.executemany("insert into hosts(host,color_id)values(%s,%s)", [("1.1.1.11",1),("1.1.1.11",2)]) 16 17 18 # 提交,不然無法保存新建或者修改的數據 19 conn.commit() 20 21 # 關閉游標 22 cursor.close() 23 # 關閉連接 24 conn.close()
具體操作
1 import pymysql 2 3 # 創建連接(相當於創建了一個socket連接) 4 conn = pymysql.connect(host='172.16.5.237', port=3306, user='root', passwd='12345678', db='oldboy') 5 6 # 創建游標#實時上我們的是cursor來取數據 7 cursor = conn.cursor() 8 9 # 執行SQL,並返回收影響行數 10 effect_row = cursor.execute("select * from A;") 11 # print(effect_row)#顯示表中有幾行 12 # print(cursor.fetchone())#取一行 13 # print(cursor.fetchall())#打印表中的所有數據 14 15 # 執行SQL,並返回受影響行數 16 #effect_row = cursor.execute("update hosts set host = '1.1.1.2' where nid > %s", (1,)) 17 18 # 執行SQL,並返回受影響行數 19 #effect_row = cursor.executemany("insert into hosts(host,color_id)values(%s,%s)", [("1.1.1.11",1),("1.1.1.11",2)]) 20 21 #批量插入 22 # data = [ 23 # (22), 24 # (33), 25 # (44) 26 # ] 27 # effect_row = cursor.executemany("insert into A(id) values(%s)",data)#批量寫入 28 29 # 提交,不然無法保存新建或者修改的數據 30 conn.commit()#默認就客氣了事務,所以這里不提交數據庫就沒有數據 31 32 # 關閉游標 33 cursor.close() 34 # 關閉連接 35 conn.close()
2、獲取新創建數據自增ID
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import pymysql 4 5 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1') 6 cursor = conn.cursor() 7 cursor.executemany("insert into hosts(host,color_id)values(%s,%s)", [("1.1.1.11",1),("1.1.1.11",2)]) 8 conn.commit() 9 cursor.close() 10 conn.close() 11 12 # 獲取最新自增ID 13 new_id = cursor.lastrowid
3、獲取查詢數據
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import pymysql 4 5 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1') 6 cursor = conn.cursor() 7 cursor.execute("select * from hosts") 8 9 # 獲取第一行數據 10 row_1 = cursor.fetchone() 11 12 # 獲取前n行數據 13 # row_2 = cursor.fetchmany(3) 14 # 獲取所有數據 15 # row_3 = cursor.fetchall() 16 17 conn.commit() 18 cursor.close() 19 conn.close()
注:在fetch數據時按照順序進行,可以使用cursor.scroll(num,mode)來移動游標位置,如:
- cursor.scroll(1,mode='relative') # 相對當前位置移動
- cursor.scroll(2,mode='absolute') # 相對絕對位置移動
4、fetch數據類型
關於默認獲取的數據是元祖類型,如果想要或者字典類型的數據,即:
1 import pymysql 2 3 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1') 4 5 # 游標設置為字典類型 6 cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) 7 r = cursor.execute("call p1()") 8 9 result = cursor.fetchone() 10 11 conn.commit() 12 cursor.close() 13 conn.close()
8、ORM sqlachemy學習
- ORM介紹
- sqlalchemy安裝
- sqlalchemy基本使用
- 多外鍵關聯
- 多對多關系
一、ORM介紹
orm英文全稱object relational mapping,就是對象映射關系程序,簡單來說我們類似python這種面向對象的程序來說一切皆對象,但是我們使用的數據庫卻都是關系型的,為了保證一致的使用習慣,通過orm將編程語言的對象模型和數據庫的關系模型建立映射關系,這樣我們在使用編程語言對數據庫進行操作的時候可以直接使用編程語言的對象模型進行操作就可以了,而不用直接使用sql語言。
orm的優點:
- 隱藏了數據訪問細節,“封閉”的通用數據庫交互,ORM的核心。他使得我們的通用數據庫交互變得簡單易行,並且完全不用考慮該死的SQL語句。快速開發,由此而來。
- ORM使我們構造固化數據結構變得簡單易行。
缺點:
- 無可避免的,自動化意味着映射和關聯管理,代價是犧牲性能(早期,這是所有不喜歡ORM人的共同點)。現在的各種ORM框架都在嘗試使用各種方法來減輕這塊(LazyLoad,Cache),效果還是很顯著的。
二、sqlalchemy安裝
在Python中,最有名的ORM框架是SQLAlchemy。用戶包括openstack\Dropbox等知名公司或應用,主要用戶列表http://www.sqlalchemy.org/organizations.html#openstack
Dialect用於和數據API進行交流,根據配置文件的不同調用不同的數據庫API,從而實現對數據庫的操作,如:

1 MySQL-Python 2 mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> 3 4 pymysql 5 mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] 6 7 MySQL-Connector 8 mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname> 9 10 cx_Oracle 11 oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...] 12 13 更多詳見:http://docs.sqlalchemy.org/en/latest/dialects/index.html
安裝sqlalchemy
1 easy_install sqlalchemy
三、sqlalchemy基本使用
簡單的新建用法(新建一個表)
1 import sqlalchemy 2 from sqlalchemy import create_engine 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy import Column, Integer, String 5 6 engine = create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy", 7 encoding='utf-8', echo=True) 8 9 10 Base = declarative_base() #生成orm基類 11 12 class User(Base): 13 __tablename__ = 'user' #表名 14 id = Column(Integer, primary_key=True) 15 name = Column(String(32)) 16 password = Column(String(64)) 17 18 Base.metadata.create_all(engine) #創建表結構
另外一種寫法(不常用)

1 from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey 2 from sqlalchemy.orm import mapper 3 4 metadata = MetaData() 5 6 user = Table('user', metadata, 7 Column('id', Integer, primary_key=True), 8 Column('name', String(50)), 9 Column('fullname', String(50)), 10 Column('password', String(12)) 11 ) 12 13 class User(object): 14 def __init__(self, name, fullname, password): 15 self.name = name 16 self.fullname = fullname 17 self.password = password 18 19 mapper(User, user) #the table metadata is created separately with the Table construct, then associated with the User class via the mapper() function
現在開始插入一條數據:
1 import sqlalchemy 2 from sqlalchemy import create_engine 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy import Column, Integer, String 5 from sqlalchemy.orm import sessionmaker 6 7 engine = create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy", 8 encoding='utf-8', echo=True) 9 10 11 Base = declarative_base() #生成orm基類 12 13 class User(Base): 14 __tablename__ = 'user' #表名 15 id = Column(Integer, primary_key=True) 16 name = Column(String(32)) 17 password = Column(String(64)) 18 19 Session_class = sessionmaker(bind=engine) #創建與數據庫的會話session class ,注意,這里返回給session的是個class,不是實例 20 Session = Session_class() #生成session實例 21 22 23 user_obj = User(name="zhangsan",password="12345678") #生成你要創建的數據對象 24 print(user_obj.name,user_obj.id) #此時還沒創建對象呢,不信你打印一下id發現還是None 25 26 Session.add(user_obj) #把要創建的數據對象添加到這個session里, 一會統一創建 27 print(user_obj.name,user_obj.id) #此時也依然還沒創建 28 29 Session.commit() #現此才統一提交,創建數據 30 31 32 Base.metadata.create_all(engine) #創建表結構
注意上面導入了一個模塊sessionmaker
查詢:
1 import sqlalchemy 2 from sqlalchemy import create_engine 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy import Column, Integer, String 5 from sqlalchemy.orm import sessionmaker 6 7 engine = create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy", 8 encoding='utf-8')#echo=True這里去掉這里 9 10 11 Base = declarative_base() #生成orm基類 12 13 class User(Base): 14 __tablename__ = 'user' #表名 15 id = Column(Integer, primary_key=True) 16 name = Column(String(32)) 17 password = Column(String(64)) 18 19 Session_class = sessionmaker(bind=engine) #創建與數據庫的會話session class ,注意,這里返回給session的是個class,不是實例 20 Session = Session_class() #生成session實例 21 22 data = Session.query(User).filter_by(name="zhangsan").all()#.all數所有 23 print(data[0].name,data[0].password)#因為這里取出的是一個列表,所以就得這么取 24 25 Session.commit() #現此才統一提交,創建數據 26 27 28 Base.metadata.create_all(engine) #創建表結構
上面這個太二了,來個高大上點的

1 import sqlalchemy 2 from sqlalchemy import create_engine 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy import Column, Integer, String 5 from sqlalchemy.orm import sessionmaker 6 7 engine = create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy", 8 encoding='utf-8')#echo=True這里去掉這里 9 10 11 Base = declarative_base() #生成orm基類 12 13 14 class User(Base): 15 __tablename__ = 'user' #表名 16 id = Column(Integer, primary_key=True) 17 name = Column(String(32)) 18 password = Column(String(64)) 19 20 def __repr__(self): 21 return "<name=%s,password=%s)>" % (self.name,self.password) 22 23 Session_class = sessionmaker(bind=engine) #創建與數據庫的會話session class ,注意,這里返回給session的是個class,不是實例 24 Session = Session_class() #生成session實例 25 26 data = Session.query(User).filter_by(name="zhangsan").all()#.all()數所有 27 print(data)# 28 29 Session.commit() #現此才統一提交,創建數據 30 31 32 Base.metadata.create_all(engine) #創建表結構
修改:

1 import sqlalchemy 2 from sqlalchemy import create_engine 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy import Column, Integer, String 5 from sqlalchemy.orm import sessionmaker 6 7 engine = create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy", 8 encoding='utf-8')#echo=True這里去掉這里 9 10 11 Base = declarative_base() #生成orm基類 12 13 14 class User(Base): 15 __tablename__ = 'user' #表名 16 id = Column(Integer, primary_key=True) 17 name = Column(String(32)) 18 password = Column(String(64)) 19 20 def __repr__(self): 21 return "<name=%s,password=%s)>" % (self.name,self.password) 22 23 Session_class = sessionmaker(bind=engine) #創建與數據庫的會話session class ,注意,這里返回給session的是個class,不是實例 24 Session = Session_class() #生成session實例 25 26 data = Session.query(User).filter_by(name="zhangsan").first()#.all()數所有 27 data.name = "lisi" 28 print(data)# 29 30 Session.commit() #現此才統一提交,創建數據 31 32 33 Base.metadata.create_all(engine) #創建表結構
回滾:

1 import sqlalchemy 2 from sqlalchemy import create_engine 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy import Column, Integer, String 5 from sqlalchemy.orm import sessionmaker 6 7 engine = create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy", 8 encoding='utf-8')#echo=True這里去掉這里 9 10 11 Base = declarative_base() #生成orm基類 12 13 14 class User(Base): 15 __tablename__ = 'user' #表名 16 id = Column(Integer, primary_key=True) 17 name = Column(String(32)) 18 password = Column(String(64)) 19 20 def __repr__(self): 21 return "<name=%s,password=%s)>" % (self.name,self.password) 22 23 Session_class = sessionmaker(bind=engine) #創建與數據庫的會話session class ,注意,這里返回給session的是個class,不是實例 24 Session = Session_class() #生成session實例 25 26 fake_user = User(name="hehe",password='12345678') 27 Session.add(fake_user) 28 29 print(Session.query(User).filter(User.name.in_(['hehe'])).all() ) #這時看session里有你剛添加和修改的數據 30 31 Session.rollback()#回滾一下 32 print("rollback后") 33 34 print(Session.query(User).filter(User.name.in_(['hehe'])).all() )#再看看有沒有數據了 35 36 37 # Session.commit() #現此才統一提交,創建數據 38 # Base.metadata.create_all(engine) #創建表結構
獲取所有數據:
1 print(Session.query(User.name,User.id).all() )
多條件查詢:
1 objs = Session.query(User).filter(User.id>0).filter(User.id<7).all()
統計和分組:
1 Session.query(User).filter(User.name.like("Ra%")).count()
分組
1 from sqlalchemy import func 2 print(Session.query(func.count(User.name),User.name).group_by(User.name).all() )
1、外鍵關聯

1 __author__ = 'Administrator' 2 3 import sqlalchemy 4 from sqlalchemy import create_engine 5 from sqlalchemy.ext.declarative import declarative_base 6 from sqlalchemy import Column, Enum,Integer, String,DATE,ForeignKey 7 from sqlalchemy.orm import sessionmaker,relationship 8 9 engine = create_engine("mysql+pymysql://root:12345678@172.16.5.238/oldboydb", 10 encoding='utf-8')#echo=True這里去掉這里 11 Base = declarative_base() #生成orm基類 12 13 class Student(Base): 14 __tablename__ = "student" 15 id = Column(Integer,primary_key=True) 16 name = Column(String(32),nullable=False) 17 register_date = Column(DATE,nullable=False) 18 19 def __repr__(self): 20 return "<%s name:%s>"%(self.id,self.name) 21 22 class Study_record(Base): 23 __tablename__ = "study_record" 24 id = Column(Integer,primary_key=True) 25 day = Column(Integer,nullable=False) 26 status = Column(String(32),nullable=False) 27 stu_id = Column(Integer,ForeignKey("student.id")) 28 29 student = relationship("Student",backref="my_study_record")#這個是兩個orm在內存中將兩個建立表的類關聯起來。 30 31 def __repr__(self): 32 return "<%s day:%s status:%s>"%(self.student.name,self.day,self.status) 33 34 Base.metadata.create_all(engine)#創建表結構 35 36 37 Session_class = sessionmaker(bind=engine) #創建與數據庫的會話session class 38 Session = Session_class() #生成session實例 39 40 # s1 = Student(name="zhangsan1",register_date = "2016-10-21")#給student表中插入數據 41 # s2 = Student(name="zhangsan2",register_date = "2016-10-22") 42 # s3 = Student(name="zhangsan3",register_date = "2016-10-23") 43 # s4 = Student(name="zhangsan4",register_date = "2016-10-24") 44 # 45 # study_obj1 = Study_record(day = 1,status="YES",stu_id = 1)給study_record表中插入數據 46 # study_obj2 = Study_record(day = 2,status="NO",stu_id = 1) 47 # study_obj3 = Study_record(day = 3,status="YES",stu_id = 1) 48 # study_obj4 = Study_record(day = 4,status="YES",stu_id = 2) 49 # 50 # Session.add_all([s1,s2,s3,s4,study_obj1,study_obj2,study_obj3,study_obj4]) 51 52 # stu_obj = Session.query(Student).filter(Student.name=="zhangsan1").first() 53 # print(stu_obj.my_study_record)#通過查詢Student這個類查詢外鍵zhangsan1的study_record表中的數據 54 55 stu_obj = Session.query(Study_record).filter(Study_record.stu_id=="1").all() 56 print(stu_obj)#使用study_record表中的的stu_id反查所有等於1的信息(這里就將兩個表的數據統一查詢出來了) 57 58 59 Session.commit()
2、多外鍵關聯

1 #需求:一個人的名字可能關聯的是兩個地址,或者更多。我們在customer表中存id和姓名。在address表中存地址 2 3 from sqlalchemy import Integer, ForeignKey, String, Column 4 from sqlalchemy.ext.declarative import declarative_base 5 from sqlalchemy.orm import relationship 6 from sqlalchemy import create_engine 7 8 Base = declarative_base() #生成orm基類 9 10 11 class Customer(Base):#創建表結構customer表 12 __tablename__ = 'customer' 13 id = Column(Integer, primary_key=True) 14 name = Column(String(64)) 15 16 billing_address_id = Column(Integer, ForeignKey("address.id"))#下賬單的地址 17 shipping_address_id = Column(Integer, ForeignKey("address.id"))#收貨的地址 18 19 billing_address = relationship("Address", foreign_keys=[billing_address_id]) 20 shipping_address = relationship("Address", foreign_keys=[shipping_address_id]) 21 22 23 class Address(Base):#創建address表 24 __tablename__ = 'address' 25 id = Column(Integer, primary_key=True) 26 street = Column(String(64)) 27 city = Column(String(64)) 28 state = Column(String(64)) 29 30 31 def __repr__(self): 32 return self.street 33 34 engine = create_engine("mysql+pymysql://root:12345678@172.16.5.238/oldboydb", 35 encoding='utf-8') 36 37 # Base.metadata.create_all(engine) # 創建表結構

1 from day12.pymysql_SQLAlchemy import orm_many_fk 2 from sqlalchemy.orm import sessionmaker 3 4 Session_class = sessionmaker(bind=orm_many_fk.engine) # 創建與數據庫的會話session class ,注意,這里返回給session的是個class,不是實例 5 session = Session_class() # 生成session實例 #cursor 6 # 7 # addr1 = orm_many_fk.Address(street="Tiantongyuan", city="ChangPing", state="BJ") 8 # addr2 = orm_many_fk.Address(street="Wudaokou", city="Haidian", state="BJ") 9 # addr3 = orm_many_fk.Address(street="Yanjiao", city="LangFang", state="HB") 10 # 11 # session.add_all([addr1,addr2,addr3]) 12 # c1 = orm_many_fk.Customer(name="Alex", billing_address= addr1,shipping_address=addr2) 13 # c2 = orm_many_fk.Customer(name="Jack", billing_address= addr3,shipping_address=addr3) 14 # 15 # session.add_all([c1,c2]) 16 17 obj = session.query(orm_many_fk.Customer).filter(orm_many_fk.Customer.name=="jack").first() 18 print(obj.name,obj.billing_address,obj.shipping_address) 19 20 session.commit()
3、多對多關系
現在來設計一個能描述“圖書”與“作者”的關系的表結構,需求是
- 一本書可以有好幾個作者一起出版
- 一個作者可以寫好幾本書

1 from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey 2 from sqlalchemy.orm import relationship 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy import create_engine 5 from sqlalchemy.orm import sessionmaker 6 7 8 Base = declarative_base() 9 10 11 book_m2m_author = Table('book_m2m_author', Base.metadata, 12 Column('book_id',Integer,ForeignKey('books.id')), 13 Column('author_id',Integer,ForeignKey('authors.id')), 14 ) 15 16 class Book(Base): 17 __tablename__ = 'books' 18 id = Column(Integer,primary_key=True) 19 name = Column(String(64)) 20 pub_date = Column(DATE) 21 authors = relationship('Author',secondary=book_m2m_author,backref='books') 22 23 def __repr__(self): 24 return self.name 25 26 class Author(Base): 27 __tablename__ = 'authors' 28 id = Column(Integer, primary_key=True) 29 name = Column(String(32)) 30 31 def __repr__(self): 32 return self.name 33 34 engine = create_engine("mysql+pymysql://root:12345678@172.16.5.238/oldboydb?charset=utf8", 35 ) 36 37 Base.metadata.create_all(engine) # 創建表結構

1 from day12.pymysql_SQLAlchemy import orm_m2m 2 from sqlalchemy.orm import sessionmaker 3 4 Session_class = sessionmaker(bind=orm_m2m.engine) # 創建與數據庫的會話session class ,注意,這里返回給session的是個class,不是實例 5 session = Session_class() # 生成session實例 #cursor 6 7 8 # b1 = orm_m2m.Book(name="learn python with Alex",pub_date="2014-05-2") 9 # b2= orm_m2m.Book(name="learn Zhangbility with Alex",pub_date="2015-05-2") 10 # b3 = orm_m2m.Book(name="跟Alex去泰國",pub_date="2016-05-2") 11 12 # a1 = orm_m2m.Author(name="Alex") 13 # a2 = orm_m2m.Author(name="Jack") 14 # a3 = orm_m2m.Author(name="Rain") 15 # 16 # b1.authors = [a1,a3] 17 # b3.authors = [a1,a2,a3] 18 19 # session.add_all([b3,]) 20 21 author_obj = session.query(orm_m2m.Author).filter(orm_m2m.Author.name=="Alex").first() 22 print(author_obj.books) 23 # book_obj = session.query(orm_m2m.Book).filter(orm_m2m.Book.id==2).first() 24 # book_obj.authors.remove(author_obj) 25 # session.commit()