Database
 sql >> Base de données >  >> RDS >> Database

Programmation de base de données Python avec SQL Express pour les débutants

Python a connu une croissance explosive en popularité au cours des 5 dernières années. De nombreux nouveaux programmeurs y sont attirés en raison de sa courbe d'apprentissage douce par rapport aux autres langages de programmation. Les programmeurs expérimentés y sont attirés en raison de son extensibilité et de sa puissance. Cependant, l'un des principaux moteurs de cette adoption massive est la facilité avec laquelle Python peut travailler avec des bases de données. Ce tutoriel de programmation Python explorera comment commencer à utiliser Python pour communiquer avec SQL Express en utilisant Python 3.

Programmation Python et base de données

Un débutant Python qui souhaite intégrer la fonctionnalité de base de données dans any projet logiciel écrit en tout la langue doit avoir une compréhension de base d'au moins deux langues. Le premier est, bien sûr, Python et le second est le langage de requête structuré spécifique (SQL) utilisé par la base de données. Bien que SQL soit standardisé, en pratique ce n'est pas un langage universel, mais les implémentations entre différentes bases de données sont suffisamment proches pour que le passage d'une base de données à une autre ne soit pas si difficile une fois que l'on a un niveau confortable d'expérience en développement d'applications de base de données. /P>

Une autre considération importante pour les bases de données est qu'elles nécessitent toutes un logiciel de gestion. Ces outils de gestion peuvent aider à configurer l'accès et les privilèges de sécurité au sein d'une base de données. Ils peuvent également être utilisés pour déboguer des applications de base de données car ils peuvent permettre à un développeur de faire des choses comme :

  • Création et gestion du contenu des tables, vues et autres objets de base de données. Cela inclut les relations entre les tables, ainsi que la configuration des règles d'intégrité.
  • Interaction avec la base de données directement via la saisie de code SQL.
  • Débogage de la syntaxe SQL.
  • Annulation (dans une certaine mesure) des dommages causés par des instructions SQL mal codées dans l'application.

Même si un développeur choisit d'utiliser une base de données basée sur noSQL telle que MongoDB, il sera toujours difficile d'apprendre la syntaxe de codage spécifique à la base de données nécessaire pour faire fonctionner une telle solution. Bien sûr, ce ne sont pas des éléments dissuasifs, ce ne sont que des facteurs techniques qui doivent être pris en compte dans tout projet de développement logiciel.

Pilotes Python et de base de données

Python, comme tout autre langage de programmation, ne peut pas communiquer nativement avec une base de données donnée. Il nécessite l'ajout de modules supplémentaires pour un serveur de base de données spécifique. Du point de vue des meilleures pratiques, il est préférable d'utiliser un module de pilote de base de données spécifique au serveur de base de données choisi pour le projet logiciel. Cela garantit que Python peut accéder à toutes les fonctionnalités du serveur de base de données, même si cela entraîne un coût supplémentaire lié à l'utilisation d'une syntaxe de programmation spécifique pour le module. Bien que certaines tentatives aient été faites pour créer des modules de pilote de base de données "universels" pouvant se connecter à plusieurs serveurs de base de données, cela se fait souvent au détriment de l'accès à certaines fonctionnalités d'un serveur de base de données particulier.

Qu'est-ce que SQL Express ?

SQL Server est la solution de serveur de base de données incontournable pour Windows depuis des décennies. Bien qu'il soit à peu près aussi éloigné d'une solution de serveur de base de données gratuite que possible, Microsoft fournit une variante allégée et gratuite de SQL Server appelée SQL Express. SQL Express est un outil d'apprentissage idéal pour les débutants car il prend en charge la même syntaxe SQL que celle utilisée par SQL Server. SQL Express et SQL Server utilisent tous deux une extension personnalisée de SQL appelée "Transact-SQL", également connue sous le nom de "T-SQL". SQL Express et SQL Server prennent en charge l'utilisation des comptes d'utilisateurs Windows et des systèmes traditionnels de nom d'utilisateur et de mot de passe pour la gestion des accès.

Python communique avec SQL Express ou SQL Server avec un module nommé PyODBC . SQL Server et SQL Express sont tous deux gérés par une application Windows distincte et gratuite appelée "SQL Server Management System", communément appelée "SSMS". Au moment d'écrire ces lignes, SQL Express et SSMS sont des téléchargements distincts de Microsoft :

  • Téléchargement SSMS
  • Téléchargement SQL Express

Comment configurer SQL Express pour le développement Python

SQL Express, comme SQL Server, prend en charge deux types d'authentification. La première est l'authentification basée sur le compte d'utilisateur Windows d'un utilisateur, également connu sous le nom de "Connexion sécurisée". La seconde est l'authentification traditionnelle basée sur le nom d'utilisateur et le mot de passe qui est implémentée dans ce qu'on appelle "l'authentification en mode mixte". L'authentification en mode mixte prend en charge à la fois l'authentification basée sur le compte d'utilisateur Windows et l'authentification basée sur le nom d'utilisateur et le mot de passe. Il n'existe aucun moyen de prendre en charge l'authentification basée sur le nom d'utilisateur et le mot de passe par elle-même dans SQL Server ou SQL Express.

Microsoft s'éloigne de l'authentification en mode mixte, car l'un des principaux avantages de l'utilisation des connexions approuvées est que les informations d'identification de la base de données n'ont pas besoin d'être stockées dans le code de l'application. La démonstration de cet article ne l'utilisera pas non plus.

NE PAS copier la chaîne de connexion après l'installation

Un point de discorde pour les développeurs d'applications de niveau débutant est la confusion initiale entourant les chaînes de connexion SQL Server. Si l'on installe SQL Express, le programme d'installation fournit la chaîne de connexion pour la post-installation de l'instance SQL Express créée. Malheureusement, la chaîne de connexion fournie ne fonctionnera probablement pas avec PyODBC . Bien qu'il soit tentant de se laisser "bercer" par un sentiment de sécurité avec ce "cadeau", cela causera plus de problèmes qu'il n'en vaut la peine.

Figure 1 – Obtention de la chaîne de connexion à partir du programme d'installation de SQL Express

Notez qu'au moment d'écrire ces lignes, le programme d'installation de SQL Express comprend également un lien pour télécharger le programme d'installation de SSMS.

Comment créer une base de données dans SQL Express

Une fois SQL Express et SSMS installés, il est temps de créer une base de données de base avec des restrictions d'accès appropriées. Le moyen le plus simple de démarrer SSMS est de cliquer sur Démarrer dans Windows, tapez "ssms" dans la barre de recherche, attendez que "Microsoft SQL Server Management Studio 18" apparaisse en haut à droite, puis cliquez sur Ouvrir lien dans la partie droite du panneau du menu Démarrer :

Figure 2 – Démarrage de SSMS

Au démarrage de SSMS, on est accueilli par la boîte de dialogue suivante :

Figure 3 – Boîte de dialogue d'ouverture de SSMS

Avec l'authentification Windows, il n'est pas nécessaire de saisir des informations d'identification. Le compte utilisateur Windows sous lequel SQL Express a été installé dispose de privilèges administratifs pour l'instance SQL Express. Cliquez simplement sur Se connecter pour continuer.

À l'extrême gauche de la fenêtre d'application SSMS , il y aura l'Explorateur d'objets . Pour créer une nouvelle base de données, faites un clic droit sur Bases de données et sélectionnez Créer une base de données du contexte menus :

Figure 4 – Création d'une nouvelle base de données – Partie 1 sur 2

En cliquant sur Nouvelle base de données… ouvrira une nouvelle fenêtre de dialogue permettant de saisir les détails de la nouvelle base de données. Pour cette démonstration, la base de données s'appellera RazorDemo , en guise de rappel d'un article précédent sur le développement d'applications basées sur Razor en C#. Entrez le nom de la base de données dans la zone de texte à côté de Nom de la base de données puis cliquez sur OK bouton en bas de la fenêtre de dialogue. Notez que, dans l'illustration ci-dessous, les colonnes du Nom logique des fichiers ont été légèrement élargis afin que les noms logiques complets des fichiers de base de données en cours de création ont été exposés :

Figure 5 – Création d'une nouvelle base de données – Partie 2 sur 2

La nouvelle base de données apparaîtra alors dans l'Explorateur d'objets sous les Bases de données dossier :

Figure 6 – La nouvelle base de données « RazorDemo »

Comment créer des tables dans SQL Express

Une base de données relationnelle n'est pas vraiment utile sans tables pour stocker les données, et la façon la plus simple de créer ces tables est d'utiliser du code SQL. Remarque, bien que l'on puisse utiliser l'assistant de création de table pour créer une table, l'utilisation du code SQL est plus rapide, plus facile et beaucoup plus simple. Commencez par faire un clic droit sur RazorDemo entrée de la base de données, puis cliquez avec le bouton gauche sur Nouvelle requête option dans la fenêtre contextuelle :

Figure 7 – Ouverture d'une nouvelle fenêtre de requête

Une fenêtre d'éditeur de requête similaire à celle ci-dessous apparaîtra à droite de l'Explorateur d'objets :

Figure 8 – La fenêtre de l'éditeur de requête

Le code de création de table est affiché dans la liste ci-dessous :

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

Remarque, lors de la création d'une fenêtre d'éditeur de requête de la base de données garantit généralement que la base de données sélectionnée sera celle sur laquelle le code est exécuté, c'est une bonne idée de toujours explicitement utiliser la base de données prévue au début du code. L'utilisation La commande sélectionne explicitement le nom de la base de données qui la suit.

En appuyant sur F5 ou en cliquant sur Exécuter le bouton exécutera les déclarations contre le RazorDemo base de données. Si l'exécution réussit, un message l'indiquant apparaîtra dans les "Messages encadré ci-dessous :

Figure 9 – Création de table réussie

Les tables nouvellement créées et leurs colonnes peuvent être vues dans l'Explorateur d'objets aussi bien. Notez que parfois l'option Actualiser L'option du menu contextuel qui apparaît lors d'un clic droit sur la base de données peut devoir être sélectionnée afin d'afficher de nouveaux objets dans une base de données :

Figure 10 – Actualisation de l'explorateur d'objets


Figure 11 – Les nouvelles tables et leurs colonnes

À ce stade, SSMS peut être fermé en toute sécurité.

Notez que SSMS fonctionne de la même manière avec n'importe quelle base de données SQL Server. Il est toujours recommandé d'enregistrer tout le code de création de table, quel que soit le serveur de base de données utilisé. Même si SQL Server et SQL permettent la récupération de tels scripts, ils permettent également l'utilisation du chiffrement sur ces instructions, et dans ces cas, le code ne peut pas être récupéré.

Python et SQL Express

Normalement, une discussion sur la sécurité de SQL Server serait nécessaire ici, mais depuis Trusted Connections sera utilisé, tant que le processus en cours d'exécution exécutant le code Python appartient à un utilisateur Windows qui a déjà accès à une base de données en cours d'accès, cette discussion ne sera pas nécessaire. Gardez à l'esprit que SQL Server et SQL Express offrent des personnalisations très robustes liées à la sécurité, mais celles-ci dépassent le cadre d'un article destiné aux débutants.

Notez qu'il ne faut pas négliger la sécurité de la base de données pour toute application exécutée dans un environnement de production ! Assurez-vous que seuls les privilèges les plus faibles possibles sont accordés au compte d'utilisateur qui accéderait à une base de données dans un environnement de projection.

La version de Python utilisée pour ces exemples de code est la 3.10 et elle a été installée via le Microsoft Store sous Windows. L'installation de Python avec cette méthode ajoutera les exécutables Python et PIP3 au chemin système, de sorte que les chemins complets vers ces commandes n'auront pas besoin d'être saisis dans l'invite de commande les fenêtres. Pour la saisie de code, un bon éditeur de texte sans frais est Notepad++.

Ouverture des fenêtres d'invite de commande

L'exécution du code Python se fait mieux via l'invite de commande . Pour accéder à l'invite de commande , cliquez sur Démarrer bouton dans Windows et entrez cmd dans la barre de recherche. Attendez Invite de commandes pour apparaître, puis cliquez sur Ouvrir lien sur le côté droit du menu Démarrer :

Figure 12 – Ouvrir une invite de commande

Une invite de commande typique la fenêtre ressemble à ceci :

Figure 13 – Une invite de commande typique

Comment installer PyODBC

PyODBC est le module Python qui permet à Python d'accéder à la fois à SQL Server et à SQL Express. Lors de l'installation de Python via le Microsoft Store, PyODBC peut être ajouté à Python via la commande :

pip3 install pyodbc

Figure 14 – Installation réussie de PyODBC

Notez que si plusieurs versions de Python sont installées, par exemple Python 2 et Python 3, il peut être nécessaire de préfixer le pip3 command avec le chemin Windows complet vers command pour la version appropriée de Python.

Notez également que si seul Python 3 est installé, le pip3 La commande doit toujours être utilisée sur le pip plus générique commande, car il s'agit de la convention appropriée.

Écrire du code Python

Maintenant que la base de données est configurée et PyODBC sont installés, la base de données peut être remplie. Dans le cas d'une base de données qui répertorie les artistes et les albums, quelques noms de groupes et albums générés aléatoirement suffiront. Le code Python pour se connecter à la base de données est également inclus, mais les inserts ne le sont pas (encore) :

# 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

Cela donne la sortie suivante :

Figure 15 – Noms de bande générés aléatoirement

Notez l'utilisation du cd commande pour passer au répertoire où le code Python est enregistré. Le PyODBC connect() échouera si le compte d'utilisateur Windows actuellement connecté n'est pas répertorié comme ayant accès dans SQL Express. Ce n'est un problème que si la base de données est créée avec un compte utilisateur Windows mais le code est exécuté sous un autre compte utilisateur Windows .

Le moins pire moyen d'INSÉRER des données dans SQL et PyODBC

De nombreux développeurs Python débutants sont tentés de passer des appels à PyODBC appels à INSERT déclarations dans les sections suivantes du code, et dans le contexte de ce qui sera dit ensuite, ce n'est pas une mauvaise idée :

Figure 16 – La "presque" mauvaise façon de travailler avec une base de données

La raison pour laquelle utiliser des appels à PyODBC pour effectuer des INSERT , SELECT , et d'autres fonctions liées à la base de données, telles que UPDATE ou SUPPRIMER , dans les boucles peut être mauvais parce qu'il y a une surcharge qui vient avec chacun de ces appels. Dans une boucle qui pourrait potentiellement itérer des centaines de fois, des milliers de fois, voire plus, cela peut entraîner un temps considérable (minutes ou plus) pour exécuter un script. Pour les applications Web qui utilisent une telle approche, les problèmes de performances s'aggravent, car de nombreux serveurs Web imposent des limites strictes à la durée d'exécution d'un script. Ne transmettez en aucun cas les entrées créées par l'utilisateur directement à une base de données. Vérifiez toujours l'entrée pour vous assurer qu'elle ne cassera pas la fonctionnalité de la base de données ou ne causera pas de problème de sécurité par le biais d'une attaque par injection SQL.

Idéalement, on voudrait utiliser les boucles ci-dessus pour créer un SQL Batch (une liste d'instructions) et ensuite avoir PyODBC exécuter sur ce seul lot, mais ce serait une très mauvaise idée si les données ne sont pas nettoyées.

Pourquoi les données devraient-elles être désinfectées ? La raison se résume à la sécurité, car les entrées de l'utilisateur ne sont jamais fiables. Nettoyer les données signifie les représenter d'une manière qui empêche toute exécution autre que l'instruction SQL créée par le développeur du programme. Un utilisateur pourrait transmettre une chaîne construite de manière malveillante qui permettrait l'exécution de code SQL créé arbitrairement. C'est ce qu'on appelle une attaque par injection SQL. Bien que les valeurs de données entrant dans un lot puissent être nettoyées, le processus pour le faire dépasse le cadre d'un didacticiel d'introduction.

PyODBC fournit un mécanisme de protection de la base de données contre les attaques par injection SQL en nettoyant les entrées utilisateur. Celles-ci impliquent l'utilisation d'instructions paramétrées , également appelés déclarations préparées . La sécurité doit toujours être une priorité, même si elle se fait au détriment de la vitesse ou d'autres mesures de performance.

Le compte d'utilisateur Windows qui a accès à cette base de données dispose par défaut des privilèges sysadmin. Cela signifie qu'en cas d'attaque par injection SQL, un utilisateur malveillant peut accéder à toutes les données de chaque base de données sur le serveur. En pratique, aucun compte avec des privilèges d'administrateur système ne devrait accéder à une base de données à partir de code Python.

La liste ci-dessous complète le premier exemple de code Python en utilisant PyODBC curseurs pour insérer les données :

# 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

La requête suivante peut être exécutée dans SSMS pour vérifier la sortie du code :

Figure 17 – Insertion réussie des données

SÉLECTIONNER des données dans SQL Express et Python

Maintenant qu'il y a des données dans la base de données, ce serait bien de les interroger. Vous trouverez ci-dessous un script simple qui accepte les données utilisateur du clavier et les transmet à la base de données via une requête paramétrée :

# 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

Mêmes résultats. L'un d'entre eux inclut même un exemple d'attaque brute par injection SQL :

Figure 18 – Résultats de la requête. Notez la dernière valeur de recherche.

Réflexions finales sur le développement de bases de données Python

Il n'y a vraiment aucune limite aux applications pilotées par SQL Server qui peuvent être développées à l'aide de Python. Un développeur n'est limité que par sa connaissance de SQL, et nous espérons que les concepts fondamentaux présentés dans cet article pourront orienter un développeur débutant dans la bonne direction en termes d'élargissement de sa compréhension de SQL et de création d'applications plus complexes.

Ce didacticiel de programmation de base de données Python a présenté les moyens par lesquels SQL Express pourrait être installé en tant que remplaçant de développement pour SQL Server, et a montré comment Python 3 peut être étendu afin de communiquer correctement avec une instance de base de données SQL Express sur ce serveur. Cet article a également montré comment SQL Server Management Studio doit être utilisé pour gérer toutes les bases de données SQL Express ou SQL Server. Pour aller plus loin, cet article a également abordé les précautions de sécurité de base et l'utilisation d'un codage efficace dans le but de garantir des temps d'exécution raisonnables pour les applications pilotées par SQL Server.