Skip to content

9. Uso do SGBD MySQL

9.1. Instalação do módulo MySQLdb

Vamos escrever scripts utilizando um banco de dados MySQL:

As funções Python para gerenciamento de um banco de dados MySQL estão encapsuladas em um módulo MySQLdb que não está incluído na distribuição inicial do Python. Portanto, é necessário baixar e instalar o módulo. Veja aqui um passo a passo:

  • no menu de programas, selecione o gerenciador de pacotes do Python, [1]. A janela de comandos [2] será exibida.

Procure a palavra-chave mysql nos pacotes:


C:\Documents and Settings\st>pypm search mysql
Get: [pypm-be.activestate.com] :repository-index:
Get: [pypm-free.activestate.com] :repository-index:
autosync: synced 2 repositories
  chartio                    Setup wizard and connection client for connecting
  chartio-setup              Setup wizard and connection client for connecting
  cns.recipe.zmysqlda        Recipe for installing ZMySQLDA
  collective.recipe.zmysqlda Recipe for installing ZMySQLDA
  django-mysql-manager       DESCRIPTION_DESCRIPTION_DESCRIPTION
  jaraco.mysql               MySQLDB-compatible MySQL wrapper by Jason R. Coomb
  lovely.testlayers          mysql, postgres nginx, memcached cassandra test la
  mtstat-mysql               MySQL Plugins for mtstat
  mysql-autodoc              Generate HTML documentation from a mysql database
  mysql-python               Python interface to MySQL
  mysqldbda                  MySQL Database adapter
  products.zmysqlda          MySQL Zope2 adapter.
  pymysql                    Pure Python MySQL Driver
  pymysql-sa                 PyMySQL dialect for SQLAlchemy.
  pymysql3                   Pure Python MySQL Driver
  sa-mysql-dt                Alternative implementation of DateTime column for
  schemaobject               Iterate over a MySQL database schema as a Python o
  schemasync                 A MySQL Schema Synchronization Utility
  simplestore                A datastore layer built on top of MySQL in Python.
  sqlbean                    A auto maping ORM for MYSQL and can bind with memc
  sqlwitch                   sqlwitch offers idiomatic SQL generation on top of
  tiddlywebplugins.mysql     MySQL-based store for tiddlyweb
  tiddlywebplugins.mysql2    MySQL-based store for tiddlyweb
zest.recipe.mysql          A Buildout recipe to setup a MySQL database.

Foram listados todos os módulos cujo nome ou descrição contém a palavra-chave mysql. O que nos interessa é o [mysql-python], na linha 14. Vamos instalá-lo:


C:\Documents and Settings\st>pypm install mysql-python
The following packages will be installed into "%APPDATA%\Python" (2.7):
 mysql-python-1.2.3
Hit: [pypm-free.activestate.com] mysql-python 1.2.3
Installing mysql-python-1.2.3

C:\Documents and Settings\st>echo %APPDATA%
C:\Documents and Settings\st\Application Data
  • linha 5: o pacote mysql-python-1.2.3 foi instalado na pasta "%APPDATA%\Python", onde APPDATA é a pasta indicada na linha 8.

Essa operação pode falhar se:

  • o interpretador Python utilizado for uma versão de 64 bits;
  • o caminho %APPDATA% contiver caracteres acentuados.

9.2. Instalação do MySQL

Existem várias maneiras de instalar o SGBD MySQL. Aqui, utilizamos o WampServer, um pacote que reúne vários softwares:

  • um servidor web Apache. Vamos usá-lo para escrever scripts web em Python;
  • o SGBD MySQL;
  • a linguagem de script PHP;
  • uma ferramenta de administração do SGBD MySQL escrita em PHP: phpMyAdmin.

O WampServer pode ser baixado (junho de 2011) no seguinte endereço:

http://www.wampserver.com/download.php
  • no [1], baixe a versão correta do WampServer;
  • no [2], após a instalação, execute-o. Isso iniciará o servidor web Apache e o SGBD MySQL;
  • no [3], após ser iniciado, o WampServer pode ser administrado a partir de um ícone [3] localizado no canto inferior direito da barra de tarefas;
  • no [4], inicia-se a ferramenta de administração do MySQL.

Cria-se um banco de dados [dbpersonnes]:

Image

Cria-se um usuário [admpersonnes] com a senha [nobody]:

  • em [1], o nome do usuário;
  • em [2], a máquina de SGBD na qual lhe são concedidos direitos;
  • em [3], sua senha [nobody];
  • em [4], o mesmo;
  • em [5], não se concede nenhum direito a esse usuário;
  • em [6], ele é criado.
  • em [7], retorna-se à página inicial de phpMyAdmin;
  • em [8], utiliza-se o link [Privileges] desta página para ir alterar os do usuário [admpersonnes] e [9].
  • em [10], indica-se que se deseja conceder ao usuário [admpersonnes] direitos sobre o banco de dados [dbpersonnes];
  • em [11], confirma-se a escolha.
  • com o link [12] [Tout cocher], concedem-se ao usuário [admpersonnes] todos os direitos sobre o banco de dados [dbpersonnes] [13];
  • confirmamos em [14].

Agora temos:

  • um banco de dados MySQL e [dbpersonnes];
  • um usuário [admpersonnes / nobody] que possui todos os direitos sobre esse banco de dados.

Vamos escrever scripts em Python para explorar o banco de dados.

9.3. Conexão com um banco de dados MySQL - 1


Programa (mysqldb_01)


# importação do módulo MySQLdb
import sys
sys.path.append("D:\Programs\ActivePython\site-packages")
import MySQLdb

# conexão a um banco de dados MySQL
....

Notas:

  • linhas 2-4: os scripts que contêm operações com os arquivos SGBD e MySQL devem importar o módulo MySQLdb. Lembramos que instalamos esse módulo na pasta [%APPDATA%\Python]. A pasta [%APPDATA%\Python] é automaticamente pesquisada quando um código Python solicita um módulo. Na verdade, todas as pastas declaradas no sys.path são pesquisadas. Aqui está um exemplo que exibe essas pastas:

# -*- coding=utf-8 -*-

import sys

# exibição das pastas de sys.path
for dossier in sys.path:
    print dossier

A exibição na tela é a seguinte:

D:\data\istia-1112\python\tutoriel
C:\Windows\system32\python27.zip
D:\Programs\ActivePython\Python2.7.2\DLLs
D:\Programs\ActivePython\Python2.7.2\lib
D:\Programs\ActivePython\Python2.7.2\lib\plat-win
D:\Programs\ActivePython\Python2.7.2\lib\lib-tk
D:\Programs\ActivePython\Python2.7.2
C:\Users\Serge TahÚ\AppData\Roaming\Python\Python27\site-packages
D:\Programs\ActivePython\Python2.7.2\lib\site-packages
D:\Programs\ActivePython\Python2.7.2\lib\site-packages\win32
D:\Programs\ActivePython\Python2.7.2\lib\site-packages\win32\lib
D:\Programs\ActivePython\Python2.7.2\lib\site-packages\Pythonwin
D:\Programs\ActivePython\Python2.7.2\lib\site-packages\setuptools-0.6c11-py2.7.egg-info

Linha 8: a pasta [site-packages], onde o MySQLdb havia sido instalado inicialmente. Movemos a pasta [site-packages], que é a pasta na qual o utilitário pypm instala os módulos do Python. Para adicionar uma nova pasta que o Python irá explorar em busca de módulos, adicionamos-a à lista sys.path:


# importação do módulo MySQLdb
import sys
sys.path.append("D:\Programs\ActivePython\site-packages")
import MySQLdb

# conexão a um banco de dados MySQL
....

Na linha 3, adiciona-se a pasta para a qual o módulo MySQLdb foi movido.

O código completo do exemplo é o seguinte:


# importação do módulo MySQLdb
import sys
sys.path.append("D:\Programs\ActivePython\site-packages")
import MySQLdb

# conexão a um banco de dados MySQL
# a identidade do usuário é (admpersonnes,nobody)
user="admpersonnes"
pwd="nobody"
host="localhost"
connexion=None
try:
    print "connexion..."
    # conexão
    connexion=MySQLdb.connect(host=host,user=user,passwd=pwd)
    # acompanhamento
    print "Connexion a MySQL reussie sous l'identite host={0},user={1},passwd={2}".format(host,user,pwd)
except MySQLdb.OperationalError,message:
    print "Erreur : {0}".format(message)
finally:
    try:
        connexion.close()
    except:
        pass

  • linhas 8-11: o script conectará (linha 15) o usuário [admpersonnes / nobody] ao SGBD MySQL da máquina [localhost]. Ele não é conectado a um banco de dados específico;
  • linhas 12-24: a conexão pode falhar. Por isso, ela é feita dentro de um bloco try / except / finally;
  • linha 15: o método connect do módulo MySQLdb aceita diferentes parâmetros nomeados:
    • user: usuário proprietário da conexão [admpersonnes];
    • pwd: senha do usuário [nobody];
    • host: máquina do SGBD MySQL [localhost];
    • db: o banco de dados ao qual se conecta. Opcional.
  • linha 18: se for lançada uma exceção, ela será do tipo [ MySQLdb.OperationalError] e a mensagem de erro associada estará na variável [message];
  • linhas 20-23: na cláusula [finally], encerra-se a conexão. Em caso de exceção, ela é interceptada (linha 23), mas não é realizada nenhuma ação (linha 24).

Resultados

connexion...
Connexion a MySQL reussie sous l'identite host=localhost,user=admpersonnes,passwd=nobody

9.4. Conexão a um banco de dados MySQL - 2


Programa (mysqldb_02)


# importação do módulo MySQLdb
import sys
sys.path.append("D:\Programs\ActivePython\site-packages")
import MySQLdb

# ---------------------------------------------------------------------------------
def testeConnexion(hote,login,pwd):
    # conecta e, em seguida, desconecta (login, senha) do banco de dados MySQL do servidor host
    # lança a exceção MySQLdb.operationalError
    # conexão
    connexion=MySQLdb.connect(host=hote,user=login,passwd=pwd)
    print "Connexion a MySQL reussie sous l'identite (%s,%s,%s)" % (hote,login,passwd)
    # a conexão é encerrada
    connexion.close()
    print "Fermeture connexion MySQL reussie\n"
 

# ---------------------------------------------- main
# conexão com o banco de dados MySQL
# identidade do usuário
user="admpersonnes"
passwd="nobody"
host="localhost"
# teste de conexão
try:
    testeConnexion(host,user,passwd)
except MySQLdb.OperationalError,message:
    print message
# com um usuário inexistente
try:
    testeConnexion(host,"xx","xx")
except MySQLdb.OperationalError,message:
    print message

Notas:

  • linhas 7-15: uma função que tenta conectar e, em seguida, desconectar um usuário de um SGBD MySQL. Exibe o resultado;
  • linhas 18-34: programa principal – chama duas vezes o método testeConnexion e exibe eventuais exceções.

Resultados

1
2
3
4
Connexion a MySQL reussie sous l'identite (localhost,admpersonnes,nobody)
Fermeture connexion MySQL reussie

Echec de la connexion a MySQL : (1045, "Access denied for user 'xx'@'localhost'(using password: YES)")

9.5. Criação de uma tabela MySQL

Agora que sabemos como criar uma conexão com um SGBD MySQL, começamos a emitir comandos SQL nessa conexão. Para isso, vamos nos conectar ao banco de dados criado ([dbpersonnes]) e usar a conexão para criar uma tabela nesse banco de dados.


Programa (mysqldb_03)


# importação do módulo MySQLdb
import sys
sys.path.append("D:\Programs\ActivePython\site-packages")
import MySQLdb

# ---------------------------------------------------------------------------------
def executeSQL(connexion,update):
    # executa uma consulta de atualização na conexão
    # solicitação de um cursor
    curseur=connexion.cursor()
    # executa a consulta SQL na conexão
    try:
        curseur.execute(update)
        connexion.commit()
    except Exception, erreur:
        connexion.rollback()
        raise
    finally:
        curseur.close()

# ---------------------------------------------- main
# conexão com o banco de dados MySQL
# a identidade do usuário
ID="admpersonnes"
PWD="nobody"
# o servidor do SGBD
HOTE="localhost"
# identidade do banco de dados
BASE="dbpersonnes"
# conexão
try:
    connexion=MySQLdb.connect(host=HOTE,user=ID,passwd=PWD,db=BASE)
except MySQLdb.OperationalError,message:
    print message
    sys.exit()

# exclusão da tabela “pessoas”, caso exista
# se ela não existir, ocorrerá um erro
# ignora-se
requete="drop table personnes"
try:
    executeSQL(connexion,requete)
except:
    pass
# criação da tabela “pessoas”
requete="create table personnes (prenom varchar(30) NOT NULL, nom varchar(30) NOT NULL, age integer NOT NULL, primary key(nom,prenom))"
try:
    executeSQL(connexion,requete)
except MySQLdb.OperationalError,message:
    print message
    sys.exit()
# desconectamos e saímos
try:
    connexion.close()
except MySQLdb.OperationalError,message:
    print message
sys.exit()

Notas:

  • linha 7: a função executeSQL executa uma consulta SQL em uma conexão aberta;
  • linha 10: as operações SQL na conexão são realizadas por meio de um objeto específico chamado cursor;
  • linha 10: obtenção de um cursor;
  • linha 13: execução da consulta SQL;
  • linha 14: a transação atual é validada;
  • linha 15: em caso de exceção, a mensagem de erro é armazenada na variável erro;
  • linha 16: a transação atual é invalidada;
  • linha 17: a exceção é reenviada;
  • linha 19: haja ou não erro, o cursor é fechado. Isso libera os recursos a ele associados.

Resultados

create table personnes (prenom varchar(30) NOT NULL, nom varchar(30) NOT NULL, age integer NOT NULL, primary key(nom,prenom)) : requete reussie

Verificação com phpMyAdmin:

  • O banco de dados [dbpersonnes] [1] possui uma tabela [personnes] [2] que tem a estrutura [3] e a chave primária [4].

9.6. Preenchimento da tabela [personnes]

Depois de ter criado anteriormente a tabela [personnes], agora vamos preenchê-la.


Programa (mysqldb_04)


# importação do módulo MySQLdb
import sys
sys.path.append("D:\Programs\ActivePython\site-packages")
import MySQLdb
# outros módulos
import re

# ---------------------------------------------------------------------------------
def executerCommandes(HOTE,ID,PWD,BASE,SQL,suivi=False,arret=True):
    # utiliza a conexão (HOTE, ID, PWD, BASE)
    # executa nesta conexão os comandos SQL contidos no arquivo de texto SQL
    # esse arquivo é um arquivo de comandos SQL a ser executado, um por linha
    # se acompanhamento=True, então cada execução de um comando SQL é acompanhada por uma mensagem indicando se foi bem-sucedida ou falhou
    # se “arret” for True, a função interrompe a execução ao encontrar o primeiro erro; caso contrário, ela executa todos os comandos SQL
    # a função retorna uma lista (número de erros, erro1, erro2, ...)

    # verifica-se a presença do arquivo SQL
    data=None
    try:
        data=open(SQL,"r")
    except:
        return [1,"Le fichier %s n'existe pas" % (SQL)]

    # conexão
    try:
        connexion=MySQLdb.connect(host=HOTE,user=ID,passwd=PWD,db=BASE)
    except MySQLdb.OperationalError,erreur:
        return [1,"Erreur lors de la connexion a MySQL sous l'identite (%s,%s,%s,%s) : %s" % (HOTE, ID, PWD, BASE, erreur)]
    
    # solicita-se um cursor
    curseur=connexion.cursor()
    # execução das consultas SQL contidas no arquivo SQL
    # elas são colocadas em uma tabela
    requetes=data.readlines()
    # elas são executadas uma a uma — inicialmente, sem erros
    erreurs=[0]
    for i in range(len(requetes)):
        # armazenamos a consulta atual
        requete=requetes[i]
        # a consulta está vazia? Se sim, passa-se para a próxima consulta
        if re.match(r"^\s*$",requete):
            continue
        # execução da consulta i
        erreur=""
        try:
            curseur.execute(requete)
        except Exception, erreur:
            pass
        #: ocorreu algum erro?
        if erreur:
            # mais um erro
            erreurs[0]+=1
            # mensagem de erro
            msg="%s : Erreur (%s)" % (requete,erreur)
            erreurs.append(msg)
            # exibir na tela ou não?
            if suivi:
                print msg
            # Vamos parar?
            if arret:
                return erreurs
        else:
            if suivi: 
                print "%s : Execution reussie" % (requete)
    # encerramento da conexão e liberação dos recursos
    curseur.close()
    connexion.commit()
    # desconectando
    try:
        connexion.close()
    except MySQLdb.OperationalError,erreur:
        # mais um erro
        erreurs[0]+=1
        # mensagem de erro
        msg="%s : Erreur (%s)" % (requete,erreur)
        erreurs.append(msg)

    # retorno
    return erreurs


# ---------------------------------------------- main
# conexão com o banco de dados MySQL
# identidade do usuário
ID="admpersonnes"
PWD="nobody"
# o servidor do SGBD
HOTE="localhost"
# identidade do banco de dados
BASE="dbpersonnes"
# identidade do arquivo de texto com os comandos SQL a serem executados
TEXTE="sql.txt";

# criação e preenchimento da tabela
erreurs=executerCommandes(HOTE,ID,PWD,BASE,TEXTE,True,False)
#exibição do número de erros
print "il y a eu %s erreur(s)" % (erreurs[0])
for i in range(1,len(erreurs)):
    print erreurs[i]


Resultados

O arquivo sql.txt:

1
2
3
4
5
6
7
8
9
drop table personnes
create table personnes (prenom varchar(30) not null, nom varchar(30) not null, age integer not null, primary key (nom,prenom))
insert into personnes values('Paul','Langevin',48)
insert into personnes values ('Sylvie','Lefur',70)
xx

insert into personnes values ('Pierre','Nicazou',35)
insert into personnes values ('Geraldine','Colou',26)
insert into personnes values ('Paulette','Girond',56)

Um erro foi inserido propositalmente na linha 5.

Resultados na tela:

drop table personnes : Execution reussie
create table personnes (prenom varchar(30) not null, nom varchar(30) not null, age integer not null, primary key (nom,prenom)) : Execution reussie
insert into personnes values('Paul','Langevin',48) : Execution reussie
insert into personnes values ('Sylvie','Lefur',70) : Execution reussie
xx : Erreur ((1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xx' at
 line 1"))
insert into personnes values ('Pierre','Nicazou',35) : Execution reussie
insert into personnes values ('Geraldine','Colou',26) : Execution reussie
insert into personnes values ('Paulette','Girond',56) : Execution reussie
il y a eu 1 erreur(s)
xx : Erreur ((1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xx' at line 1"))

Verificação com phpMyAdmin:

Image

  • no [1], o link [Afficher] permite acessar o conteúdo da tabela [personnes] [2].

9.7. Execução de quaisquer consultas SQL

O script a seguir permite executar um arquivo de comandos SQL e exibir o resultado de cada um deles:

  • o resultado do SELECT se a ordem for um SELECT;
  • o número de linhas modificadas se o comando for INSERT, UPDATE, DELETE.

Programa (mysqldb_05)


# importação do módulo MySQLdb
import sys
sys.path.append("D:\Programs\ActivePython\site-packages")
import MySQLdb
# outros módulos
import re

def cutNewLineChar(ligne):
    # remove-se o marcador de fim de linha de [ligne], caso exista
    l=len(ligne)
    while(ligne[l-1]=="\n" or ligne[l-1]=="\r"):
        l-=1
    return(ligne[0:l])

# ---------------------------------------------------------------------------------
def afficherInfos(curseur):
    # exibe o resultado de uma consulta SQL
    # era uma consulta SELECT?
    if curseur.description:
        # há uma descrição — portanto, é um SELECT
        # descrição[i] é a descrição da coluna nº i da instrução SELECT
        # descriçãoQZXW2HTMLBW2ldZQXQZXW2HTMLBWzBdZQX é o nome da coluna nº i do select
        # são exibidos os nomes dos campos
        titre=""
        for i in range(len(curseur.description)):
            titre+=curseur.description[i][0]+","
        # exibe a lista de campos sem a vírgula final
        print titre[0:len(titre)-1]
        # linha separadora
        print "-"*(len(titre)-1)
        # linha atual do select
        ligne=curseur.fetchone()
        while ligne:
            print ligne
            # linha seguinte do select
            ligne=curseur.fetchone()
    else:
        # não há campos — não era um select
        print "%s lignes(s) a (ont) ete modifiee(s)" % (curseur.rowcount)


# ---------------------------------------------------------------------------------
def executerCommandes(HOTE,ID,PWD,BASE,SQL,suivi=False,arret=True):
    # utiliza a conexão (HOTE,ID,PWD,BASE)
    # executa nesta conexão os comandos SQL contidos no arquivo de texto SQL
    # esse arquivo é um arquivo de comandos SQL a ser executado, um por linha
    # se acompanhamento=1, então cada execução de um comando SQL é acompanhada por uma mensagem indicando se foi bem-sucedida ou falhou
    # se “parada” = 1, a função para ao encontrar o primeiro erro; caso contrário, ela executa todos os comandos SQL
    # a função retorna um array (número de erros, erro1, erro2, ...)

    # verifica-se a presença do arquivo SQL
    data=None
    try:
        data=open(SQL,"r")
    except:
        return [1,"Le fichier %s n'existe pas" % (SQL)]

    # conexão
    try:
        connexion=MySQLdb.connect(host=HOTE,user=ID,passwd=PWD,db=BASE)
    except MySQLdb.OperationalError,erreur:
        return [1,"Erreur lors de la connexion a MySQL sous l'identite (%s,%s,%s,%s) : %s" % (HOTE, ID, PWD, BASE, erreur)]
    
    # solicita-se um cursor
    curseur=connexion.cursor()
    # execução das consultas SQL contidas no arquivo SQL
    # colocamos em uma tabela
    requetes=data.readlines()
    # elas são executadas uma a uma — inicialmente, sem erros
    erreurs=[0]
    for i in range(len(requetes)):
        # armazenamos a consulta atual
        requete=requetes[i]
        # a consulta está vazia? Se sim, passa-se para a próxima consulta
        if re.match(r"^\s*$",requete):
            continue
        # execução da consulta i
        erreur=""
        try:
            curseur.execute(requete)
        except Exception, erreur:
            pass
        #: ocorreu algum erro?
        if erreur:
            # mais um erro
            erreurs[0]+=1
            # mensagem de erro
            msg="%s : Erreur (%s)" % (requete,erreur)
            erreurs.append(msg)
            # exibir na tela ou não?
            if suivi:
                print msg
            # Vamos parar?
            if arret:
                return erreurs
        else:
            if suivi: 
                print "%s : Execution reussie" % (requete)
                # informações sobre o resultado da consulta executada
                afficherInfos(curseur)

    # encerramento da conexão e liberação dos recursos
    curseur.close()
    connexion.commit()
    # desconectando
    try:
        connexion.close()
    except MySQLdb.OperationalError,erreur:
        # mais um erro
        erreurs[0]+=1
        # mensagem de erro
        msg="%s : Erreur (%s)" % (requete,erreur)
        erreurs.append(msg)

    # retorno
    return erreurs


# ---------------------------------------------- main
# conexão com o banco de dados MySQL
# identidade do usuário
ID="admpersonnes"
PWD="nobody"
# o servidor do SGBD
HOTE="localhost"
# identidade do banco de dados
BASE="dbpersonnes"
# identidade do arquivo de texto com os comandos SQL a serem executados
TEXTE="sql2.txt"


# criação e preenchimento da tabela
erreurs=executerCommandes(HOTE,ID,PWD,BASE,TEXTE,True,False)
#exibição do número de erros
print "il y a eu %s erreur(s)" % (erreurs[0])
for i in range(1,len(erreurs)):
    print erreurs[i]

Notas:

  • a novidade está na linha 100 do script: após a execução de uma ordem SQL, são solicitadas informações sobre o cursor utilizado por essa consulta. Essas informações são fornecidas pela função afficheInfos nas linhas 16 a 40;
  • linhas 19 e 39: se a consulta SQL executada fosse uma SELECT, o atributo [curseur.description] seria uma matriz cujo elemento nº i descreve o campo nº i do resultado da consulta SELECT. Caso contrário, o atributo [curseur.rowcount] (linha 39) é o número de linhas modificadas pela consulta INSERT, UPDATE ou DELETE;
  • linhas 32 e 36: o método [curseur.fetchone] permite recuperar a linha atual do SELECT. Existe um método [curseur.fetchall] que permite recuperá-las de uma só vez.

Resultados

O arquivo das consultas executadas:

1
2
3
4
5
6
7
8
9
select * from personnes
select nom,prenom from personnes order by nom asc, prenom desc
select * from personnes where age between 20 and 40 order by age desc, nom asc, prenom asc
insert into personnes values('Josette','Bruneau',46)
update personnes set age=47 where nom='Bruneau'
select * from personnes where nom='Bruneau'
delete from personnes where nom='Bruneau'
select * from personnes where nom='Bruneau'
xselect * from personnes where nom='Bruneau'

Resultados na tela:

select * from personnes : Execution reussie
prenom,nom,age
---------------
('Geraldine', 'Colou', 26L)
('Paulette', 'Girond', 56L)
('Paul', 'Langevin', 48L)
('Sylvie', 'Lefur', 70L)
('Pierre', 'Nicazou', 35L)
select nom,prenom from personnes order by nom asc, prenom desc : Execution reussie
nom,prenom
-----------
('Colou', 'Geraldine')
('Girond', 'Paulette')
('Langevin', 'Paul')
('Lefur', 'Sylvie')
('Nicazou', 'Pierre')
select * from personnes where age between 20 and 40 order by age desc, nom asc,prenom asc : Execution reussie
prenom,nom,age
---------------
('Pierre', 'Nicazou', 35L)
('Geraldine', 'Colou', 26L)
insert into personnes values('Josette','Bruneau',46) : Execution reussie
1 lignes(s) a (ont) ete modifiee(s)
update personnes set age=47 where nom='Bruneau' : Execution reussie
1 lignes(s) a (ont) ete modifiee(s)
select * from personnes where nom='Bruneau' : Execution reussie
prenom,nom,age
---------------
('Josette', 'Bruneau', 47L)
delete from personnes where nom='Bruneau' : Execution reussie
1 lignes(s) a (ont) ete modifiee(s)
select * from personnes where nom='Bruneau' : Execution reussie
prenom,nom,age
---------------
xselect * from personnes where nom='Bruneau' : Erreur ((1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xselect * from personnes where nom='Bruneau'' at line 1"))

Verificação PhpMyadmin: