WEEK12:Mysql and ORM

  • 關係數據庫管理系統(RDBMS)
    • 特色
      • 數據以表格的形式出現
      • 每行爲各類記錄名稱
      • 每列爲記錄名稱所對應的數據域
      • 許多的行和列組成一張表單
      • 若干的表單組成database
    • 術語
      • 數據庫: 數據庫是一些關聯表的集合
      • 數據表: 表是數據的矩陣。在一個數據庫中的表看起來像一個簡單的電子表格
      • 列: 一列(數據元素) 包含了相同的數據, 例如郵政編碼的數據
      • 行:一行(=元組,或記錄)是一組相關的數據,例如一條用戶訂閱的數據
      • 冗餘:存儲兩倍數據,冗餘可使系統速度更快
      • 主鍵:主鍵是惟一的。一個數據表中只能包含一個主鍵。你可使用主鍵來查詢數據
      • 外鍵:外鍵用於關聯兩個表
      • 複合鍵:複合鍵(組合鍵)將多個列做爲一個索引鍵,通常用於複合索引
      • 索引:使用索引可快速訪問數據庫表中的特定信息。索引是對數據庫表中一列或多列的值進行排序的一種結構。相似於書籍的目錄
      • 參照完整性: 參照的完整性要求關係中不容許引用不存在的實體。與實體完整性是關係模型必須知足的完整性約束條件,目的是保證數據的一致性。
    • Mysql數據庫(MariaDB)
      最流行的關係型數據庫管理系統
      • 特色:
        • 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系統
      • 管理命令
        • 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(主鍵)
      • 經常使用命令
        • 建立數據表
          • 語法
            CREATE TABLE table_name (column_name column_type);
          • 實例
            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關鍵字用於定義列爲主鍵。 您可使用多列來定義主鍵,列間以逗號分隔
        • 插入數據
          • 語法
            INSERT INTO table_name ( field1, field2,...fieldN ) VALUES ( value1, value2,...valueN );
          • 實例
            insert into student (name,age,register_date) values ("alex li",22,"2016-03-4");
        • 格式化輸出
          select * from student\G
          加\G以後再也不須要加分號
        • 查看數據表屬性
          desc student;
        • 查詢數據
          • 語法
            SELECT column_name,column_name
            FROM table_name
            [WHERE Clause]
            [OFFSET M ][LIMIT N]
            • 解析
              • 查詢語句中你可使用一個或者多個表,表之間使用逗號(,)分割,並使用WHERE語句來設定查詢條件
              • SELECT 命令能夠讀取一條或者多條記錄
              • 可使用星號(*)來代替其餘字段,SELECT語句會返回表的全部字段數據
              • 可使用 WHERE 語句來包含任何條件
              • 能夠經過OFFSET指定SELECT語句開始查詢的數據偏移量。默認狀況下偏移量爲0
              • 可使用 LIMIT 屬性來設定返回的記錄數  
          • 實例
            • limit後面跟的是3條數據,offset後面是從第3條開始讀取
              select * from student limit 3 offset 2;
            • limit後面是從第3條開始讀,讀取1條信息
              select * from student limit 3 ,1;
        • WHERE 子句
          • 語法
            SELECT field1, field2,...fieldN FROM table_name1, table_name2...
            [ WHERE condition1 [ AND [ OR ]] condition2.....
          • 實例
            使用主鍵來做爲 WHERE 子句的條件查詢是很是快速的
            select * from student where register_date > '2016-03-04' ;
        • UPDATE 更新
          • 語法
            UPDATE table_name SET field1=new-value1, field2=new-value2
            [ WHERE Clause]
          • 實例
            update student set age=22 , name = "Alex Li" where stu_id>3;
        • DELETE 語句
          • 語法
            DELETE FROM table_name [ WHERE Clause] delete from student where stu_id=5;
        • LIKE 子句
          • 語法
            SELECT field1, field2,...fieldN table_name1, table_name2...
            WHERE field1 LIKE condition1 [ AND [ OR ]] filed2 = 'somevalue'
          • 實例
            select * from student where name binary like "%Li" ; #binary則是將內容強制轉換成二進制的字符串
            select * from student where name binary like  binary "%Li" ; #只匹配大寫,like binary 用來區分大小寫
        • 排序
          • 語法
            SELECT field1, field2,...fieldN table_name1, table_name2...
            ORDER BY field1, [field2...] [ ASC [ DESC ]]
            使用 ASC DESC 關鍵字來設置查詢結果是按升序或降序排列。 默認狀況下,它是按升序排列。
          • 實例
            select from student where name like binary "%Li" order by stu_id desc ;
        • GROUP BY語句
          • 語法
            SELECT column_name, function (column_name)
            FROM table_name
            WHERE column_name operator value
            GROUP BY column_name;
          • 實例
            • 使用 GROUPBY語句 將數據表按名字進行分組,並統計每一個人有多少條記錄
              SELECT name, COUNT(*) FROM employee_tbl GROUP BY name;
            • 使用 WITH ROLLUP
              SELECT name , SUM (singin) as singin_count FROM employee_tbl GROUP BY name WITH ROLLUP ;

              NULL表示全部人的登陸次數;可使用 coalesce 來設置一個能夠取代 NUll 的名稱,coalesce 語法:
              SELECT coalesce(name, '總數'), SUM(singin) as singin_count FROM  employee_tbl GROUP BY name WITH ROLLUP;
              python

        • ALTER 命令
          修改數據表名或者修改數據表字段
          • 刪除,添加或修改表字段
            • 語法
              alter table student drop register_date; #從student表刪除register_date字段
              alter table student add phone int (11) not null ; #添加phone字段
          • 修改字段類型及名稱
            若是須要修改字段類型及名稱, 你能夠在ALTER命令中使用 MODIFY 或 CHANGE 子句
            • 語法
              • 把字段 c 的類型從 CHAR(1) 改成 CHAR(10)
                ALTERTABLEtestalter_tbl MODIFYc CHAR(10)
              • 使用 CHANGE 子句, 語法有很大的不一樣。 在 CHANGE 關鍵字以後,緊跟着的是你要修改的字段名,而後指定新字段名及類型
                ALTERTABLEtestalter_tbl CHANGE i j BIGINT;
                ALTERTABLEtestalter_tbl CHANGE j j INT;
          • ALTER TABLE 對 NULL值和默認值的影響
            修改字段時,能夠指定是否包含或者是否設置默認值
            指定字段 j 爲 NOT NULL 且默認值爲100
            ALTERTABLEtestalter_tbl MODIFY j BIGINT NOT NULL DEFAULT 100;
          • 修改表名
            ALTERTABLEtestalter_tbl RENAME TOalter_tbl;
        • 關於主鍵
          外鍵,一個特殊的索引,用於關連2個表,只能是指定內容
          • 建立第一張表 class
            createtableclass(id intnotnullprimarykey,namechar(16));
          • 建立第二張表 student2 並關聯

            CREATE TABLE "student2" ("id" int(11) NOT NULL,"name" char(16) NOT NULL,"class_id" int(11) NOT NULL,PRIMARY KEY ("id"),
            #主要是用來加快查詢速度的。Key是索引約束,對錶中字段進行約束索引的,都是經過primary foreign unique等建立的
            KEY "fk_class_key" ("class_id"), 
            #本表中的class_id關聯表class表中id,關聯後的名字爲fk_class_key
            CONSTRAINT "fk_class_key" FOREIGN KEY ("class_id") REFERENCES "class" ("id") )mysql

            此時若是class 表中不存在id 1,student表也插入不了,這就叫外鍵約束
            insertintostudent2(id,name,class_id) values(1,'alex', 1);
            #
            ERROR 1452 (23000): Cannot addorupdatea child row: a foreignkeyconstraintfails (`testdb`.`student2`, CONSTRAINT`fk_class_key` FOREIGNKEY(`class_id`) REFERENCES`class` (`id`))sql

            若是有student表中跟這個class表有關聯的數據,你是不能刪除class表中與其關聯的紀錄的
            delete from class where id =1;
            # 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`))

        • NULL值的處理
          MySQL使用 SQL SELECT 命令及 WHERE 子句來讀取數據表中的數據,可是當提供的查詢條件字段爲 NULL 時,該命令可能就沒法正常工做
          • IS NULL: 當列的值是NULL,此運算符返回true
          • IS NOT NULL: 當列的值不爲NULL, 運算符返回true
        • 鏈接
          • INNER JOIN 內鏈接(等值鏈接):獲取兩個表中字段匹配關係的記錄【其實就是隻顯示2個表的交集】
            select  * from  A  INNER JOIN B  on  A .a = B.b; (等於select A.*,B.*  from A,B where A.a = B.b;
            #將A表中的a列和B表中的b列內鏈接
          • LEFT JOIN 左鏈接:獲取左表全部記錄,即便右表沒有對應匹配的記錄【其實就是求差集】
            select  * from  a RIGHT JOIN b on A .a = B.b;
            #A表中存在可是B表中不存在的值則顯示NULL,即非差集的值顯示爲NULL
          • RIGHT JOIN 右鏈接:與 LEFT JOIN 相反,用於獲取右表全部記錄,即便左表沒有對應匹配的記錄
          • FULL JOIN【求並集】
            mysql 並不直接支持full join,可是可使用如下方法實現
            select  * from  A   left join B  on A .a = B.b   UNION  select * from  A  right join B   on  A .a = B.b;
            #使用UNION語法聯合兩條命令
      • 事務
        用於處理操做量大,複雜度高的數據
        • 特色
          • 在MySQL中只有使用了Innodb數據庫引擎的數據庫或表才支持事務
          • 事務處理能夠用來維護數據庫的完整性,保證成批的SQL語句要麼所有執行,要麼所有不執行
          • 事務用來管理insert,update,delete語句
        • 四個條件
          • 事務的原子性:一組事務,要麼成功;要麼撤回
          • 穩定性 : 有非法數據(外鍵約束之類),事務撤回
          • 隔離性:事務獨立運行。一個事務處理後的結果,影響了其餘事務,那麼其餘事務會撤回。事務的100%隔離,須要犧牲速度
          • 可靠性:軟、硬件崩潰後,InnoDB數據表驅動會利用日誌文件重構修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit選項 決定何時吧事務保存到日誌裏。
        • 實例
          1 mysql> begin; #開始一個事務
          2 mysql> insert into a (a) values(555);
          3 mysql> rollback; 回滾 , 這樣數據是不會寫入的,若是想提交直接使用commit進行提交
      • 索引 
        索引的創建對於MySQL的高效運行是很重要的,索引能夠大大提升MySQL的檢索速度
        • 普通索引
          • 查看索引
            show index from student;
          • 建立方式
            • 普通建立
              最基本的索引,它沒有任何限制。它有如下幾種建立方式:
              CREATE INDEX index_Name ON mytable(username(length));  
              若是是CHAR,VARCHAR類型,length能夠小於字段實際長度;若是是BLOB和TEXT類型,必須指定 length
            • 修改表結構
              ALTER  mytable ADD  INDEX [indexName] ON  (username(length)) 
            • 建立表的時候直接指定
              CREATE  TABLE  mytable(ID INT NOT NULL,username VARCHAR(16) NOT NULL,INDEX [indexName] (username(length))); 
          • 刪除索引
            DROP  INDEX [indexName] ON  mytable; 
        • 惟一索引
          索引列的值必須惟一,但容許有空值。若是是組合索引,則列值的組合必須惟一
          • 建立索引
            • 建立索引
              CREATE  UNIQUE  INDEX  indexName ON  mytable(username(length)) 
            • 修改表結構
              ALTER  mytable ADD UNIQUE [indexName] ON (username(length)) 
            • 建立表的時候直接指定
              CREATE TABLE mytable(ID INT NOT NULL,username VARCHAR(16) NOT NULL,UNIQUE [indexName] (username(length)));  
          • 使用ALTER添加和刪除索引
            • 有四種方式來添加數據表的索引
              • ALTER  TABLE  tbl_name  ADD  PRIMARY  KEY  (column_list): 該語句添加一個主鍵,這意味着索引值必須是惟一的,且不能爲 NULL
              • ALTER  TABLE  tbl_name  ADD  UNIQUE  index_name (column_list): 這條語句建立索引的值必須是惟一的(除了 NULL 外, NULL 可能會出現屢次)。
              • ALTER  TABLE  tbl_name  ADD  INDEX  index_name (column_list): 添加普通索引,索引值可出現屢次。
              • ALTER  TABLE  tbl_name  ADD  FULLTEXT index_name (column_list):該語句指定了索引爲 FULLTEXT ,用於全文索引。
            • 實例 
              ALTER  TABLE  testalter_tbl ADD  INDEX (c);
              ALTER 命令中使用 DROP 子句來刪除索引
              ALTER  TABLE  testalter_tbl DROP  INDEX (c);
          • 使用ALTER添加和刪除主鍵
            • 主鍵只能做用於一個列上,添加主鍵索引時,你須要確保該主鍵默認不爲空(NOTNULL
              ALTER TABLE testalter_tbl MODIFY i INT NOT NULL;
              ALTER TABLE testalter_tbl ADD PRIMARY KEY (i);
            • 使用 ALTER命令刪除主鍵(刪除指定時只需指定PRIMARY KEY,但在刪除索引時,你必須知道索引名
              ALTER TABLE testalter_tbl DROP PRIMARY KEY;
          • 顯示索引信息
            SHOW INDEX FROM table_name\G
    • pymysql        
      • 使用操做
        • 執行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 # 建立遊標(就是鼠標的位置或者就是begin;)
           7 cursor = conn.cursor()
           8   
           9 # 執行SQL,並返回受影響行數,插入數據
          10 effect_row = cursor.executemany("insert into hosts(host,color_id)values(%s,%s)", [("1.1.1.11",1),("1.1.1.11",2)])
          11 
          16 # 提交,否則沒法保存新建或者修改的數據
          17 conn.commit()
          18   
          19 # 關閉遊標
          20 cursor.close()
          21 
          22 # 關閉鏈接
          23 conn.close()
        • 獲取查詢數據
           1 import pymysql
           2   
           3 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
           4 cursor = conn.cursor()
           5 cursor.execute("select * from hosts")
           6   
           7 # 獲取第一行數據
           8 row_1 = cursor.fetchone()
           9   
          10 # 獲取前n行數據
          11 row_2 = cursor.fetchmany(3)
          12 
          13 # 獲取全部數據
          14 row_3 = cursor.fetchall()
          15   
          16 conn.commit()
          17 cursor.close()
          18 conn.close()
          19 
          20 #注:在fetch數據時按照順序進行,可使用cursor.scroll(num,mode)來移動遊標位置,如:
          21 #  一、cursor.scroll(1,mode='relative')  # 相對當前位置移動
          22 #  二、cursor.scroll(2,mode='absolute') # 相對絕對位置移動
        • 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()
      • SQLAlchemy
        SQLAlchemy是Python編程語言下的一款ORM框架,該框架創建在數據庫API之上,使用關係對象映射進行數據庫操做,簡言之即是:將對象轉換成SQL,而後使用數據API執行SQL並獲取執行結果
        • 優勢
          • 隱藏了數據訪問細節,「封閉」的通用數據庫交互,ORM的核心。他使得咱們的通用數據庫交互變得簡單易行,而且徹底不用考慮該死的SQL語句
          • ORM使咱們構造固化數據結構變得簡單易行
        • 缺點
          • 無可避免的,自動化意味着映射和關聯管理,代價是犧牲性能(早期,這是全部不喜歡ORM人的共同點)。如今的各類ORM框架都在嘗試使用各類方法來減輕這塊(LazyLoad,Cache),效果仍是很顯著的
        • 基本使用
            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 #鏈接數據庫
            8 engine = create_engine("mysql+pymysql://root:alex3714@192.168.16.86/oldboydb",encoding='utf-8', echo=True) 
            9 
           10 #生成orm基類
           11 Base = declarative_base() 
           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     #讀取所有數據庫的數據的時候可以格式化輸出,對下面的print(my_user)有效
           20     def __repr__(self):
           21         return "< %s name:%s >" %(self.id,self.name)
           22 # class Student(Base):
           23 #     __tablename__ = 'student' #表名
           24 #     id = Column(Integer, primary_key=True) #建立列
           25 #     name = Column(String(32),nullable=False)
           26 #       register_date=Column(DATE,,nullable=False)
           27 #     password = Column(String(32),nullable=False)
           28 
           29 
           30 #建立表結構
           31 Base.metadata.create_all(engine) 
           32 
           33 #建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
           34 Session_class = sessionmaker(bind=engine)
           35 
           36 #生成session實例 
           37 Session = Session_class() 
           38  
           39 #生成你要建立的數據對象
           40 user_obj = User(name="alex",password="alex3714") 
           41 
           42 #此時還沒建立對象呢,不信你打印一下id發現仍是None
           43 print(user_obj.name,user_obj.id)  
           44 
           45 #把要建立的數據對象添加到這個session裏, 一會再統一建立
           46 Session.add(user_obj) 
           47 
           48 #此時也依然還沒建立
           49 print(user_obj.name,user_obj.id) 
           50 
           51 #現此才統一提交,建立數據
           52 Session.commit() 
           53 
           54 #獲取全部數據
           55 print(Session.query(User.name,User.id).all() )
           56 
           57 #查詢
           58 my_user = Session.query(User).filter_by(name="alex").all()
           59 print(my_user[0].name,data[0].password)
           60 print(my_user)
           61 my_user = Session.query(User).filter(User.id>1).all() #判斷相等則使用雙等號==
           62 print(my_user)
           63 objs = Session.query(User).filter(User.id>0).filter(User.id<7).all() #多條件查詢,2個filter的關係至關於 user.id >1 AND user.id <7 的效果
           64 print(Session.query(User,Student).filter(User.id==Student.id).all()) #多表查詢
           65     #相等 :query.filter(User.name == 'ed')
           66     #不相等 :query.filter(User.name != 'ed')
           67     #LIKE :query.filter(User.name.like('%ed%'))
           68     #in :query.filter(User.name.in_(['ed', 'wendy', 'jack']))
           69     #not in :query.filter(~User.name.in_(['ed', 'wendy', 'jack'])) 
           70 
           71 #修改
           72 my_user = Session.query(User).filter_by(name="alex").first()
           73 my_user.name = "Alex Li"
           74 Session.commit()
           75 
           76 #回滾
           77 my_user = Session.query(User).filter_by(id=1).first()
           78 my_user.name = "Jack" 
           79 fake_user = User(name='Rain', password='12345')
           80 Session.add(fake_user)
           81 print(Session.query(User).filter(User.name.in_(['Jack','rain'])).all() )  #這時看session裏有你剛添加和修改的數據
           82 Session.rollback() #此時你rollback一下
           83 print(Session.query(User).filter(User.name.in_(['Jack','rain'])).all() ) #再查就發現剛纔添加的數據沒有了
           84 # Session.commit()
           85 
           86 #統計和分組
           87 Session.query(User).filter(User.name.like("Ra%")).count() #統計
           88 from sqlalchemy import func
           89 print(Session.query(func.count(User.name),User.name).group_by(User.name).all() )#分組,至關於SELECT count(user.name) AS count_1, user.name AS user_name FROM user GROUP BY user.name
           90 
           91 #外鍵關聯
           92 from sqlalchemy import ForeignKey
           93 from sqlalchemy.orm import relationship
           94 class Address(Base): #咱們建立一個addresses表,跟user表關聯
           95     __tablename__ = 'addresses'
           96     id = Column(Integer, primary_key=True)
           97     email_address = Column(String(32), nullable=False)
           98     user_id = Column(Integer, ForeignKey('user.id')) 
           99     user = relationship("User", backref="addresses") #這個容許你在user表裏經過backref字段反向查出全部它在addresses表裏的關聯項
          100     def __repr__(self):
          101         return "<Address(email_address='%s')>" % self.email_address
          102 obj = Session.query(User).first()
          103 for i in obj.addresses: #經過user對象反查關聯的addresses記錄
          104     print(i)
          105 addr_obj = Session.query(Address).first()
          106 print(addr_obj.user.name)  #在addr_obj裏直接查關聯的user表
          107 
          108 #建立關聯對象
          109 obj = Session.query(User).filter(User.name=='rain').all()[0]
          110 print(obj.addresses)
          111 obj.addresses = [Address(email_address="r1@126.com"), #添加關聯對象
          112                  Address(email_address="r2@126.com")]
          113 Session.commit()
        • 多外鍵關聯
           1 #>>>>>>>>>>>orm_many_fk.py
           2 from sqlalchemy import Integer, ForeignKey, String, Column
           3 from sqlalchemy.ext.declarative import declarative_base
           4 from sqlalchemy.orm import relationship
           5 from sqlalchemy import creat_engine
           6  
           7 Base = declarative_base()
           8  
           9 class Customer(Base):
          10     __tablename__ = 'customer'
          11     id = Column(Integer, primary_key=True)
          12     name = Column(String(64))
          13  
          14     billing_address_id = Column(Integer, ForeignKey("address.id")) #外鍵一
          15     shipping_address_id = Column(Integer, ForeignKey("address.id")) #外鍵二
          16  
          17     billing_address = relationship("Address", foreign_keys=[billing_address_id])
          18     shipping_address = relationship("Address", foreign_keys=[shipping_address_id])
          19  
          20 class Address(Base):
          21     __tablename__ = 'address'
          22     id = Column(Integer, primary_key=True)
          23     street = Column(String(64))
          24     city = Column(String(64))
          25     state = Column(String(64))
          26     
          27 engine = create_engine("mysql+pymysql://root:alex3714@localhost/testdb",encoding='utf-8', echo=True)
          28 #Base.metadata.create_all(engine) #建立表結構
           1 #>>>>>>>>>>>orm_api.py
           2 import orm_many_fk
           3 from sqlalchemy.orm import sessionmaker
           4 
           5 #>>>>>建立數據
           6 Session_class=sessionmaker(bind=orm_many_fk.engine)#建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
           7 Session = Session_class() #生成session實例 
           8 
           9 addr1=orm_many_fk.Address(street="tiantongyuan",city="changping",state="beijing")
          10 addr2=orm_many_fk.Address(street="wudaokou",city="haidian",state="beijing")
          11 addr3=orm_many_fk.Address(street="yanjiao",city="langfang",state="hebei")
          12 session.add_all([addr1,addr2,addr3])
          13 
          14 c1=orm_many_fk.Customer(name="alex",billing_address=addr1,shipping_address=addr2)
          15 c2=orm_many_fk.Customer(name="jack",billing_address=addr3,shipping_address=addr3)
          16 session.add_all([c1,c2])
          17 
          18 session.commit()
          19 
          20 #>>>>>查詢數據
          21 obj=session.query(orm_many_fk.Customer).filter(orm_many_fk.Customer.name=="alex").first()
          22 print(obj.name,obj.billing_address,obj.shipping_address)
        • 多對多關係
          一本書多個做者,一個做者多本書
           1 #orm_m2m.py
           2 from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey
           3 from sqlalchemy.orm import relationship
           4 from sqlalchemy.ext.declarative import declarative_base
           5 from sqlalchemy import create_engine
           6 from sqlalchemy.orm import sessionmaker
           7 
           8 #>>>>>>>>>>建立
           9 Base = declarative_base()
          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 class Book(Base):
          16     __tablename__ = 'books'
          17     id = Column(Integer,primary_key=True)
          18     name = Column(String(64))
          19     pub_date = Column(DATE)
          20     authors = relationship('Author',secondary=book_m2m_author,backref='books')
          21 
          22     def __repr__(self):
          23         return self.name
          24 
          25 class Author(Base):
          26     __tablename__ = 'authors'
          27     id = Column(Integer, primary_key=True)
          28     name = Column(String(32))
          29 
          30     def __repr__(self):
          31         return self.name
          32         
          33 engine = create_engine("mysql+pymysql://root:alex3714@localhost/testdb?charset=utf8",encoding='utf-8')#?charset=utf8可以使鏈接支持中文
          34 Base.metadata.create_all(engine) #建立表結構
           1 #orm_fk.py
           2 import orm_m2m
           3 from sqlalchemy.orm import sessionmaker
           4 
           5 #>>>>>>>建立
           6 Session_class=sessionmaker(bind=orm_many_fk.engine)#建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
           7 Session = Session_class() #生成session實例 
           8 
           9 b1=orm_m2m.Book(name="learn python with alen",pub_date="2019-07-14")
          10 b2=orm_m2m.Book(name="learn zhuangbility with alen",pub_date="2019-07-14")
          11 b3=orm_m2m.Book(name="learn hook up girls with alex",pub_date="2019-07-14")
          12 
          13 a1=orm_m2m.Author(name="alex")
          14 a2=orm_m2m.Author(name="jack")
          15 a3=orm_m2m.Author(name="rain")
          16 
          17 b1.authors=[a1,a3]
          18 b3.authors=[a1,a2,a3]
          19 
          20 session.add_all([b1,b2,b3,a1,a2,a3])
          21 session.commit()
          22 
          23 #>>>>>>查詢
          24 author_obj=session.query(orm_m2m.Author).filter(orm_m2m.Author.name=="alex").first()
          25 print(author_obj.books[1].pub_date)
          26 book_obj=session.query(orm_m2m.Book).filter(orm_m2m.Book.id==2).first()
          27 print(book_obj.authors)
          28 
          29 #>>>>>>>刪除
          30 #經過書刪除做者
          31 #author_obj =session.query(Author).filter_by(name="jack").first()
          32 #book_obj =session.query(Book).filter_by(name="learn hook up girls with alex").first()
          33 book_obj.authors.remove(author_obj)#刪除id=2的這本書
          34 session.commit()
          35 #直接刪除做者 
          36 author_obj =session.query(Author).filter_by(name="alex").first()
          37 s.delete(author_obj)
          38 s.commit()
          39 
          40 #處理中文
          41 #sqlalchemy設置編碼字符集必定要在數據庫訪問的URL上增長charset=utf8,不然數據庫的鏈接就不是utf8的編碼格式
          42 b4=orm_m2m.Book(name="跟alex去泰國",pub_date="2019-07-14")
          43 session.add_all([b4,])
相關文章
相關標籤/搜索