您的位置:首页 > 编程语言 > Python开发

Python之路-python(mysql介绍和安装、pymysql、ORM sqlachemy)

2017-07-24 14:36 549 查看


Python之路-python(mysql介绍和安装、pymysql、ORMsqlachemy)

本节内容

1、数据库介绍

2、mysql管理

3、mysql数据类型

4、常用mysql命令

  创建数据库

  外键

  增删改查表

5、事务

6、索引

7、python操作mysql

8、ORMsqlachemy学习

1、数据库介绍

什么是数据库?

数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,

每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据。

我们也可以将数据存储在文件中,但是在文件中读写数据速度相对较慢。

所以,现在我们使用关系型数据库管理系统(RDBMS)来存储和管理的大数据量。所谓的关系型数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。

RDBMS即关系数据库管理系统(RelationalDatabaseManagementSystem)的特点:

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(RelationalDatabaseManagementSystem:关系数据库管理系统)应用软件之一。由瑞典MySQLAB公司开发,目前属于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操作权限:

1insertintouser(host,user,password,select_priv,insert_priv,update_priv)values('localhost','lisi',password('12345678'),'y','y','y');


1flushprivileges;


管理MySQL的命令

以下列出了使用Mysql数据库过程中常用的命令:

USE数据库名:选择要操作的Mysql数据库,使用该命令后所有Mysql命令都只针对该数据库。

SHOWDATABASES:列出MySQL数据库管理系统的数据库列表。

SHOWTABLES:#显示指定数据库的所有表,使用该命令前需要使用use命令来选择要操作的数据库。

SHOWCOLUMNSFROM数据表:#显示数据表的属性,属性类型,主键信息,是否为NULL,默认值等其他信息。

createdatabasetestdbcharset"utf8";#创建一个叫testdb的数据库,且让其支持中文

dropdatabasetestdb;#删除数据库

SHOWINDEXFROM数据表:显示数据表的详细索引信息,包括PRIMARYKEY(主键)。

3、mysql数据类型

MySQL中定义数据字段的类型对你数据库的优化是非常重要的。

MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。

数值类型

MySQL支持所有标准SQL数值数据类型。

这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLEPRECISION)。

关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。

BIT数据类型保存位字段值,并且支持MyISAM、MEMORY、InnoDB和BDB表。

作为SQL标准的扩展,MySQL也支持整数类型TINYINT、MEDIUMINT和BIGINT。下面的表显示了需要的每个整数类型的存储和范围。

类型大小范围(有符号)范围(无符号)用途
TINYINT1字节(-128,127)(0,255)小整数值
SMALLINT2字节(-32768,32767)(0,65535)大整数值
MEDIUMINT3字节(-8388608,8388607)(0,16777215)大整数值
INT或INTEGER4字节(-2147483648,2147483647)(0,4294967295)大整数值
BIGINT8字节(-9233372036854775808,9223372036854775807)(0,18446744073709551615)极大整数值
FLOAT4字节(-3.402823466E+38,1.175494351E-38),0,(1.175494351E-38,3.402823466351E+38)0,(1.175494351E-38,3.402823466E+38)单精度

浮点数值
DOUBLE8字节(1.7976931348623157E+308,2.2250738585072014E-308),0,(2.2250738585072014E-308,1.7976931348623157E+308)0,(2.2250738585072014E-308,1.7976931348623157E+308)双精度

浮点数值
DECIMAL对DECIMAL(M,D),如果M>D,为M+2否则为D+2依赖于M和D的值依赖于M和D的值小数值

日期和时间类型

表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。

每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。

TIMESTAMP类型有专有的自动更新特性,将在后面描述。

类型大小

(字节)
范围格式用途
DATE31000-01-01/9999-12-31YYYY-MM-DD日期值
TIME3'-838:59:59'/'838:59:59'HH:MM:SS时间值或持续时间
YEAR11901/2155YYYY年份值
DATETIME81000-01-0100:00:00/9999-12-3123:59:59YYYY-MM-DDHH:MM:SS混合日期和时间值
TIMESTAMP41970-01-0100:00:00/2037年某时YYYYMMDDHHMMSS混合日期和时间值,时间戳

字符串类型

字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。
类型大小用途
CHAR0-255字节定长字符串
VARCHAR0-65535字节变长字符串
TINYBLOB0-255字节不超过255个字符的二进制字符串
TINYTEXT0-255字节短文本字符串
BLOB0-65535字节二进制形式的长文本数据
TEXT0-65535字节长文本数据
MEDIUMBLOB0-16777215字节二进制形式的中等长度文本数据
MEDIUMTEXT0-16777215字节中等长度文本数据
LONGBLOB0-4294967295字节二进制形式的极大文本数据
LONGTEXT0-4294967295字节极大文本数据
CHAR和VARCHAR类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。

BINARY和VARBINARY类类似于CHAR和VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。

BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。

有4种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。这些对应4种BLOB类型,有相同的最大长度和存储需求

4、常用mysql命令

  创建数据库

  语法

  

1CREATETABLEtable_name(column_namecolumn_type);


创建一个student表

createtablestudent(stu_idintnotnullauto_increment,namechar(32)notnull,ageintnotnull,register_datedate,primarykey(stu_id));


实例解析:

如果你不想字段为NULL可以设置字段的属性为NOTNULL,在操作数据库时如果输入该字段的数据为NULL,就会报错。
AUTO_INCREMENT定义列为自增的属性,一般用于主键,数值会自动加1。
PRIMARYKEY关键字用于定义列为主键。您可以使用多列来定义主键,列间以逗号分隔。

MySQL插入数据

语法

1INSERTINTOtable_name(field1,field2,...fieldN)
2VALUES
3(value1,value2,...valueN);


1mysql>insertintostudent(name,age,register_date)values("zhangsan",22,"2016-10-26");
2QueryOK,1rowaffected(0.00sec)
3
4mysql>select*fromstudent;
5+--------+----------+-----+---------------+
6|stu_id|name|age|register_date|
7+--------+----------+-----+---------------+
8|1|zhangsan|22|2016-10-26|
9+--------+----------+-----+---------------+
101rowinset(0.00sec)


MySQL查询数据

语法

1SELECTcolumn_name,column_name
2FROMtable_name
3[WHEREClause]
4[OFFSETM][LIMITN]


1mysql>select*fromstudent;
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+--------+-----------+-----+---------------+
104rowsinset(0.00sec)
11
12方法一:
13mysql>selectnamefromstudentwherename="zhangsan2";
14+-----------+
15|name|
16+-----------+
17|zhangsan2|
18+-----------+
191rowinset(0.00sec)
20
21方法二:
22mysql>selectname,agefromstudentwherename="zhangsan2"andage=24;
23+-----------+-----+
24|name|age|
25+-----------+-----+
26|zhangsan2|24|
27+-----------+-----+
281rowinset(0.00sec)


查询语句中你可以使用一个或者多个表,表之间使用逗号(,)分割,并使用WHERE语句来设定查询条件。
SELECT命令可以读取一条或者多条记录。
你可以使用星号(*)来代替其他字段,SELECT语句会返回表的所有字段数据
你可以使用WHERE语句来包含任何条件。
你可以通过OFFSET指定SELECT语句开始查询的数据偏移量。默认情况下偏移量为0。
你可以使用LIMIT属性来设定返回的记录数。

1mysql>select*fromstudent;
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+--------+-----------+-----+---------------+
104rowsinset(0.00sec)


1#limit相当于从表中的第几条开始查询,offset代表从前面第几条开始计算的第几条数据。(包含limit那行)
2方法一:
3mysql>select*fromstudentlimit2offset1;
4+--------+-----------+-----+---------------+
5|stu_id|name|age|register_date|
6+--------+-----------+-----+---------------+
7|2|zhangsan1|23|2016-10-27|
8|3|zhangsan2|24|2016-10-28|
9+--------+-----------+-----+---------------+
102rowsinset(0.00sec)
11
12
13#下面这个少了个offset,完全就变了。下面说明是从limit指定条开始读,后面1代表读几行。
14方法二:
15mysql>select*fromstudentlimit2,1;
16+--------+-----------+-----+---------------+
17|stu_id|name|age|register_date|
18+--------+-----------+-----+---------------+
19|3|zhangsan2|24|2016-10-28|
20+--------+-----------+-----+---------------+
211rowinset(0.00sec)


MySQLwhere子句

语法

1SELECTfield1,field2,...fieldNFROMtable_name1,table_name2...
2[WHEREcondition1[AND[OR]]condition2.....


以下为操作符列表,可用于WHERE子句中。

下表中实例假定A为10B为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子句的条件查询是非常快速的。

1mysql>select*fromstudentwhereage>24;
2+--------+-----------+-----+---------------+
3|stu_id|name|age|register_date|
4+--------+-----------+-----+---------------+
5|4|zhangsan3|25|2016-10-29|
6+--------+-----------+-----+---------------+
71rowinset(0.00sec)


MySQLUPDATE查询

语法

1mysql>select*fromstudent;
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+--------+-----------+-----+---------------+
104rowsinset(0.00sec)
11
12mysql>updatestudentsetage=28wherename="zhangsan3"andage="25";
13QueryOK,1rowaffected(0.00sec)
14Rowsmatched:1Changed:1Warnings:0
15
16mysql>select*fromstudent;
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+--------+-----------+-----+---------------+
254rowsinset(0.00sec)


MySQLDELETE语句

语法:

1DELETEFROMtable_name[WHEREClause]<br><br>deletefromstudentwherestu_id=5;


例如:

1mysql>deletefromstudentwherename="zhangsan3"andage=28;
2QueryOK,1rowaffected(0.00sec)
3
4mysql>select*fromstudent;
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+--------+-----------+-----+---------------+
123rowsinset(0.00sec)


MySQLLIKE子句

语法:

1SELECTfield1,field2,...fieldNtable_name1,table_name2...
2WHEREfield1LIKEcondition1[AND[OR]]filed2='somevalue'
3
4
5select*fromstudentwherenamebinarylike"%Li";
6select*fromstudentwherenamebinarylikebinary"%Li";#只匹配大写


例如:

1mysql>select*fromstudentwherenamelike"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+--------+-----------+-----+---------------+
104rowsinset(0.00sec)
11
12mysql>select*fromstudentwhereagelike"24";
13+--------+-----------+-----+---------------+
14|stu_id|name|age|register_date|
15+--------+-----------+-----+---------------+
16|3|zhangsan2|24|2016-10-28|
17+--------+-----------+-----+---------------+
181rowinset(0.00sec)


MySQL排序

1SELECTfield1,field2,...fieldNfromtable_name1,table_name2...
2ORDERBYfield1,[field2...][ASC[DESC]]
3使用ASC或DESC关键字来设置查询结果是按升序或降序排列。默认情况下,它是按升序排列。


例如:

1mysql>select*fromstudent;
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+--------+-----------+-----+---------------+
115rowsinset(0.00sec)
12
13mysql>selectagefromstudentorderbyageDESC;
14+-----+
15|age|
16+-----+
17|26|
18|25|
19|24|
20|23|
21|22|
22+-----+
235rowsinset(0.00sec)
24
25mysql>selectagefromstudentorderbyageasc;
26+-----+
27|age|
28+-----+
29|22|
30|23|
31|24|
32|25|
33|26|
34+-----+
355rowsinset(0.00sec)


MySQLGROUPBY语句  

1SELECTcolumn_name,function(column_name)
2FROMtable_name
3WHEREcolumn_nameoperatorvalue
4GROUPBYcolumn_name;


例如:

mysql>select*fromstudent;
+--------+-----------+-----+---------------+
|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|
+--------+-----------+-----+---------------+
6rowsinset(0.00sec)

#接下来我们使用GROUPBY语句将数据表按名字进行分组,并统计每个人有多少条记录:
mysql>selectname,count(*)fromstudentgroupbyname;
+-----------+----------+
|name|count(*)|
+-----------+----------+
|zhangsan|1|
|zhangsan1|1|
|zhangsan2|2|
|zhangsan3|1|
|ZHANGSAN4|1|
+-----------+----------+
5rowsinset(0.00sec)


1#使用WITHROLLUP
#我们模拟stu_id就登陆数,统计一下总登录量

2mysql>selectcoalesce(name,"总数"),sum(stu_id)assingin_conutfromstudentgroupbynamewithrollup;
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+-------------------------+--------------+
136rowsinset(0.00sec)
14
15其中记录NULL表示所有人的登录次数。<br>
16我们可以使用coalesce来设置一个可以取代NUll的名称,coalesce语法:
17mysql>selectcoalesce(name,"总数"),sum(stu_id)assingin_conutfromstudentgroupbynamewithrollup;


MySQLALTER命令

我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQLALTER命令。

删除,添加或修改表字段

删除字段:

1mysql>altertablestudentdropregister_date;
2QueryOK,6rowsaffected(0.01sec)
3Records:6Duplicates:0Warnings:0
4
5mysql>select*fromstudent;
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+--------+-----------+-----+
166rowsinset(0.00sec)


添加字段:

1mysql>altertablestudentaddsinginint(32)notnull;
2QueryOK,6rowsaffected(0.01sec)
3Records:6Duplicates:0Warnings:0
4
5mysql>select*fromstudent;
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+--------+-----------+-----+--------+
166rowsinset(0.00sec)


修改字段类型及名称

如果需要修改字段类型及名称,你可以在ALTER命令中使用MODIFY或CHANGE子句。

例如,把字段c的类型从CHAR(1)改为CHAR(10),可以执行以下命令:

1mysql>ALTERTABLEtestalter_tblMODIFYcCHAR(10);


使用CHANGE子句,语法有很大的不同。在CHANGE关键字之后,紧跟着的是你要修改的字段名,然后指定新字段名及类型。尝试如下实例:

1mysql>ALTERTABLEtestalter_tblCHANGEijBIGINT;
3mysql>ALTERTABLEtestalter_tblCHANGEjjINT;


ALTERTABLE对Null值和默认值的影响

当你修改字段时,你可以指定是否包含只或者是否设置默认值。

以下实例,指定字段j为NOTNULL且默认值为100。

1mysql>ALTERTABLEtestalter_tbl
2->MODIFYjBIGINTNOTNULLDEFAULT100;


修改表名

1mysql>ALTERTABLEtestalter_tblRENAMETOalter_tbl;


关于外键

外键,一个特殊的索引,用于关键2个表,只能是指定内容 

1mysql>createtableclass(
2->idintnotnullprimarykey,
3->namechar(16));
4QueryOK,0rowsaffected(0.02sec)
5
6
7CREATETABLE`student2`(
8`id`int(11)NOTNULL,
9`name`char(16)NOTNULL,
10`class_id`int(11)NOTNULL,
11PRIMARYKEY(`id`),
12KEY`fk_class_key`(`class_id`),
13CONSTRAINT`fk_class_key`FOREIGNKEY(`class_id`)REFERENCES`class`(`id`)
14)
31此时如果class表中不存在id1,student表也插入不了,这就叫外键约束
32mysql>insertintostudent2(id,name,class_id)values(1,'alex',1);
33ERROR1452(23000):Cannotaddorupdateachildrow:aforeignkeyconstraintfails(`testdb`.`student2`,CONSTRAINT`fk_class_key`FOREIGNKEY(`class_id`)REFERENCES`class`(`id`))
34
35
36
37mysql>insertintoclass(id,name)values(1,"linux");
38QueryOK,1rowaffected(0.01sec)
39
40mysql>insertintostudent2(id,name,class_id)values(1,'alex',1);
41QueryOK,1rowaffected(0.00sec)
42
43
44#如果有student表中跟这个class表有关联的数据,你是不能删除class表中与其关联的纪录的
45mysql>deletefromclasswhereid=1;
46ERROR1451(23000):Cannotdeleteorupdateaparentrow:aforeignkeyconstraintfails(`testdb`.`student2`,CONSTRAINT`fk_class_key`FOREIGNKEY(`class_id`)REFERENCES`class`(`id`))



MySQLNULL值处理  

我们已经知道MySQL使用SQLSELECT命令及WHERE子句来读取数据表中的数据,但是当提供的查询条件字段为NULL时,该命令可能就无法正常工作。

为了处理这种情况,MySQL提供了三大运算符:

ISNULL:当列的值是NULL,此运算符返回true。

ISNOTNULL:当列的值不为NULL,运算符返回true。

<=>:比较操作符(不同于=运算符),当比较的的两个值为NULL时返回true。

关于NULL的条件比较运算是比较特殊的。你不能使用=NULL或!=NULL在列中查找NULL值。

在MySQL中,NULL值与任何其它值的比较(即使是NULL)永远返回false,即NULL=NULL返回false。

MySQL中处理NULL使用ISNULL和ISNOTNULL运算符。

Mysql连接(leftjoin,rightjoin,innerjoin,fulljoin)

我们已经学会了如果在一张表中读取数据,这是相对简单的,但是在真正的应用中经常需要从多个数据表中读取数据。

本章节我们将向大家介绍如何使用MySQL的JOIN在两个或多个表中查询数据。

你可以在SELECT,UPDATE和DELETE语句中使用Mysql的JOIN来联合多表查询。

JOIN按照功能大致分为如下三类:

INNERJOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。
LEFTJOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
RIGHTJOIN(右连接):与LEFTJOIN相反,用于获取右表所有记录,即使左表没有对应匹配的记录。

Innerjoin(交集):

#交集
mysql>select*fromAinnerjoinBonA.id=B.id;
+----+----+
|id|id|
+----+----+
|3|3|
|4|4|
+----+----+
2rowsinset(0.00sec)


LEFTJOIN(差集)

1mysql>select*fromAleftjoinBonA.id=B.id;
2+----+------+
3|id|id|
4+----+------+
5|1|NULL|
6|2|NULL|
7|3|3|
8|4|4|
9+----+------+
104rowsinset(0.00sec)
11
12mysql>select*fromBleftjoinAonB.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+----+------+
236rowsinset(0.00sec)


Rightjoin(其实就是leftjoin相反)

1mysql>select*fromArightjoinBonA.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+------+----+
126rowsinset(0.00sec)


Fulljoin(并集)

mysql并不直接支持fulljoin,but总是难不到我们

1mysql>select*fromAleftjoinBonA.id=B.idunionselect*fromArightjoinBonA.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+------+------+
148rowsinset(0.00sec)


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中不保存表的

具体行数,也就是说,执行selectcount(*)from

table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含

where条件时,两种表的操作是一样的。

3.对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。

4.DELETE

FROMtable时,InnoDB不会重新建立表,而是一行一行的删除。

5.LOADTABLEFROM

MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

另外,InnoDB表的行锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update

tablesetnum=1wherenamelike“�a%”

任何一种表都不是万能的,只用恰当的针对业务类型来选择合适的表类型,才能最大的发挥MySQL的性能优势.

MySQL

Administrator建数据库的时候,表缺省是InnoDB类型。

InnoDB,MyISAM

两种类型有什么区别:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。

MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持,外键等高级数据库功能。

MyISAM类型的二进制数据文件可以在不同操作系统中迁移。也就是可以直接从Windows系统拷贝到linux系统中使用。

1查看系统支持的存储引擎

showengines;

2查看表使用的存储引擎

两种方法:

a、showtablestatusfromdb_namewherename='table_name';

b、showcreatetabletable_name;

如果显示的格式不好看,可以用\g代替行尾分号

有人说用第二种方法不准确,我试了下,关闭掉原先默认的Innodb引擎后根本无法执行showcreatetabletable_name指令,因为之前建的是Innodb表,关掉后默认用MyISAM引擎,导致Innodb表数据无法被正确读取。

3修改表引擎方法

altertabletable_nameengine=innodb;

4关闭Innodb引擎方法

关闭mysql服务:netstopmysql

找到mysql安装目录下的my.ini文件:

找到default-storage-engine=INNODB改为default-storage-engine=MYISAM

找到#skip-innodb改为skip-innodb

启动mysql服务:netstartmysql

1mysql>showcreatetableC;
2+-------+-----------------------------------------------------------------------------------------------------+
3|Table|CreateTable|
4+-------+-----------------------------------------------------------------------------------------------------+
5|C|CREATETABLE`C`(
6`a`int(11)NOTNULL,
7PRIMARYKEY(`a`)
8)ENGINE=InnoDBDEFAULTCHARSET=utf8|
9+-------+-----------------------------------------------------------------------------------------------------+
101rowinset(0.00sec)
11
12mysql>begin;
13QueryOK,0rowsaffected(0.00sec)
14
15mysql>insertintoC(a)values(1);
16QueryOK,1rowaffected(0.00sec)
17
18mysql>select*fromC;
19+---+
20|a|
21+---+
22|1|
23+---+
241rowinset(0.00sec)
25
26mysql>rollback;
27QueryOK,0rowsaffected(0.00sec)
28
29mysql>select*fromC;
30Emptyset(0.00sec)
31
32mysql>


注意:如果开始一个事务的时候,直接commit;了就已经提交了,如果再想rollback就回不去了。

6、索引

MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。

打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。

索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索包含多个列。

创建索引时,你需要确保该索引是应用在SQL查询语句的条件(一般作为WHERE子句的条件)。

实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。

普通索引

创建索引

这是最基本的索引,它没有任何限制。它有以下几种创建方式:

1CREATEINDEXindexNameONmytable(username(length));


如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定length。

修改表结构

1ALTERmytableADDINDEX[indexName]ON(username(length))


创建表的时候直接指定

1CREATETABLEmytable(
2
3IDINTNOTNULL,
4
5usernameVARCHAR(16)NOTNULL,
6
7INDEX[indexName](username(length))
8
9);


删除索引的语法

1DROPINDEX[indexName]ONmytable;


唯一索引

它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:

创建索引


View
Code

使用ALTER命令添加和删除索引


View
Code

使用ALTER命令添加和删除主键


View
Code

显示索引信息

1SHOWINDEXFROMtable_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几乎相同。

安装

1easy_installpymysql


使用操作

1、执行SQL

1importpymysql
2
3#创建连接
4conn=pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123',db='t1')
5#创建游标
6cursor=conn.cursor()
7
8#执行SQL,并返回收影响行数
9effect_row=cursor.execute("updatehostssethost='1.1.1.2'")
10
11#执行SQL,并返回受影响行数
12#effect_row=cursor.execute("updatehostssethost='1.1.1.2'wherenid>%s",(1,))
13
14#执行SQL,并返回受影响行数
15#effect_row=cursor.executemany("insertintohosts(host,color_id)values(%s,%s)",[("1.1.1.11",1),("1.1.1.11",2)])
16
17
18#提交,不然无法保存新建或者修改的数据
19conn.commit()
20
21#关闭游标
22cursor.close()
23#关闭连接
24conn.close()


具体操作

1importpymysql
2
3#创建连接(相当于创建了一个socket连接)
4conn=pymysql.connect(host='172.16.5.237',port=3306,user='root',passwd='12345678',db='oldboy')
5
6#创建游标#实时上我们的是cursor来取数据
7cursor=conn.cursor()
8
9#执行SQL,并返回收影响行数
10effect_row=cursor.execute("select*fromA;")
11#print(effect_row)#显示表中有几行
12#print(cursor.fetchone())#取一行
13#print(cursor.fetchall())#打印表中的所有数据
14
15#执行SQL,并返回受影响行数
16#effect_row=cursor.execute("updatehostssethost='1.1.1.2'wherenid>%s",(1,))
17
18#执行SQL,并返回受影响行数
19#effect_row=cursor.executemany("insertintohosts(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("insertintoA(id)values(%s)",data)#批量写入
28
29#提交,不然无法保存新建或者修改的数据
30conn.commit()#默认就客气了事务,所以这里不提交数据库就没有数据
31
32#关闭游标
33cursor.close()
34#关闭连接
35conn.close()


2、获取新创建数据自增ID

1#!/usr/bin/envpython
2#-*-coding:utf-8-*-
3importpymysql
4
5conn=pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123',db='t1')
6cursor=conn.cursor()
7cursor.executemany("insertintohosts(host,color_id)values(%s,%s)",[("1.1.1.11",1),("1.1.1.11",2)])
8conn.commit()
9cursor.close()
10conn.close()
11
12#获取最新自增ID
13new_id=cursor.lastrowid


3、获取查询数据

1#!/usr/bin/envpython
2#-*-coding:utf-8-*-
3importpymysql
4
5conn=pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123',db='t1')
6cursor=conn.cursor()
7cursor.execute("select*fromhosts")
8
9#获取第一行数据
10row_1=cursor.fetchone()
11
12#获取前n行数据
13#row_2=cursor.fetchmany(3)
14#获取所有数据
15#row_3=cursor.fetchall()
16
17conn.commit()
18cursor.close()
19conn.close()


注:在fetch数据时按照顺序进行,可以使用cursor.scroll(num,mode)来移动游标位置,如:

cursor.scroll(1,mode='relative')#相对当前位置移动
cursor.scroll(2,mode='absolute')#相对绝对位置移动

4、fetch数据类型

  关于默认获取的数据是元祖类型,如果想要或者字典类型的数据,即:

1importpymysql
2
3conn=pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123',db='t1')
4
5#游标设置为字典类型
6cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)
7r=cursor.execute("callp1()")
8
9result=cursor.fetchone()
10
11conn.commit()
12cursor.close()
13conn.close()


8、ORMsqlachemy学习

ORM介绍
sqlalchemy安装
sqlalchemy基本使用
多外键关联
多对多关系

一、ORM介绍

orm英文全称objectrelationalmapping,就是对象映射关系程序,简单来说我们类似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,从而实现对数据库的操作,如:



1MySQL-Python
2mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
3
4pymysql
5mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
6
7MySQL-Connector
8mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
9
10cx_Oracle
11oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
12
13更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html


安装sqlalchemy

1easy_installsqlalchemy


三、sqlalchemy基本使用

简单的新建用法(新建一个表)

1importsqlalchemy
2fromsqlalchemyimportcreate_engine
3fromsqlalchemy.ext.declarativeimportdeclarative_base
4fromsqlalchemyimportColumn,Integer,String
5
6engine=create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy",
7encoding='utf-8',echo=True)
8
9
10Base=declarative_base()#生成orm基类
11
12classUser(Base):
13__tablename__='user'#表名
14id=Column(Integer,primary_key=True)
15name=Column(String(32))
16password=Column(String(64))
17
18Base.metadata.create_all(engine)#创建表结构


另外一种写法(不常用)



1fromsqlalchemyimportTable,MetaData,Column,Integer,String,ForeignKey
2fromsqlalchemy.ormimportmapper
3
4metadata=MetaData()
5
6user=Table('user',metadata,
7Column('id',Integer,primary_key=True),
8Column('name',String(50)),
9Column('fullname',String(50)),
10Column('password',String(12))
11)
12
13classUser(object):
14def__init__(self,name,fullname,password):
15self.name=name
16self.fullname=fullname
17self.password=password
18
19mapper(User,user)#thetablemetadataiscreatedseparatelywiththeTableconstruct,thenassociatedwiththeUserclassviathemapper()function


现在开始插入一条数据:

1importsqlalchemy
2fromsqlalchemyimportcreate_engine
3fromsqlalchemy.ext.declarativeimportdeclarative_base
4fromsqlalchemyimportColumn,Integer,String
5fromsqlalchemy.ormimportsessionmaker
6
7engine=create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy",
8encoding='utf-8',echo=True)
9
10
11Base=declarative_base()#生成orm基类
12
13classUser(Base):
14__tablename__='user'#表名
15id=Column(Integer,primary_key=True)
16name=Column(String(32))
17password=Column(String(64))
18
19Session_class=sessionmaker(bind=engine)#创建与数据库的会话sessionclass,注意,这里返回给session的是个class,不是实例
20Session=Session_class()#生成session实例
21
22
23user_obj=User(name="zhangsan",password="12345678")#生成你要创建的数据对象
24print(user_obj.name,user_obj.id)#此时还没创建对象呢,不信你打印一下id发现还是None
25
26Session.add(user_obj)#把要创建的数据对象添加到这个session里,一会统一创建
27print(user_obj.name,user_obj.id)#此时也依然还没创建
28
29Session.commit()#现此才统一提交,创建数据
30
31
32Base.metadata.create_all(engine)#创建表结构


注意上面导入了一个模块sessionmaker

查询:

1importsqlalchemy
2fromsqlalchemyimportcreate_engine
3fromsqlalchemy.ext.declarativeimportdeclarative_base
4fromsqlalchemyimportColumn,Integer,String
5fromsqlalchemy.ormimportsessionmaker
6
7engine=create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy",
8encoding='utf-8')#echo=True这里去掉这里
9
10
11Base=declarative_base()#生成orm基类
12
13classUser(Base):
14__tablename__='user'#表名
15id=Column(Integer,primary_key=True)
16name=Column(String(32))
17password=Column(String(64))
18
19Session_class=sessionmaker(bind=engine)#创建与数据库的会话sessionclass,注意,这里返回给session的是个class,不是实例
20Session=Session_class()#生成session实例
21
22data=Session.query(User).filter_by(name="zhangsan").all()#.all数所有
23print(data[0].name,data[0].password)#因为这里取出的是一个列表,所以就得这么取
24
25Session.commit()#现此才统一提交,创建数据
26
27
28Base.metadata.create_all(engine)#创建表结构


上面这个太二了,来个高大上点的



1importsqlalchemy
2fromsqlalchemyimportcreate_engine
3fromsqlalchemy.ext.declarativeimportdeclarative_base
4fromsqlalchemyimportColumn,Integer,String
5fromsqlalchemy.ormimportsessionmaker
6
7engine=create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy",
8encoding='utf-8')#echo=True这里去掉这里
9
10
11Base=declarative_base()#生成orm基类
12
13
14classUser(Base):
15__tablename__='user'#表名
16id=Column(Integer,primary_key=True)
17name=Column(String(32))
18password=Column(String(64))
19
20def__repr__(self):
21return"<name=%s,password=%s)>"%(self.name,self.password)
22
23Session_class=sessionmaker(bind=engine)#创建与数据库的会话sessionclass,注意,这里返回给session的是个class,不是实例
24Session=Session_class()#生成session实例
25
26data=Session.query(User).filter_by(name="zhangsan").all()#.all()数所有
27print(data)#
28
29Session.commit()#现此才统一提交,创建数据
30
31
32Base.metadata.create_all(engine)#创建表结构


修改:



1importsqlalchemy
2fromsqlalchemyimportcreate_engine
3fromsqlalchemy.ext.declarativeimportdeclarative_base
4fromsqlalchemyimportColumn,Integer,String
5fromsqlalchemy.ormimportsessionmaker
6
7engine=create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy",
8encoding='utf-8')#echo=True这里去掉这里
9
10
11Base=declarative_base()#生成orm基类
12
13
14classUser(Base):
15__tablename__='user'#表名
16id=Column(Integer,primary_key=True)
17name=Column(String(32))
18password=Column(String(64))
19
20def__repr__(self):
21return"<name=%s,password=%s)>"%(self.name,self.password)
22
23Session_class=sessionmaker(bind=engine)#创建与数据库的会话sessionclass,注意,这里返回给session的是个class,不是实例
24Session=Session_class()#生成session实例
25
26data=Session.query(User).filter_by(name="zhangsan").first()#.all()数所有
27data.name="lisi"
28print(data)#
29
30Session.commit()#现此才统一提交,创建数据
31
32
33Base.metadata.create_all(engine)#创建表结构


回滚:



1importsqlalchemy
2fromsqlalchemyimportcreate_engine
3fromsqlalchemy.ext.declarativeimportdeclarative_base
4fromsqlalchemyimportColumn,Integer,String
5fromsqlalchemy.ormimportsessionmaker
6
7engine=create_engine("mysql+pymysql://root:12345678@172.16.5.237/oldboy",
8encoding='utf-8')#echo=True这里去掉这里
9
10
11Base=declarative_base()#生成orm基类
12
13
14classUser(Base):
15__tablename__='user'#表名
16id=Column(Integer,primary_key=True)
17name=Column(String(32))
18password=Column(String(64))
19
20def__repr__(self):
21return"<name=%s,password=%s)>"%(self.name,self.password)
22
23Session_class=sessionmaker(bind=engine)#创建与数据库的会话sessionclass,注意,这里返回给session的是个class,不是实例
24Session=Session_class()#生成session实例
25
26fake_user=User(name="hehe",password='12345678')
27Session.add(fake_user)
28
29print(Session.query(User).filter(User.name.in_(['hehe'])).all())#这时看session里有你刚添加和修改的数据
30
31Session.rollback()#回滚一下
32print("rollback后")
33
34print(Session.query(User).filter(User.name.in_(['hehe'])).all())#再看看有没有数据了
35
36
37#Session.commit()#现此才统一提交,创建数据
38#Base.metadata.create_all(engine)#创建表结构


获取所有数据:

1print(Session.query(User.name,User.id).all())


多条件查询:

1objs=Session.query(User).filter(User.id>0).filter(User.id<7).all()


统计和分组:

1Session.query(User).filter(User.name.like("Ra%")).count()


分组

1fromsqlalchemyimportfunc
2print(Session.query(func.count(User.name),User.name).group_by(User.name).all())


1、外键关联



1__author__='Administrator'
2
3importsqlalchemy
4fromsqlalchemyimportcreate_engine
5fromsqlalchemy.ext.declarativeimportdeclarative_base
6fromsqlalchemyimportColumn,Enum,Integer,String,DATE,ForeignKey
7fromsqlalchemy.ormimportsessionmaker,relationship
8
9engine=create_engine("mysql+pymysql://root:12345678@172.16.5.238/oldboydb",
10encoding='utf-8')#echo=True这里去掉这里
11Base=declarative_base()#生成orm基类
12
13classStudent(Base):
14__tablename__="student"
15id=Column(Integer,primary_key=True)
16name=Column(String(32),nullable=False)
17register_date=Column(DATE,nullable=False)
18
19def__repr__(self):
20return"<%sname:%s>"%(self.id,self.name)
21
22classStudy_record(Base):
23__tablename__="study_record"
24id=Column(Integer,primary_key=True)
25day=Column(Integer,nullable=False)
26status=Column(String(32),nullable=False)
27stu_id=Column(Integer,ForeignKey("student.id"))
28
29student=relationship("Student",backref="my_study_record")#这个是两个orm在内存中将两个建立表的类关联起来。
30
31def__repr__(self):
32return"<%sday:%sstatus:%s>"%(self.student.name,self.day,self.status)
33
34Base.metadata.create_all(engine)#创建表结构
35
36
37Session_class=sessionmaker(bind=engine)#创建与数据库的会话sessionclass
38Session=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
55stu_obj=Session.query(Study_record).filter(Study_record.stu_id=="1").all()
56print(stu_obj)#使用study_record表中的的stu_id反查所有等于1的信息(这里就将两个表的数据统一查询出来了)
57
58
59Session.commit()


2、多外键关联



1#需求:一个人的名字可能关联的是两个地址,或者更多。我们在customer表中存id和姓名。在address表中存地址
2
3fromsqlalchemyimportInteger,ForeignKey,String,Column
4fromsqlalchemy.ext.declarativeimportdeclarative_base
5fromsqlalchemy.ormimportrelationship
6fromsqlalchemyimportcreate_engine
7
8Base=declarative_base()#生成orm基类
9
10
11classCustomer(Base):#创建表结构customer表
12__tablename__='customer'
13id=Column(Integer,primary_key=True)
14name=Column(String(64))
15
16billing_address_id=Column(Integer,ForeignKey("address.id"))#下账单的地址
17shipping_address_id=Column(Integer,ForeignKey("address.id"))#收货的地址
18
19billing_address=relationship("Address",foreign_keys=[billing_address_id])
20shipping_address=relationship("Address",foreign_keys=[shipping_address_id])
21
22
23classAddress(Base):#创建address表
24__tablename__='address'
25id=Column(Integer,primary_key=True)
26street=Column(String(64))
27city=Column(String(64))
28state=Column(String(64))
29
30
31def__repr__(self):
32returnself.street
33
34engine=create_engine("mysql+pymysql://root:12345678@172.16.5.238/oldboydb",
35encoding='utf-8')
36
37#Base.metadata.create_all(engine)#创建表结构




1fromday12.pymysql_SQLAlchemyimportorm_many_fk
2fromsqlalchemy.ormimportsessionmaker
3
4Session_class=sessionmaker(bind=orm_many_fk.engine)#创建与数据库的会话sessionclass,注意,这里返回给session的是个class,不是实例
5session=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
17obj=session.query(orm_many_fk.Customer).filter(orm_many_fk.Customer.name=="jack").first()
18print(obj.name,obj.billing_address,obj.shipping_address)
19
20session.commit()


3、多对多关系

现在来设计一个能描述“图书”与“作者”的关系的表结构,需求是

一本书可以有好几个作者一起出版
一个作者可以写好几本书



1fromsqlalchemyimportTable,Column,Integer,String,DATE,ForeignKey
2fromsqlalchemy.ormimportrelationship
3fromsqlalchemy.ext.declarativeimportdeclarative_base
4fromsqlalchemyimportcreate_engine
5fromsqlalchemy.ormimportsessionmaker
6
7
8Base=declarative_base()
9
10
11book_m2m_author=Table('book_m2m_author',Base.metadata,
12Column('book_id',Integer,ForeignKey('books.id')),
13Column('author_id',Integer,ForeignKey('authors.id')),
14)
15
16classBook(Base):
17__tablename__='books'
18id=Column(Integer,primary_key=True)
19name=Column(String(64))
20pub_date=Column(DATE)
21authors=relationship('Author',secondary=book_m2m_author,backref='books')
22
23def__repr__(self):
24returnself.name
25
26classAuthor(Base):
27__tablename__='authors'
28id=Column(Integer,primary_key=True)
29name=Column(String(32))
30
31def__repr__(self):
32returnself.name
33
34engine=create_engine("mysql+pymysql://root:12345678@172.16.5.238/oldboydb?charset=utf8",
35)
36
37Base.metadata.create_all(engine)#创建表结构




1fromday12.pymysql_SQLAlchemyimportorm_m2m
2fromsqlalchemy.ormimportsessionmaker
3
4Session_class=sessionmaker(bind=orm_m2m.engine)#创建与数据库的会话sessionclass,注意,这里返回给session的是个class,不是实例
5session=Session_class()#生成session实例#cursor
6
7
8#b1=orm_m2m.Book(name="learnpythonwithAlex",pub_date="2014-05-2")
9#b2=orm_m2m.Book(name="learnZhangbilitywithAlex",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
21author_obj=session.query(orm_m2m.Author).filter(orm_m2m.Author.name=="Alex").first()
22print(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()


转载地址:'target='_blank'>http://www.cnblogs.com/lei0213/p/6002921.html附另一篇文章:

python(pymysql)之mysql简单操作

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: