任務:python
六週三次課(11月22日)
12.8 建立表
12.9/12.10 增長數據
12.11 查詢數據mysql
筆記:sql
數據庫鍵表,直接在python代碼中執行,數據庫
#!/usr/bin/env python函數
# -*- coding:utf-8 -*-fetch
# @Time : 2017/5/5 13:56加密
# @Author : llill設計
# @File : aa.pycode
import MySQLdborm
def connect_mysql():
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
cus = cnx.cursor()
# sql = '''insert into student(id, name, age, gender, score) values ('1001', 'ling', 29, 'M', 88), ('1002', 'ajing', 29, 'M', 90), ('1003', 'xiang', 33, 'M', 87);'''
student = '''create table Student(
StdID int not null,
StdName varchar(100) not null,
Gender enum('M', 'F'),
Age tinyint
)'''
course = '''create table Course(
CouID int not null,
CName varchar(50) not null,
TID int not null
)'''
score = '''create table Score(
SID int not null,
StdID int not null,
CID int not null,
Grade int not null
)'''
teacher = '''create table Teacher(
TID int not null,
TName varchar(100) not null
)'''
tmp = '''set @i := 0;
create table tmp as select (@i := @i + 1) as id from information_schema.tables limit 10;
'''
try:
cus.execute(student)
cus.execute(course)
cus.execute(score)
cus.execute(thearch)
cus.execute(tmp)
cus.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('error')
raise e
finally:
cnx.close()
結果:
mysql> show tables;
+------------------+
| Tables_in_python |
+------------------+
| Course |
| Score |
| Student |
| Teacher |
| tmp |
+------------------+
1 rows in set (0.00 sec)
沒有任何異常,在數據庫中查看錶,出現這五個表。說明這五個表已經建立成功。
既然咱們要搞,就儘量的接近實戰,咱們來把數據搞大一點,語句設計的複雜一點,這樣對咱們之後接觸到簡單的sql語句時,就有很大的幫助。
首先咱們先來了解一下information_schema這個庫,這個在mysql安裝時就有了,提供了訪問數據庫元數據的方式。那什麼是元數據庫呢?元數據是關於數據的數據,如數據庫名或表名,列的數據類型,或訪問權限等。有些時候用於表述該信息的其餘術語包括「數據詞典」和「系統目錄」。
information_schema數據庫表說明:
SCHEMATA表:提供了當前mysql實例中全部數據庫的信息。是show databases的結果取之此表。
TABLES表:提供了關於數據庫中的表的信息(包括視圖)。詳細表述了某個表屬於哪一個schema,表類型,表引擎,建立時間等信息。是show tables from schemaname的結果取之此表。
COLUMNS表:提供了表中的列信息。詳細表述了某張表的全部列以及每一個列的信息。是show columns from schemaname.tablename的結果取之此表。
STATISTICS表:提供了關於表索引的信息。是show index from schemaname.tablename的結果取之此表。
USER_PRIVILEGES(用戶權限)表:給出了關於全程權限的信息。該信息源自mysql.user受權表。是非標準表。
SCHEMA_PRIVILEGES(方案權限)表:給出了關於方案(數據庫)權限的信息。該信息來自mysql.db受權表。是非標準表。
TABLE_PRIVILEGES(表權限)表:給出了關於表權限的信息。該信息源自mysql.tables_priv受權表。是非標準表。
COLUMN_PRIVILEGES(列權限)表:給出了關於列權限的信息。該信息源自mysql.columns_priv受權表。是非標準表。
CHARACTER_SETS(字符集)表:提供了mysql實例可用字符集的信息。是SHOW CHARACTER SET結果集取之此表。
COLLATIONS表:提供了關於各字符集的對照信息。
COLLATION_CHARACTER_SET_APPLICABILITY表:指明瞭可用於校對的字符集。這些列等效於SHOW COLLATION的前兩個顯示字段。
TABLE_CONSTRAINTS表:描述了存在約束的表。以及表的約束類型。
KEY_COLUMN_USAGE表:描述了具備約束的鍵列。
ROUTINES表:提供了關於存儲子程序(存儲程序和函數)的信息。此時,ROUTINES表不包含自定義函數(UDF)。名爲「mysql.proc name」的列指明瞭對應於INFORMATION_SCHEMA.ROUTINES表的mysql.proc表列。
VIEWS表:給出了關於數據庫中的視圖的信息。須要有show views權限,不然沒法查看視圖信息。
TRIGGERS表:提供了關於觸發程序的信息。必須有super權限才能查看該表
而TABLES在安裝好mysql的時候,必定是有數據的,由於在初始化mysql的時候,就須要建立系統表,該表必定有數據。
set @i := 0;
create table tmp as select (@i := @i + 1) as id from information_schema.tables limit 10;
mysql中變量不用事前申明,在用的時候直接用「@變量名」使用就能夠了。set這個是mysql中設置變量的特殊用法,當@i須要在select中使用的時候,必須加:,這樣就建立好了一個表tmp,查看tmp的數據:
mysql> select * from tmp;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+------+
10 rows in set (0.00 sec)
咱們只是從information_schema.tables表中取10條數據,任何表有10條數據也是能夠的,而後把變量@i做爲id列的值,分10次不斷輸出,依據最後select的結果,建立表tmp。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/5/5 13:56
# @Author : llill
# @File : aa.py
import MySQLdb
def connect_mysql():
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
students = '''set @i := 10000;
insert into Student select @i:=@i+1, substr(concat(sha1(rand()), sha1(rand())), 1, 3 + floor(rand() * 75)), case floor(rand()*10) mod 2 when 1 then 'M' else 'F' end, 25-floor(rand() * 5) from tmp a, tmp b, tmp c, tmp d;
'''
course = '''set @i := 10;
insert into Course select @i:=@i+1, substr(concat(sha1(rand()), sha1(rand())), 1, 5 + floor(rand() * 40)), 1 + floor(rand() * 100) from tmp a;
'''
score = '''set @i := 10000;
insert into Score select @i := @i +1, floor(10001 + rand()*10000), floor(11 + rand()*10), floor(1+rand()*100) from tmp a, tmp b, tmp c, tmp d;
'''
theacher = '''set @i := 100;
insert into Teacher select @i:=@i+1, substr(concat(sha1(rand()), sha1(rand())), 1, 5 + floor(rand() * 80)) from tmp a, tmp b;
'''
try:
cus_students = cnx.cursor()
cus_students.execute(students)
cus_students.close()
cus_course = cnx.cursor()
cus_course.execute(course)
cus_course.close()
cus_score = cnx.cursor()
cus_score.execute(score)
cus_score.close()
cus_teacher = cnx.cursor()
cus_teacher.execute(theacher)
cus_teacher.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('error')
raise e
finally:
cnx.close()
結果:
mysql> select count(*) from Student;
+----------+
| count(*) |
+----------+
| 10000 |
+----------+
1 row in set (0.01 sec)
mysql> select count(*) from Course;
+----------+
| count(*) |
+----------+
| 10 |
+----------+
1 row in set (0.00 sec)
mysql> select count(*) from Score;
+----------+
| count(*) |
+----------+
| 10000 |
+----------+
1 row in set (0.00 sec)
mysql> select count(*) from Teacher;
+----------+
| count(*) |
+----------+
| 100 |
+----------+
1 row in set (0.00 sec)
如圖所示,在Student的表中增長了10000條數據,id是從10000開始的。count函數時用來統計個數的。
解釋;
咱們知道Student有四個字段,StdID,StdName,Gender,Age;咱們先來看這個select語句:select @i:=@i+1, substr(concat(sha1(rand()), sha1(rand())), 1, 3+floor(rand() * 75)), case floor(rand()*10) mod 2 when 1 then 'M' else 'F' end, 25-floor(rand() * 5) from tmp a, tmp b, tmp c, tmp d;
StdID字段:@i就表明的就是,從10000開始,在上一句sql中設置的;
StdName字段:substr(concat(sha1(rand()), sha1(rand())), 1, floor(rand() * 80))就表明的是,
substr是一個字符串函數,從第二個參數1,開始取字符,取到3+ floor(rand() * 75)結束
floor函數表明的是去尾法取整數。
rand()函數表明的是從0到1取一個隨機的小數。
rand() * 75就表明的是:0到75任何一個小數,
3+floor(rand() * 75)就表明的是:3到77的任意一個數字
concat()函數是一個對多個字符串拼接函數。
sha1是一個加密函數,sha1(rand())對生成的0到1的一個隨機小數進行加密,轉換成字符串的形式。
concat(sha1(rand()), sha1(rand()))就表明的是:兩個0-1生成的小數加密而後進行拼接。
substr(concat(sha1(rand()), sha1(rand())), 1, floor(rand() * 80))就表明的是:從一個隨機生成的一個字符串的第一位開始取,取到(隨機3-77)位結束。
Gender字段:case floor(rand()*10) mod 2 when 1 then 'M' else 'F' end,就表明的是,
floor(rand()*10)表明0-9隨機取一個數
floor(rand()*10) mod 2 就是對0-9取得的隨機數除以2的餘數,
case floor(rand()*10) mod 2 when 1 then 'M' else 'F' end,表明:當餘數爲1是,就取M,其餘的爲F
Age字段:25-floor(rand() * 5)表明的就是,25減去一個0-4的一個整數
如今有一個問題,爲何會出現10000條數據呢,這10000條數據時怎麼生成的呢,雖然字段一一對應上了,可是怎麼出來這麼多數據呢?
先來看個例子:
select * from tmp a, tmp b, tmp c;
最終是1000條數據,試試有一些感受了呢,a, b, c都是tmp表的別名,至關於每一個表都循環了一遍。因此最終的數據是有多少個表,就是10的多少次冪。
10000條數據,可能會有同窗的名字是同樣的,咱們的需求就是在數據庫中查出來全部名字有重複的同窗的全部信息,而後寫入到文件中。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/5/5 13:56
# @Author : llill
# @File : mm.py
import codecs
import MySQLdb
def connect_mysql():
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
sql = '''select * from Student where StdName in (select StdName from Student group by StdName having count(1)>1 ) order by StdName;'''
try:
cus = cnx.cursor()
cus.execute(sql)
result = cus.fetchall()
with codecs.open('select.txt', 'w+') as f:
for line in result:
f.write(str(line))
f.write('\n')
cus.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('error')
raise e
finally:
cnx.close()
結果:
本地目錄出現一個select.txt文件,內容以下:
(19844L, u'315', u'F', 24)
(17156L, u'315', u'F', 25)
(14349L, u'48f', u'F', 25)
(17007L, u'48f', u'F', 25)
(12629L, u'afd', u'F', 25)
(13329L, u'afd', u'F', 24)
(10857L, u'e31', u'F', 23)
(14476L, u'e31', u'M', 21)
(16465L, u'ee5', u'M', 22)
(18570L, u'ee5', u'M', 21)
(17056L, u'ef0', u'M', 23)
(16946L, u'ef0', u'F', 24)
解釋:
select * from Student where StdName in (select StdName from Student group by StdName having count(1)>1 ) order by StdName;'
有些老師很差好上次,致使課程的及格率過低,最後名最差的5名老師將會被開除。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/5/5 13:56
# @Author : llill
# @File : delete.py
import codecs
import MySQLdb
def connect_mysql():
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
sql = '''delete from Teacher where TID in(
select TID from (select Course.CouID, Course.TID, Teacher.TName, count(Teacher.TID) as count_teacher from Course
left join Score on Score.Grade < 60 and Course.CouID = Score.CouID
left join Teacher on Course.TID = Teacher.TID
group by Course.TID
order by count_teacher desc
limit 5) as test )
'''
try:
cus = cnx.cursor()
cus.execute(sql)
result = cus.fetchall()
cus.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('error')
raise e
finally:
cnx.close()
結果:
程序正常執行,沒有報錯
解釋:
首先,咱們把分數低於5分的成績全部都加60分。
代碼以下:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/5/5 13:56
# @Author : llill
# @File : update.py
import codecs
import MySQLdb
def connect_mysql():
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
sql = '''select *, (grade+60) as newGrade from Score where Grade <5;'''
update = '''update Score set grade = grade + 60 where grade < 5; '''
try:
cus_start = cnx.cursor()
cus_start.execute(sql)
result1 = cus_start.fetchall()
print(len(result1))
cus_start.close()
cus_update = cnx.cursor()
cus_update.execute(update)
cus_update.close()
cus_end = cnx.cursor()
cus_end.execute(sql)
result2 = cus_end.fetchall()
print(len(result2))
cus_end.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('error')
raise e
finally:
cnx.close()
結果:
321
0
解釋:
1.剛開始,咱們能夠查到分數小於5分的總個數有321個
2.select *, (grade+60) as newGrade from Score where Grade <5;這個sql是把全部的成績小於5的都列出來,而後最後加一列分數加60分的結果。
3.update Score set grade = grade + 60 where grade < 5;是把分數小於5的全部成績都加60分
4.最後在檢查分數小於5的個數爲0,說明全部低於5分的分數都發生了改變。