Python za posledních 5 let prudce vzrostl na popularitě. Mnoho nových programátorů je přitahováno kvůli jeho jemné křivce učení ve srovnání s jinými programovacími jazyky. Zkušení programátoři jsou k němu přitahováni kvůli jeho rozšiřitelnosti a výkonu. Jedním z hlavních hnacích sil tohoto masového přijetí je však snadnost, kterou Python dokáže pracovat s databázemi. Tento tutoriál programování v Pythonu prozkoumá, jak začít používat Python pro komunikaci s SQL Express pomocí Pythonu 3.
Python a programování databází
Začátečník v Pythonu, který si přeje integrovat funkcionalitu databáze do jakéhokoli softwarový projekt napsaný v jakémkoli jazyk musí mít základní znalosti alespoň dvou jazyky. Prvním je samozřejmě Python a druhým je specifický strukturovaný dotazovací jazyk (SQL), který databáze používá. Přestože je SQL standardizován, v praxi to není univerzální jazyk, ale implementace mezi různými databázemi jsou si dostatečně blízké, takže přesun z jedné databáze do druhé není tak velký problém, pokud má člověk pohodlnou úroveň zkušeností s vývojem databázových aplikací.
Dalším důležitým faktorem pro databáze je, že všechny vyžadují software pro správu. Tyto nástroje pro správu mohou pomoci s nastavením přístupu a bezpečnostních oprávnění v rámci databáze. Mohou být také použity k ladění databázových aplikací, protože umožňují vývojářům dělat věci jako:
- Vytváření a správa obsahu tabulek, pohledů a dalších databázových objektů. To zahrnuje vztahy mezi tabulkami a také konfiguraci pravidel integrity.
- Přímá interakce s databází prostřednictvím zadání kódu SQL.
- Ladění syntaxe SQL.
- Vrátí (do určité míry) škody způsobené nesprávně zakódovanými příkazy SQL v aplikaci.
I když se vývojář rozhodne použít databázi založenou na noSQL, jako je MongoDB, bude stále existovat problém naučit se syntaxi kódování specifickou pro databázi, která je potřebná k tomu, aby takové řešení fungovalo. Samozřejmě to nejsou odstrašující prostředky, jsou to pouze technické faktory, které je třeba vzít v úvahu u každého projektu vývoje softwaru.
Ovladače Pythonu a databáze
Python, stejně jako jakýkoli jiný programovací jazyk, neumí nativně komunikovat s danou databází. Vyžaduje to přidání dalších modulů pro konkrétní databázový server. Z hlediska nejlepší praxe je nejlepší použít modul ovladače databáze, který je specifický pro databázový server vybraný pro softwarový projekt. Tím zajistíte, že Python bude mít přístup ke všem funkcím databázového serveru, i když to bude spojeno s vyšší cenou použití specifické programovací syntaxe pro modul. I když byly učiněny určité pokusy vytvořit „univerzální“ moduly databázových ovladačů, které se mohou připojit k více databázovým serverům, tyto pokusy jsou často na úkor ztráty přístupu k určitým funkcím konkrétního databázového serveru.
Co je SQL Express?
SQL Server je řešením databázového serveru pro Windows po celá desetiletí. I když je to asi tak daleko od bezplatného řešení databázového serveru, jak se dá získat, Microsoft poskytuje nulovou, zkrácenou variantu SQL Server s názvem SQL Express. SQL Express je ideální výukový nástroj pro začátečníky, protože podporuje stejnou syntaxi SQL jako SQL Server. SQL Express i SQL Server používají vlastní rozšíření SQL nazvané „Transact-SQL“, známé také jako „T-SQL“. SQL Express i SQL Server podporují použití uživatelských účtů Windows a tradičních systémů uživatelských jmen a hesel pro správu přístupu.
Python komunikuje s SQL Express nebo SQL Server pomocí modulu s názvem PyODBC . SQL Server i SQL Express jsou spravovány samostatnou aplikací pro Windows s nulovými náklady nazvanou „SQL Server Management System“, populárně známá jako „SSMS“. V době psaní tohoto článku jsou SQL Express i SSMS samostatné soubory ke stažení od společnosti Microsoft:
- Stažení SSMS
- Stažení SQL Express
Jak nakonfigurovat SQL Express pro vývoj Pythonu
SQL Express, stejně jako SQL Server, podporuje dva druhy ověřování. Prvním je ověřování založené na uživatelském účtu Windows uživatele, známém také jako „důvěryhodné připojení“. Druhým je tradiční ověřování založené na uživatelském jménu a hesle, které je implementováno v tom, co se nazývá „Autentizace ve smíšeném režimu“. Ověřování ve smíšeném režimu podporuje ověřování na základě uživatelského účtu systému Windows a ověřování na základě uživatelského jména a hesla. Neexistuje žádný způsob, jak podporovat ověřování na základě uživatelského jména a hesla samo o sobě na serveru SQL Server nebo SQL Express.
Společnost Microsoft ustoupila od ověřování ve smíšeném režimu, protože jednou z hlavních výhod používání důvěryhodných připojení je to, že přihlašovací údaje k databázi není nutné ukládat v kódu aplikace. Demonstrace v tomto článku jej také nebude používat.
NEKopírování připojovacího řetězce po instalaci
Jedním z bodů sporu pro vývojáře aplikací na úrovni začátečníků je počáteční zmatek kolem připojovacích řetězců SQL Server. Pokud instalujete SQL Express, instalační program poskytne připojovací řetězec pro vytvořenou instanci SQL Express po instalaci. Bohužel poskytnutý připojovací řetězec pravděpodobně nebude fungovat s PyODBC . I když je lákavé nechat se „ukolébat“ do pocitu bezpečí s tímto „zadarmo“, způsobí to víc problémů, než stojí za to.
Obrázek 1 – Získání připojovacího řetězce z instalačního programu SQL Express
Všimněte si, že v době psaní tohoto článku instalační program pro SQL Express také obsahuje odkaz ke stažení instalačního programu SSMS.
Jak vytvořit databázi v SQL Express
Jakmile jsou nainstalovány SQL Express i SSMS, je čas vytvořit základní databázi s vhodnými omezeními přístupu. Nejjednodušší způsob, jak spustit SSMS, je kliknout na Start v systému Windows, zadejte do vyhledávacího pole „ssms“, počkejte, až se v pravém horním rohu zobrazí „Microsoft SQL Server Management Studio 18“, a poté klikněte na tlačítko Otevřít odkaz na pravé straně panelu nabídky Start:
Obrázek 2 – Spuštění SSMS
Po spuštění SSMS se zobrazí následující dialogové okno:
Obrázek 3 – dialogové okno pro otevření SSMS
S Windows Authentication není potřeba zadávat žádné přihlašovací údaje. Uživatelský účet systému Windows pod kterým byl SQL Express nainstalován, má administrátorská oprávnění pro instanci SQL Express. Jednoduše klikněte na Připojit pokračovat.
Zcela vlevo v okně aplikace SSMS , bude zde Průzkumník objektů . Chcete-li vytvořit novou databázi, klikněte pravým tlačítkem na Databáze a vyberte Vytvořit databázi z Kontextu menu:
Obrázek 4 – Vytvoření nové databáze – Část 1 ze 2
Kliknutím na Nová databáze… otevře nové dialogové okno, které umožňuje zadat údaje o nové databázi. Pro tuto ukázku se databáze bude jmenovat RazorDemo , trochu jako návrat k předchozímu článku o vývoji aplikací založených na Razor v C#. Do textového pole vedle Název databáze zadejte název databáze a poté klikněte na OK tlačítko ve spodní části dialogového okna. Všimněte si, že na obrázku níže jsou sloupce pro Logický název souborů bylo mírně rozšířeno tak, aby byly plné Logické názvy z vytvářených databázových souborů bylo odhaleno:
Obrázek 5 – Vytvoření nové databáze – Část 2 ze 2
Nová databáze se poté objeví v Průzkumníku objektů v části Databáze složka:
Obrázek 6 – Nově vytvořená databáze „RazorDemo“
Jak vytvářet tabulky v SQL Express
Relační databáze není opravdu užitečná bez tabulek k ukládání dat a nejpřímějším způsobem, jak tyto tabulky vytvořit, je použití kódu SQL. Všimněte si, že lze použít Průvodce vytvořením tabulky k vytvoření tabulky je použití kódu SQL rychlejší, jednodušší a mnohem přímočařejší. Začněte kliknutím pravým tlačítkem na RazorDemo záznam databáze a poté klikněte levým tlačítkem na Nový dotaz možnost v kontextovém okně:
Obrázek 7 – Otevření nového okna dotazu
Napravo od Průzkumníka objektů se zobrazí okno editoru dotazů podobné tomu níže :
Obrázek 8 – okno editoru dotazů
Kód pro vytvoření tabulky je uveden v seznamu níže:
use RazorDemo; # See the Important Note below create table artists (rcdid int not null identity primary key, artist_name varchar(max)); create table albums (rcdid int not null identity primary key, artist_id int not null references artists(rcdid) on delete cascade, album_name varchar(max)); Listing 1 - Table Creation SQL Code
Všimněte si, že při vytváření okna editoru dotazů z databáze obvykle zaručuje, že vybraná databáze bude ta, proti které se kód spouští, je dobré vždy explicitně použít zamýšlenou databázi na začátku kódu. použití příkaz explicitně vybere název databáze, která za ním následuje.
Stiskněte F5 nebo kliknutím na tlačítko Provést tlačítko provede příkazy proti RazorDemo databáze. Pokud je provedení úspěšné, zobrazí se v části „Zprávy zpráva, která o tom informuje pole níže:
Obrázek 9 – Úspěšné vytvoření tabulky
Nově vytvořené tabulky a jejich sloupce lze zobrazit v Průzkumníku objektů také. Všimněte si, že někdy Obnovit K zobrazení nových objektů v databázi může být nutné vybrat možnost z kontextové nabídky, která se zobrazí po kliknutí pravým tlačítkem na databázi:
Obrázek 10 – Obnovení Průzkumníka objektů
Obrázek 11 – Nové tabulky a jejich sloupce
V tomto okamžiku lze SSMS bezpečně zavřít.
Všimněte si, že SSMS funguje stejně s jakoukoli databází SQL Server. Vždy je nejlepším postupem uložit veškerý kód pro vytváření tabulek bez ohledu na to, jaký databázový server používáte. Přestože SQL Server a SQL umožňují obnovu takových skriptů, oba umožňují použití šifrování i u takových příkazů a v těchto případech nelze kód obnovit.
Python a SQL Express
Normálně by zde byla potřeba diskuse o zabezpečení SQL Serveru, ale protože Trusted Connections bude použito, pokud běžící proces spouštějící kód Pythonu vlastní uživatel systému Windows který již má přístup k databázi, ke které se přistupuje, tato diskuse nebude potřeba. Mějte na paměti, že jak SQL Server, tak SQL Express nabízejí velmi robustní přizpůsobení související se zabezpečením, ale ty jsou nad rámec článku určeného pro začátečníky.
Nezapomínejte na správné zabezpečení databáze u jakékoli aplikace běžící v produkčním prostředí! Ujistěte se, že uživatelskému účtu, který bude přistupovat k databázi v projekčním prostředí, jsou udělena pouze ta nejmenší možná oprávnění.
Verze Pythonu použitá pro tyto příklady kódu je 3.10 a byla nainstalována prostřednictvím obchodu Microsoft Store ve Windows. Instalace Pythonu pomocí této metody přidá spustitelné soubory Pythonu a PIP3 do systémové cesty, takže úplné cesty k těmto příkazům nebude nutné zadávat do Příkazového řádku Okna. Pro zadávání kódu je dobrý textový editor s nulovými náklady Notepad++.
Otevření příkazového řádku systému Windows
Spuštění kódu Pythonu se nejlépe provádí pomocí Příkazového řádku . Přístup k Příkazovému řádku , klikněte na tlačítko Start ve Windows a zadejte cmd do vyhledávacího pole. Počkejte na Příkazový řádek a poté klikněte na tlačítko Otevřít odkaz na pravé straně nabídky Start :
Obrázek 12 – Otevření příkazového řádku
Typický Příkazový řádek okno vypadá takto:
Obrázek 13 – Typický příkazový řádek
Jak nainstalovat PyODBC
PyODBC je modul Pythonu, který umožňuje Pythonu přistupovat k SQL Serveru i SQL Express. Po instalaci Pythonu přes Microsoft Store, PyODBC lze přidat do Pythonu pomocí příkazu:
pip3 install pyodbc
Obrázek 14 – Úspěšná instalace PyODBC
Všimněte si, že pokud je nainstalováno více verzí Pythonu, například Python 2 a Python 3, může být nutné přidat předponu pip3 příkaz s úplnou cestou WIndows k příkazu pro příslušnou verzi Pythonu.
Všimněte si také, že pokud je nainstalován pouze Python 3, pip3 příkaz by měl být stále používán přes obecnější pip příkaz, protože toto je správná konvence.
Psaní kódu Python
Nyní, když je databáze nakonfigurována a PyODBC jsou nainstalovány, lze databázi naplnit. V případě databáze, která katalogizuje interprety a alba, postačí nějaká náhodně vygenerovaná jména kapel a alb. Kód Pythonu pro připojení k databázi je také zahrnut, ale vložky (zatím):
# bad-band-name-maker.py import sys import random import pyodbc part1 = ["The", "Uncooked", "Appealing", "Larger than Life", "Drooping", "Unwell", "Atrocious", "Glossy", "Barrage", "Unlawful"] part2 = ["Defeated", "Hi-Fi", "Extraterrestrial", "Adumbration", "Limpid", "Looptid", "Cromulent", "Unsettled", "Soot", "Twinkle"] part3 = ["Brain", "Segment", "Audio", "Legitimate Business", "Mentality", "Sound", "Canticle", "Monsoon", "Preserves", "Hangout"] part4 = ["Cougar", "Lion", "Lynx", "Ocelot", "Puma", "Jaguar", "Panther"] part5 = ["Fodder", "Ersatz Goods", "Leftovers", "Infant Formula", "Mush", "Smoothie", "Milkshakes"] def main(argv): # Connect to the RazorDemo database. conn = pyodbc.connect("Driver={ODBC Driver 17 for SQL Server};Server=localhost\SQLEXPRESS;Database=RazorDemo;Trusted_Connection=yes;") # Generate 15 bad band names: for x in range(1, 16): rand1 = random.randrange(0, 9) rand2 = random.randrange(0, 9) rand3 = random.randrange(0, 9) badName = part1[rand1] + ' ' + part2[rand2] + ' ' + part3[rand3] print ("Band name [" + str(x) + "] is [" + badName + "]") for y in range(1, 3): rand4 = random.randrange(0, len(part4)) rand5 = random.randrange(0, len(part5)) albumName = part4[rand4] + " " + part5[rand5] print ("\tAlbum [" + albumName + "]") # Close the Connection conn.close() return 0 if __name__ == "__main__": main(sys.argv[1:]) Listing 2 - Making up some data
Výsledkem je následující výstup:
Obrázek 15 – Náhodně generované názvy kapel
Všimněte si použití cd příkaz pro přechod do adresáře, kde je uložen kód Pythonu. PyODBC připojit() funkce selže, pokud je aktuálně přihlášený Uživatelský účet Windows není uveden jako uživatel s přístupem v SQL Express. To je problém pouze v případě, že je databáze vytvořena pomocí jednoho uživatelského účtu Windows ale kód je spuštěn pod jiným uživatelským účtem Windows .
Nejméně nejhorší způsob vkládání dat do SQL a PyODBC
Mnoho začínajících vývojářů Pythonu je v pokušení volat do PyODBC volání INSERT prohlášení v následujících částech kódu a v kontextu toho, co bude uvedeno dále, to není špatný nápad:
Obrázek 16 – „Téměř“ špatný způsob práce s databází
Důvod, proč používat volání PyODBC k provedení INSERTů , VYBERE a další funkce související s databází, jako je UPDATE nebo SMAZAT , v rámci smyček může být špatné, protože s každým z těchto volání přichází režie. V rámci smyčky, která by se mohla potenciálně opakovat stokrát, tisíckrát nebo dokonce vícekrát, to může mít za následek značné množství času (minuty nebo více) na běh skriptu. U webových aplikací, které používají takový přístup, se problémy s výkonem dále prohlubují, protože mnoho webových serverů ukládá omezení doby, po kterou může skript běžet. Nikdy za žádných okolností nepředávejte uživatelsky vytvořené vstupy přímo do databáze. Vždy zkontrolujte vstup, abyste se ujistili, že nenaruší funkčnost databáze nebo nezpůsobí bezpečnostní problém prostřednictvím útoku SQL Injection.
V ideálním případě by bylo vhodné použít výše uvedené smyčky k vytvoření dávky SQL (seznam příkazů) a poté mít PyODBC spustit na této jediné dávce, ale to by byl velmi špatný nápad, pokud by data nebyla dezinfikována.
Proč by měla být data dezinfikována? Důvod se scvrkává na bezpečnost, protože uživatelskému vstupu nelze nikdy věřit. Dezinfekce dat znamená jejich reprezentaci způsobem, který zabrání vykonání čehokoli jiného než příkazu SQL vytvořeného vývojářem programu. Uživatel by mohl předat zlomyslně vytvořený řetězec, který by umožnil spuštění libovolně vytvořeného kódu SQL. Toto je známé jako útok SQL Injection. Zatímco datové hodnoty vstupující do dávky lze dezinfikovat, proces tak činí mimo rámec úvodního tutoriálu.
PyODBC poskytuje mechanismus pro ochranu databáze před útoky SQL Injection dezinfekcí uživatelských vstupů. Ty zahrnují použití parametrizovaných příkazů , také označované jako připravené výpisy . Zabezpečení musí být vždy prioritou, i když je to na úkor rychlosti nebo jiných metrik výkonu.
Uživatelský účet Windows, který má přístup k této databázi, má ve výchozím nastavení oprávnění správce systému. To znamená, že pokud dojde k útoku SQL Injection, uživatel se zlými úmysly může získat přístup ke všem datům v každé databázi na serveru. V praxi by žádný účet s oprávněními sysadmin neměl přistupovat k žádné databázi z kódu Python.
Níže uvedený seznam rozšiřuje první příklad kódu Pythonu pomocí PyODBC kurzory pro vložení dat:
# bad-band-name-maker2.py import sys import random import pyodbc part1 = ["The", "Uncooked", "Appealing", "Larger than Life", "Drooping", "Unwell", "Atrocious", "Glossy", "Barrage", "Unlawful"] part2 = ["Defeated", "Hi-Fi", "Extraterrestrial", "Adumbration", "Limpid", "Looptid", "Cromulent", "Unsettled", "Soot", "Twinkle"] part3 = ["Brain", "Segment", "Audio", "Legitimate Business", "Mentality", "Sound", "Canticle", "Monsoon", "Preserves", "Hangout"] part4 = ["Cougar", "Lion", "Lynx", "Ocelot", "Puma", "Jaguar", "Panther"] part5 = ["Fodder", "Ersatz Goods", "Leftovers", "Infant Formula", "Mush", "Smoothie", "Milkshakes"] def main(argv): # Connect to the RazorDemo database. conn = pyodbc.connect("Driver={ODBC Driver 17 for SQL Server};Server=localhost\SQLEXPRESS;Database=RazorDemo;Trusted_Connection=yes;") # Generate 15 bad band names, and try to keep them unique. previousNames = "" nameCount = 0 while (nameCount < 16): rand1 = random.randrange(0, 9) rand2 = random.randrange(0, 9) rand3 = random.randrange(0, 9) badName = part1[rand1] + ' ' + part2[rand2] + ' ' + part3[rand3] # A crude but effective way of ensuring uniqueness, although there is no unique constraint on the artist name in the database. # This prepends and appends bars to both the list of previously used names and the current name. If the current name is # new, it will not be in that string. if ("|" + previousNames + "|").find("|" + badName + "|") == -1: print ("Band name [" + str(nameCount) + "] is [" + badName + "]") sql1 = "insert into artists (artist_name) values (?)" values1 = [badName] rs1 = conn.cursor() rs1.execute(sql1, values1) rs1.commit() # If the cursor is not closed, then other cursors cannot be executed. rs1.close() for y in range(1, 3): rand4 = random.randrange(0, len(part4)) rand5 = random.randrange(0, len(part5)) albumName = part4[rand4] + " " + part5[rand5] print ("\tAlbum [" + albumName + "]") sql2 = "insert into albums (artist_id, album_name) values ((select top 1 rcdid from artists where artist_name=?), ?)" # Each array item here corresponds to the position of the ? in the SQL statement above. values2 = [badName, albumName] rs2 = conn.cursor () rs2.execute(sql2, values2) rs2.commit() rs2.close() # Creates a bar-delimited list of previously used names. if previousNames == "": previousNames = badName else: previousNames = previousNames + "|" + badName nameCount = 1 + nameCount else: print ("Found a duplicate of [" + badName + "]") #print (previousNames) # Close the Connection conn.close() return 0 if __name__ == "__main__": main(sys.argv[1:]) Listing 3 - Inserting the data
K ověření výstupu kódu lze v SSMS spustit následující dotaz:
Obrázek 17 – Úspěšné vložení dat
VÝBĚR dat v SQL Express a Pythonu
Nyní, když jsou v databázi data, bylo by hezké se na ně dotazovat. Níže je jednoduchý skript, který přijímá uživatelská data z klávesnice a předává je do databáze pomocí parametrizovaného dotazu:
# bad-band-name-maker3.py import sys import pyodbc def main(argv): searchValue = input("Enter something: ") # Cap the length at something reasonable. The first 20 characters. searchValue = searchValue[0:20] # Set the search value to lower case so we can perform case-insensitive matching: searchValue = searchValue.lower() # Connect to the RazorDemo database. conn = pyodbc.connect("Driver={ODBC Driver 17 for SQL Server};Server=localhost\SQLEXPRESS;Database=RazorDemo;Trusted_Connection=yes;") # You must use a parameterized query here in order to protect from SQL Injection Attacks! # For the like operator, the percent signs must be separated from the term or else the parameterization will fail. sql1 = ("select a.artist_name, b.album_name from artists a, albums b where b.artist_id = a.rcdid and " + "lower(album_name) like ('%' + ? + '%') order by a.artist_name, b.album_name") # Below is an array with one element: values1 = [searchValue] rs1 = conn.cursor() rs1.execute(sql1, values1) rows1 = rs1.fetchone() #print ("Type is [" + str(type(rows1)) + "]") if str(type(rows1)).find("NoneType") == -1: while rows1: # Columns are indexed by number only. 0 is the a.artist_name column and 1 is the b.album_name columns print(rows1[0] + " - " + rows1[1]) rows1 = rs1.fetchone() else: print ("No album name matched [" + searchValue + "]") # Close the Connection conn.close() return 0 if __name__ == "__main__": main(sys.argv[1:]) Listing 4 - Querying the Data
Stejné výsledky. Jeden dokonce obsahuje příklad hrubého útoku SQL Injection:
Obrázek 18 – Výsledky dotazu. Poznamenejte si hodnotu posledního hledání.
Poslední myšlenky na vývoj databáze Python
Opravdu neexistuje žádné omezení toho, jaké aplikace řízené SQL Serverem lze vyvíjet pomocí Pythonu. Vývojář je omezen pouze znalostí SQL a doufejme, že základní koncepty uvedené v tomto článku mohou nasměrovat vývojáře na úrovni začátečníka správným směrem, pokud jde o rozšíření porozumění SQL a vytváření složitějších aplikací.
Tento výukový program programování databáze v Pythonu představil prostředky, kterými lze SQL Express nainstalovat jako vývojovou záskok pro SQL Server, a ukázal, jak lze rozšířit Python 3, aby správně komunikoval s instancí databáze SQL Express na tomto serveru. Tento článek také ukázal, jak by mělo být SQL Server Management Studio použito ke správě jakékoli databáze SQL Express nebo SQL Server. Tento článek se dále zabývá základními bezpečnostními opatřeními a používáním efektivního kódování pro účely zajištění přiměřených časů provádění aplikací řízených SQL Serverem.