Python工具箱系列(三十四)

来源:https://www.cnblogs.com/shanxihualu/archive/2023/05/29/17440033.html
-Advertisement-
Play Games

SQLAlchemy是著名的ORM(Object Relational Mapping-對象關係映射)框架。其主要作用是在編程中,把面向對象的概念跟資料庫中表的概念對應起來。對許多語言(例如JAVA/PYTHON)來說就是定義一個對象,並且這個對象對應著一張資料庫的表。而這個對象的實例,就對應著表中... ...


SQLAlchemy是著名的ORM(Object Relational Mapping-對象關係映射)框架。其主要作用是在編程中,把面向對象的概念跟資料庫中表的概念對應起來。對許多語言(例如JAVA/PYTHON)來說就是定義一個對象,並且這個對象對應著一張資料庫的表。而這個對象的實例,就對應著表中的一條記錄。

其整體思路如下圖所示:

其中類、對象與屬性與資料庫相關內容的對應關係如下圖所示:

ORM的優點:

 

  • 數據模型與代碼統一定義,更新與維護簡單,代碼高度重用一致。

  • ORM有現成的工具,很多功能都可以自動完成,比如表格增刪、預處理、事務等。

  • 基於ORM的業務代碼比較簡單,代碼量少,語義性好,容易理解。

  • 你不必編寫性能不佳的SQL。

ORM的缺點:

 

  • ORM庫多層封裝,實現巧妙,需要花很多精力學習和設置。

  • 對於複雜的查詢,ORM要麼是無法表達,要麼是性能不如原生的SQL。

  • ORM抽象掉了資料庫層,開發者無法瞭解底層的資料庫操作,也無法定製一些特殊的SQL。

 

 

 從整體上看,ORM節省了開發時間,減少了代碼錯誤的可能性,同時能夠方便地在多個資料庫間靈活遷移,還是非常值得使用。而在python語言中,SQLAlchemy是著名的ORM框架之一,它的整體架構如下圖所示:

從圖中可以看出,SQLAIchemy是分層架構,由Core以及ORM兩部分組成。其中,Core完成了與資料庫操作的各類封閉,是相對低層的。而ORM層則利用Core層的能力進行更巨集觀的操作。因此,在一段python代碼中,使用Core與ORM層同時來操作資料庫也是可行的,並不矛盾與衝突。

下麵先從最基本的表格創建做起。非ORM編程中,表格的創建無非兩個途徑:

●基於DBMS本身提供的CLI/GUI界面,發出DDL語句進行資料庫/表格本身的增刪改查。

●使用語言連接資料庫後,發出命令來對資料庫/表格進行增刪改查。

而由於每種資料庫都有自己的方言,所以命令語句各有差異,需要不斷地調整。而使用SQLAlchemy則實現了代碼統一。例如以下代碼在mssql以及mysql上創建表格,並且可以查詢表格的元數據,以及插入數據後的查詢。

from sqlalchemy import (Column, Integer, MetaData, String, Table,
                        create_engine, text, Float, DateTime, ForeignKey)
from sqlalchemy_utils.functions import create_database, database_exists

configure_pg = {"user": "postgres",
                'password': '88488848',
                'dns': 'dbserver.home',
                "port": 5432,
                'prefix': 'postgresql+psycopg2',
                'postfix': ''
                }

configure_mssql = {"user": "sa",
                   'password': '88488848',
                   'dns': 'dbserver.home',
                   "port": 1433,
                   'prefix': 'mssql+pymssql',
                   'postfix': '?charset=utf8'
                   }

configure_mysql = {"user": "root",
                   'password': '88488848',
                   'dns': 'dbserver.home',
                   "port": 3306,
                   'prefix': 'mysql+mysqlconnector',
                   'postfix': ''
                   }

config = {'mssql': configure_mssql,
          'mysql': configure_mysql, 'postgresql': configure_pg}

database_name = 'testdb'
table_sensor_location = "sensor_location"
table_sensor_data = "sensor_data"


def linkdb(targetstr):
    """
    連接不同的資料庫

    Args:
        targetstr (string): 資料庫名稱

    Returns:
        engine: 用於後續的資料庫連接
    """
    if targetstr in config.keys():
        item = config[targetstr]
        connectstring = f"{item['prefix']}://{item['user']}:{item['password']}@{item['dns']}:{item['port']}/{database_name}{item['postfix']}"
        engine = create_engine(connectstring, echo=True, future=True)

    # 如果資料庫不存在,則創建之
    if not database_exists(engine.url):
        create_database(engine.url)

    # 做一個測試,不針對任何表
    with engine.connect() as conn:
        result = conn.execute(text("select 'hello world'"))
        print(result.all())
    return engine


def createtbs(connector):
    """"
    創建資料庫中的2張表。用於保存感測器數據與感測器本身的信息
    """
    metadata_obj = MetaData()

    # 描述感測器的表
    sensor_location_tb = Table(
        table_sensor_location,
        metadata_obj,
        Column('id', Integer, primary_key=True, autoincrement=False),
        Column('location', String(30), nullable=False)
    )

    # 保存感測器數據的表
    sensor_data_tb = Table(
        table_sensor_data,
        metadata_obj,
        Column('id', Integer, primary_key=True, autoincrement=False),
        Column('sensor_id', ForeignKey(
            f'{table_sensor_location}.id'), nullable=False),
        Column('area', String(30)),
        Column('pm25', Float),
        Column('timestamp', DateTime)
    )
    print(sensor_data_tb.compile())

    # 創建並返回表
    metadata_obj.create_all(connector)
    return sensor_data_tb, sensor_location_tb


def tableinfo(connector, tablename):
    """
    獲得指定表名的相關元數據信息

    Args:
        connector (engine): 資料庫連接器
        tablename (string): 要查詢的表名
    """
    metadata_obj = MetaData()
    some_table = Table(tablename, metadata_obj, autoload_with=connector)
    print([c.name for c in some_table.columns])


def gensonsorinfo(connector):
    with connector.connect() as conn:
        conn.execute(text(f"INSERT INTO {table_sensor_location} (id, location) VALUES (:x, :y)"),
                     [{"x": 1, "y": '1號樓'}, {"x": 2, "y": '2號樓'}])

        conn.commit()

        result = conn.execute(
            text(f"SELECT id, location FROM {table_sensor_location}"))
        for x, y in result:
            print(f"id: {x}  location: {y}")


# 依次連接多個資料庫。從而驗證代碼的一致性
for dbname in config.keys():
    con = linkdb(dbname)
    createtbs(con)
    tableinfo(con, table_sensor_data)
    tableinfo(con, table_sensor_location)
    gensonsorinfo(con)

從代碼可以看出,可以用統一的訪問方式來操作mssql/mysql/postgresql三種資料庫。而且,以上方式與前文中的基於游標的寫法類似。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 歡迎來到系列第八篇,異常處理的深入探討。本文將分五部分展開。首先,我們將學習Python異常處理的基礎知識,理解`try/except`語句的用法。然後,我們將瞭解Python的常見異常類型並通過實例理解它們的作用。第三部分,我們將更深入地解析`try-except`塊,理解其工作原理及更加複雜的用... ...
  • 哈嘍大家好,我是鹹魚 相信小伙伴們在學習 python 數據分析的過程中或多或少都會聽說或者使用過 pandas pandas 是 python 的一個拓展庫,常用於數據分析 今天鹹魚將介紹幾個關於 pandas 導入數據的方法和技巧 ## 從 URL 獲取 csv 數據 關於 pandas 導入 ...
  • ## 教程簡介 Angular Highcharts是一個基於Angular的開源組件,可在Angular應用程式中提供優雅且功能豐富的高圖表可視化,並可與Angular組件無縫配合使用。 [Angular Highcharts入門教程](https://www.itbaoku.cn/tutoria ...
  • ## 教程簡介 Flume是Apache下麵的一個分散式組件,它提供高效,可靠的收集,整合,傳輸日誌數據的服務。Flume可以理解成一個管道,它連接數據的生產者和消費者,它從數據的生產者(Source)獲取數據,保存在自己的緩存(Channel)中,然後通過Sink發送到消費者。它不對數據做保存和復 ...
  • ## 測試環境: > MySQL版本:8.0 資料庫表:T (主鍵id,唯一索引c,普通欄位d) ![](http://img.javastack.cn/1685072039483867.png) 如果你的業務設計依賴於自增主鍵的連續性,這個設計假設自增主鍵是連續的。但實際上,這樣的假設是錯的,因為 ...
  • 編碼如下:#include <stdio.h> void swap(int* x,int* y ){ int tmp; tmp=*x; *x=*y; *y=tmp ; }; int main(){ int a=4; int b=5; printf("befer\n"); printf("a=%d\n ...
  • @[TOC] # 1.背景 最近項目是國際項目,所以需要經常需要用到UTC時間和local時間的轉換。 所以整理了一下時間戳工具類,方便使用。 這裡主要用到的包就是datatime、time、pytz。 # 2. 遇到的坑 直接看測試案例 ```python tzinfo=pytz.timezone ...
  • 本文將為大家詳細講解Java中Properties配置類怎麼用,這是我們進行開發時經常用到的知識點,也是大家在學習Java中很重要的一個知識點,更是我們在面試時有可能會問到的問題!文章較長,乾貨滿滿,建議大家收藏慢慢學習。文末有本文重點總結,主頁有全系列文章分享。技術類問題,歡迎大家和我們一起交流討... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...