sql >> Database teknologi >  >> RDS >> Database

Python-databaseprogrammering med SQL Express for begyndere

Python er vokset eksplosivt i popularitet i de sidste 5 år. Mange nye programmører er tiltrukket af det på grund af dets blide indlæringskurve i forhold til andre programmeringssprog. Erfarne programmører er tiltrukket af det på grund af dets udvidelsesmuligheder og kraft. Imidlertid er en af ​​de vigtigste drivkræfter for denne masseadoption, hvor let Python kan arbejde med databaser. Denne Python-programmeringsvejledning vil undersøge, hvordan du kommer i gang med at bruge Python til at kommunikere med SQL Express ved hjælp af Python 3.

Python- og databaseprogrammering

En Python-begynder, der ønsker at integrere databasefunktionalitet i enhver softwareprojekt skrevet i enhver sprog skal have en grundlæggende forståelse af mindst to Sprog. Den første er selvfølgelig Python, og den anden er det specifikke strukturerede forespørgselssprog (SQL), der bruges af databasen. Selvom SQL er standardiseret, er det i praksis ikke et universelt sprog, men implementeringerne mellem forskellige databaser er tæt nok på, at det ikke er så stor en udfordring at flytte fra en database til en anden, når først man har et behageligt niveau af erfaring med udvikling af databaseapplikationer.

En anden vigtig overvejelse for databaser er, at de alle kræver administrationssoftware. Disse administrationsværktøjer kan hjælpe med at konfigurere adgang til og sikkerhedsrettigheder i en database. De kan også bruges til at fejlsøge databaseapplikationer, da de kan gøre det muligt for en udvikler at gøre ting som:

  • Oprettelse og styring af indholdet af tabeller, visninger og andre databaseobjekter. Dette inkluderer relationerne mellem tabeller såvel som konfigurationen af ​​integritetsregler.
  • Interaktion med databasen direkte via SQL-kodeindtastning.
  • Fejlretning af SQL-syntaks.
  • Fortrydelse (i et omfang) af skade forårsaget af forkert kodede SQL-sætninger i applikationen.

Selvom en udvikler vælger at bruge en noSQL-baseret database som MongoDB, vil der stadig være udfordringer med at lære den databasespecifikke kodningssyntaks, der skal til for at få en sådan løsning til at fungere. Selvfølgelig er disse ikke afskrækkende midler, de er blot tekniske faktorer, der skal tages i betragtning ved ethvert softwareudviklingsprojekt.

Python- og databasedrivere

Python kan, som ethvert andet programmeringssprog, ikke kommunikere med en given database. Det kræver, at der tilføjes ekstra moduler til en specifik databaseserver. Fra et bedste praksis synspunkt er det bedst at bruge et databasedrivermodul, der er specifikt for den databaseserver, der er valgt til softwareprojektet. Dette sikrer, at Python kan få adgang til alle funktionerne på databaseserveren, selvom det koster ekstra at bruge en specifik programmeringssyntaks for modulet. Mens der er blevet gjort nogle forsøg på at skabe "universelle" databasedrivermoduler, der kan oprette forbindelse til flere databaseservere, kommer disse ofte på bekostning af at miste adgangen til visse funktioner i en bestemt databaseserver.

Hvad er SQL Express?

SQL Server har været den foretrukne databaseserverløsning til Windows i årtier. Selvom det er omtrent så langt fra en gratis databaseserverløsning, som man kan komme, leverer Microsoft en nul-omkostningsfri variant af SQL Server kaldet SQL Express. SQL Express er et ideelt læringsværktøj for begyndere, da det understøtter den samme SQL-syntaks, som SQL Server bruger. Både SQL Express og SQL Server bruger en brugerdefineret udvidelse af SQL kaldet "Transact-SQL", også kendt som "T-SQL." Både SQL Express og SQL Server understøtter brugen af ​​Windows-brugerkonti og traditionelle brugernavne- og adgangskodesystemer til adgangsstyring.

Python kommunikerer med SQL Express eller SQL Server med et modul ved navn PyODBC . Både SQL Server og SQL Express administreres af en separat, gratis Windows-applikation kaldet "SQL Server Management System", populært kendt som "SSMS". I skrivende stund er både SQL Express og SSMS separate downloads fra Microsoft:

  • SSMS-download
  • SQL Express-download

Sådan konfigurerer du SQL Express til Python-udvikling

SQL Express, ligesom SQL Server, understøtter to slags godkendelse. Den første er godkendelse baseret på en brugers Windows-brugerkonto, også kendt som en "Trusted Connection". Det andet er traditionelt brugernavn, og adgangskodebaseret godkendelse er implementeret i det, der kaldes "Mixed Mode Authentication." Blandet tilstandsgodkendelse understøtter både Windows-brugerkontobaseret godkendelse og brugernavn- og adgangskodebaseret godkendelse. Der er ingen måde at understøtte brugernavn og adgangskodebaseret godkendelse i sig selv i SQL Server eller SQL Express.

Microsoft har bevæget sig væk fra Mixed Mode Authentication, da en af ​​de største fordele ved at bruge Trusted Connections er, at databaselegitimationsoplysninger ikke behøver at blive gemt i applikationskoden. Demonstrationen i denne artikel vil heller ikke bruge den.

Ikke kopiering af forbindelsesstrengen efter installation

Et stridspunkt for applikationsudviklere på begynderniveau er den indledende forvirring omkring SQL Server-forbindelsesstrenge. Hvis man installerer SQL Express, leverer installationsprogrammet forbindelsesstrengen for den oprettede SQL Express-instans efter installationen. Desværre vil den medfølgende forbindelsesstreng sandsynligvis ikke fungere med PyODBC . Selvom det er fristende at blive "lullet" ind i en følelse af sikkerhed med denne "gratis", vil det skabe flere problemer, end det er værd.

Figur 1 – Hentning af forbindelsesstrengen fra SQL Express Installer

Bemærk, at i skrivende stund indeholder installationsprogrammet til SQL Express også et link til download af SSMS-installationsprogrammet.

Sådan opretter du en database i SQL Express

Når både SQL Express og SSMS er installeret, er det tid til at oprette en grundlæggende database med passende adgangsbegrænsninger. Den nemmeste måde at starte SSMS på er at klikke på Start knappen i Windows, indtast "ssms" i søgefeltet, vent på, at "Microsoft SQL Server Management Studio 18" vises øverst til højre, og klik derefter på Åbn link i højre side af menupanelet Start:

Figur 2 – Start af SSMS

Når man starter SSMS, bliver man mødt af følgende dialogboks:

Figur 3 – SSMS-åbningsdialog

Med Windows-godkendelse er der ingen grund til at indtaste legitimationsoplysninger. Windows-brugerkontoen hvorunder SQL Express blev installeret, har administrative rettigheder til SQL Express-forekomsten. Du skal blot klikke på Opret forbindelse for at fortsætte.

Længst til venstre i SSMS Application Window , vil der være Object Explorer . For at oprette en ny database skal du højreklikke på Databaser og vælg Opret database fra Konteksten menu:

Figur 4 – Oprettelse af en ny database – del 1 af 2

Klik på Ny database... vil åbne et nyt dialogvindue, der gør det muligt at indtaste oplysningerne om den nye database. Til denne demonstration vil databasen blive kaldt RazorDemo , som lidt af et tilbagevenden til en tidligere artikel om udvikling af Razor-baserede applikationer i C#. Indtast navnet på databasen i tekstboksen ud for Databasenavn og klik derefter på OK knappen nederst i dialogvinduet. Bemærk, at i illustrationen nedenfor er kolonnerne for Logical Name af filerne blev udvidet en smule, så de fulde Logiske navne af databasefilerne, der oprettes, blev afsløret:

Figur 5 – Oprettelse af en ny database – Del 2 af 2

Den nye database vises derefter i Object Explorer under Databaser mappe:

Figur 6 – Den nyoprettede "RazorDemo"-database

Sådan opretter du tabeller i SQL Express

En relationel database er ikke rigtig nyttig uden tabeller til at gemme dataene, og den mest ligetil måde at oprette disse tabeller på er at bruge SQL-kode. Bemærk, mens man kunne bruge Table Creation Wizard at oprette en tabel er det hurtigere, nemmere og langt mere ligetil at bruge SQL-kode. Start med at højreklikke på RazorDemo databaseindtastning, og venstreklik derefter på Ny forespørgsel mulighed i kontekstvinduet:

Figur 7 – Åbning af et nyt forespørgselsvindue

Et forespørgselsredigeringsvindue, der ligner det nedenfor, vises til højre for Object Explorer :

Figur 8 – Forespørgselsredigeringsvinduet

Koden til tabeloprettelse er vist i listen nedenfor:

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

Bemærk, mens du opretter et Forespørgselsredigeringsvindue fra databasen garanterer normalt, at den valgte database vil være den, som koden udføres mod, er det en god ide altid eksplicit at bruge den tilsigtede database i starten af ​​koden. brug kommandoen vælger eksplicit navnet på den database, der følger efter den.

Tryk på F5 eller ved at klikke på Udfør knappen vil udføre sætningerne mod RazorDemo database. Hvis udførelsen lykkes, vil en meddelelse, der angiver det, blive vist i "Meddelelser boksen nedenfor:

Figur 9 – Vellykket tabeloprettelse

De nyoprettede tabeller og deres kolonner kan ses i Object Explorer såvel. Bemærk, at nogle gange Opdater mulighed fra kontekstmenuen, der vises ved højreklik på databasen, skal muligvis vælges for at vise nye objekter i en database:

Figur 10 – Opdatering af objektudforskeren


Figur 11 – De nye tabeller og deres kolonner

På dette tidspunkt kan SSMS lukkes sikkert.

Bemærk, at SSMS fungerer på samme måde med enhver SQL Server-database også. Det er altid en god praksis at gemme al tabeloprettelseskode, uanset hvilken databaseserver der bruges. Selvom SQL Server og SQL tillader gendannelse af sådanne scripts, tillader de begge også brugen af ​​kryptering på sådanne sætninger, og i disse tilfælde kan koden ikke gendannes.

Python og SQL Express

Normalt ville en diskussion om SQL Server-sikkerhed være nødvendig her, men siden Trusted Connections vil blive brugt, så længe den kørende proces, der udfører Python-koden, ejes af en Windows-bruger som allerede har adgang til en database, der tilgås, vil den diskussion ikke være nødvendig. Husk, at både SQL Server og SQL Express tilbyder meget robuste sikkerhedsrelaterede tilpasninger, men de er uden for rammerne af en artikel beregnet til begyndere.

Bemærk, udvis ikke korrekt databasesikkerhed for enhver applikation, der kører i et produktionsmiljø! Sørg for, at kun de mindst mulige privilegier gives til den brugerkonto, der ville få adgang til en database i et projektionsmiljø.

Den version af Python, der bruges til disse kodeeksempler, er 3.10, og den blev installeret via Microsoft Store i Windows. Installation af Python med denne metode vil tilføje Python og PIP3 eksekverbare filer til systemstien, så de fulde stier til disse kommandoer ikke skal indtastes i Kommandoprompten vinduer. Til kodeindtastning er en god, gratis teksteditor Notepad++.

Åbning af kommandoprompt Windows

Udførelse af Python-kode udføres bedst via Kommandoprompten . For at få adgang til Kommandoprompt , klik på Start knappen i Windows, og indtast cmd ind i søgefeltet. Vent på Kommandoprompt for at blive vist, og klik derefter på Åbn linket i højre side af Startmenuen :

Figur 12 – Åbning af en kommandoprompt

En typisk kommandoprompt vinduet ser sådan ud:

Figur 13 – En typisk kommandoprompt

Sådan installeres PyODBC

PyODBC er Python-modulet, som gør det muligt for Python at få adgang til både SQL Server og SQL Express. Efter installation af Python via Microsoft Store, PyODBC kan tilføjes til Python via kommandoen:

pip3 install pyodbc

Figur 14 – Vellykket installation af PyODBC

Bemærk, hvis der er flere versioner af Python installeret, for eksempel både Python 2 og Python 3, så kan det være nødvendigt at præfikse pip3 kommando med den fulde WIndows-sti til kommando for den relevante version af Python.

Bemærk også, at hvis kun Python 3 er installeret, er pip3 kommandoen skal stadig bruges over den mere generiske pip kommando, da dette er den rigtige konvention.

Skrivning af Python-kode

Nu hvor databasen er konfigureret og PyODBC er installeret, kan databasen udfyldes. I tilfælde af en database, der katalogiserer kunstnere og album, vil nogle tilfældigt genererede bandnavne og album være tilstrækkelige. Python-koden til at oprette forbindelse til databasen er også inkluderet, men indsættelserne er ikke (endnu):

# 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

Dette giver følgende output:

Figur 15 – Tilfældigt genererede båndnavne

Bemærk brugen af ​​cd'en kommando for at skifte til den mappe, hvor Python-koden er gemt. PyODBC connect() funktionen mislykkes, hvis den aktuelt loggede Windows-brugerkonto er ikke angivet som havende adgang i SQL Express. Dette er kun et problem, hvis databasen er oprettet med én Windows-brugerkonto men koden køres under en anden Windows-brugerkonto .

Den mindst værste måde at INDSÆTTE data på i SQL og PyODBC

Mange begyndere Python-udviklere er fristet til at foretage opkald til PyODBC opkald til INSERT udsagn i de følgende sektioner af koden, og i sammenhæng med, hvad der vil blive sagt herefter, er dette ikke en dårlig idé:

Figur 16 – Den "næsten" forkerte måde at arbejde med en database på

Grunden til at bruge opkald til PyODBC for at udføre INSERT , VÆLG , og andre databaserelaterede funktioner, såsom OPDATERING eller SLET , inden for loops kan være dårligt, fordi der er overhead, der følger med hvert af disse opkald. Inden for en loop, der potentielt kan gentage hundredvis af gange, tusindvis af gange eller endda mere, kan dette resultere i en betydelig mængde tid (minutter eller mere) til at køre gennem et script. For webapplikationer, der anvender en sådan tilgang, forværres ydeevneproblemerne yderligere, da mange webservere pålægger hårde grænser for, hvor lang tid et script kan køre. Send aldrig under nogen omstændigheder brugerskabte input direkte til en database. Kontroller altid inputtet for at sikre, at det ikke ødelægger databasens funktionalitet eller forårsager et sikkerhedsproblem ved hjælp af et SQL Injection-angreb.

Ideelt set ville man ønske at bruge sløjferne ovenfor til at oprette en SQL-batch (en liste over sætninger) og derefter have PyODBC køre på den enkelte batch, men dette ville være en meget dårlig idé, hvis dataene ikke renses.

Hvorfor skal data renses? Årsagen koger ned til sikkerhed, da brugerinput aldrig kan stole på. At rense dataene betyder at repræsentere dem på en måde, der forhindrer andet end den SQL-sætning, der er oprettet af udvikleren af ​​programmet, i at blive eksekveret. En bruger kunne videregive en ondsindet konstrueret streng, der ville muliggøre udførelse af vilkårligt oprettet SQL-kode. Dette er kendt som et SQL Injection-angreb. Mens dataværdier, der indgår i en batch, kan renses, er processen for at gøre det uden for rammerne af et indledende selvstudie.

PyODBC giver en mekanisme til at beskytte databasen mod SQL Injection-angreb ved at rense brugerinput. Disse involverer brugen af ​​parametriserede udsagn , også kaldet forberedte erklæringer . Sikkerhed skal altid være en prioritet, selvom det kommer på bekostning af hastighed eller andre præstationsmålinger.

Den Windows-brugerkonto, der har adgang til denne database, har som standard sysadmin-rettigheder. Det betyder, at hvis der skulle opstå et SQL Injection-angreb, kan en ondsindet bruger få adgang til alle data i hver database på serveren. I praksis bør ingen konto med sysadmin-rettigheder have adgang til nogen database fra Python-kode.

Listen nedenfor udvider det første Python-kodeeksempel ved at bruge PyODBC markører for at indsætte data:

# 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

Følgende forespørgsel kan køres i SSMS for at bekræfte outputtet af koden:

Figur 17 – Den vellykkede indsættelse af dataene

Vælg data i SQL Express og Python

Nu hvor der er data i databasen, ville det være rart at forespørge på det. Nedenfor er et simpelt script, der accepterer brugerdata fra tastaturet og sender det ind i databasen via parametriseret forespørgsel:

# 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

Samme resultater. Man inkluderer endda et eksempel på et råt SQL Injection-angreb:

Figur 18 – Forespørgselsresultater. Bemærk den sidste søgeværdi.

Sidste tanker om Python-databaseudvikling

Der er virkelig ingen grænser for, hvilke SQL Server-drevne applikationer, der kan udvikles ved hjælp af Python. En udvikler er kun begrænset af viden om SQL, og forhåbentlig kan de grundlæggende koncepter, der præsenteres i denne artikel, pege en udvikler på begynderniveau i den rigtige retning med hensyn til at udvide ens forståelse af SQL og bygge mere komplekse applikationer.

Denne Python-databaseprogrammeringsvejledning præsenterede midler, hvormed SQL Express kunne installeres som en udviklings-stand-in for SQL Server, og viste, hvordan Python 3 kan udvides for korrekt at kommunikere med en SQL Express-databaseinstans på den server. Denne artikel viste også, hvordan SQL Server Management Studio skal bruges til at administrere alle SQL Express- eller SQL Server-databaser. I forlængelse heraf berørte denne artikel også grundlæggende sikkerhedsforanstaltninger og brugen af ​​effektiv kodning med det formål at sikre rimelige eksekveringstider for SQL Server-drevne applikationer.


  1. betinget unik begrænsning

  2. Valgfrit argument i PL/pgSQL-funktionen

  3. PL/SQL-program til at slette posterne fra tabellen

  4. URL-strengformat til at oprette forbindelse til Oracle-database med JDBC