Maison  >  Article  >  base de données  >  Explication détaillée de la base de données MySQL utilisant Python pour faire fonctionner la méthode Schema

Explication détaillée de la base de données MySQL utilisant Python pour faire fonctionner la méthode Schema

小云云
小云云original
2017-12-08 09:52:501680parcourir

Qu'est-ce que le schéma ?

Peu importe l'application que nous créons, tant que nous traitons des entrées de l'utilisateur, il y a un principe : ne jamais faire confiance aux données d'entrée de l'utilisateur. Cela signifie que nous devons vérifier strictement les entrées des utilisateurs. Dans le développement Web, les données d'entrée sont généralement envoyées à l'API back-end sous forme JSON, et l'API doit vérifier les données d'entrée. Généralement, j'ajoute beaucoup de jugements et divers si, ce qui rend le code très laid. Existe-t-il une manière plus élégante de vérifier les données utilisateur ? Le schéma est utile. Cet article présente principalement l'explication détaillée de la méthode d'utilisation de Python pour faire fonctionner Schema dans la conception de bases de données MySQL. C'est plutôt bien. Je le partagerai avec vous ici pour la référence des amis qui en ont besoin.

㈠Partie MySQLdb

Structure de la table :

mysql> use sakila; 
mysql> desc actor; 
+-------------+----------------------+------+-----+-------------------+-----------------------------+ 
| Field    | Type         | Null | Key | Default      | Extra            | 
+-------------+----------------------+------+-----+-------------------+-----------------------------+ 
| actor_id  | smallint(5) unsigned | NO  | PRI | NULL       | auto_increment       | 
| first_name | varchar(45)     | NO  |   | NULL       |               | 
| last_name  | varchar(45)     | NO  | MUL | NULL       |               | 
| last_update | timestamp      | NO  |   | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | 
+-------------+----------------------+------+-----+-------------------+-----------------------------+ 
4 rows in set (0.00 sec)

Module de connexion à la base de données :

[root@DataHacker ~]# cat dbapi.py 
#!/usr/bin/env ipython 
#coding = utf-8 
#Author: linwaterbin@gmail.com 
#Time: 2014-1-29 
 
import MySQLdb as dbapi 
 
USER = 'root' 
PASSWD = 'oracle' 
HOST = '127.0.0.1' 
DB = 'sakila' 
 
conn = dbapi.connect(user=USER,passwd=PASSWD,host=HOST,db=DB)

1 Imprimer les métadonnées de la colonne

[root@DataHacker ~]# cat QueryColumnMetaData.py 
#!/usr/bin/env ipython 
 
from dbapi import * 
 
cur = conn.cursor() 
statement = """select * from actor limit 1""" 
cur.execute(statement) 
 
print "output column metadata....." 
print 
for record in cur.description: 
  print record 
 
cur.close() 
conn.close()

1.) Après avoir appelé execute(), le curseur doit définir son attribut de description
2.) C'est un tuple avec 7 colonnes au total : nom de la colonne, type, taille d'affichage, taille interne, précision, plage et un indicateur indiquant s'il faut accepter les valeurs nulles

[root@DataHacker ~]# chmod +x QueryColumnMetaData.py 
[root@DataHacker ~]# ./QueryColumnMetaData.py 
output column metadata..... 
 
('actor_id', 2, 1, 5, 5, 0, 0) 
('first_name', 253, 8, 45, 45, 0, 0) 
('last_name', 253, 7, 45, 45, 0, 0) 
('last_update', 7, 19, 19, 19, 0, 0)

2 Colonne d'accès valeurs par nom de colonne

Par défaut, la valeur renvoyée par la méthode get sous forme de "ligne" de la base de données est le tuple

In [1]: from dbapi import * 
In [2]: cur = conn.cursor() 
In [3]: v_sql = "select actor_id,last_name from actor limit 2" 
In [4]: cur.execute(v_sql) 
Out[4]: 2L 
In [5]: results = cur.fetchone() 
In [6]: print results[0] 
58 
In [7]: print results[1] 
AKROYD

Nous pouvons utiliser l'attribut curseurclass pour renvoyer

In [2]: import MySQLdb.cursors 
In [3]: import MySQLdb 
In [4]: conn = MySQLdb.connect(user='root',passwd='oracle',host='127.0.0.1',db='sakila',cursorclass=MySQLdb.cursors.DictCursor) 
In [5]: cur = conn.cursor() 
In [6]: v_sql = "select actor_id,last_name from actor limit 2" 
In [7]: cur.execute(v_sql) 
Out[7]: 2L 
In [8]: results = cur.fetchone() 
In [9]: print results['actor_id'] 
58 
In [10]: print results['last_name'] 
AKROYD

㈡ SQLAlchemy--SQL Alchemist

Bien qu'il existe des normes internationales pour SQL, malheureusement, chaque fabricant de bases de données interprète ces normes différemment et implémente sa propre syntaxe privée basée sur ces normes. Afin de masquer les différences entre les différents « dialectes » SQL, les gens ont développé des outils tels que SQLAlchemy

Module de connexion SQLAlchemy :

[root@DataHacker Desktop]# cat sa.py 
import sqlalchemy as sa 
engine = sa.create_engine('mysql://root:oracle@127.0.0.1/testdb',pool_recycle=3600) 
metadata = sa.MetaData()

exemple 1 : Définition de table

In [3]: t = Table('t',metadata, 
   ...:        Column('id',Integer), 
   ...:        Column('name',VARCHAR(20)), 
   ...:        mysql_engine='InnoDB', 
   ...:        mysql_charset='utf8' 
   ...:       ) 
 
In [4]: t.create(bind=engine)

exemple 2 : Suppression de table

有2种方式,其一: 
In [5]: t.drop(bind=engine,checkfirst=True)  
另一种是: 
In [5]: metadata.drop_all(bind=engine,checkfirst=True),其中可以借助tables属性指定要删除的对象

exemple 3 : 5 types de contraintes

3 .1 primary key 
下面2种方式都可以,一个是列级,一个是表级 
In [7]: t_pk_col = Table('t_pk_col',metadata,Column('id',Integer,primary_key=True),Column('name',VARCHAR(20))) 
In [8]: t_pk_col.create(bind=engine) 
In [9]: t_pk_tb = Table('t_pk_01',metadata,Column('id',Integer),Column('name',VARCHAR(20)),PrimaryKeyConstraint('id','name',name='prikey')) 
In [10]: t_pk_tb.create(bind=engine) 
3.2 Foreign Key 
In [13]: t_fk = Table('t_fk',metadata,Column('id',Integer,ForeignKey('t_pk.id'))) 
In [14]: t_fk.create(bind=engine) 
In [15]: t_fk_tb = Table('t_fk_tb',metadata,Column('col1',Integer),Column('col2',VARCHAR(10)),ForeignKeyConstraint(['col1','col2'],['t_pk.id','t_pk.name'])) 
In [16]: t_fk_tb.create(bind=engine) 
3.3 unique 
In [17]: t_uni = Table('t_uni',metadata,Column('id',Integer,unique=True)) 
In [18]: t_uni.create(bind=engine) 
In [19]: t_uni_tb = Table('t_uni_tb',metadata,Column('col1',Integer),Column('col2',VARCHAR(10)),UniqueConstraint('col1','col2')) 
In [20]: t_uni_tb.create(bind=engine) 
3.4 check 
   虽然能成功,但MySQL目前尚未支持check约束。这里就不举例了。 
3.5 not null 
In [21]: t_null = Table('t_null',metadata,Column('id',Integer,nullable=False)) 
In [22]: t_null.create(bind=engine)

4 valeurs par défaut

est divisé en 2 catégories : pessimisme (valeur fournie par DB Server) et optimisme (valeur fournie par SQLAlshemy). L'optimisme peut être divisé en : insertion et mise à jour

<.>
4.1 例子:insert 
In [23]: t_def_inser = Table(&#39;t_def_inser&#39;,metadata,Column(&#39;id&#39;,Integer),Column(&#39;name&#39;,VARCHAR(10),server_default=&#39;cc&#39;)) 
In [24]: t_def_inser.create(bind=engine) 
3.2 例子:update 
In [25]: t_def_upda = Table(&#39;t_def_upda&#39;,metadata,Column(&#39;id&#39;,Integer),Column(&#39;name&#39;,VARCHAR(10),server_onupdate=&#39;DataHacker&#39;)) 
In [26]: t_def_upda.create(bind=engine) 
3.3 例子:Passive  
In [27]: t_def_pass = Table(&#39;t_def_pass&#39;,metadata,Column(&#39;id&#39;,Integer),Column(&#39;name&#39;,VARCHAR(10),DefaultClause(&#39;cc&#39;))) 
In [28]: t_def_pass.create(bind=engine)

㈢ Masquer le schéma

Que la sécurité des données soit exposée à un objet totalement digne de confiance, cela est la clé pour quiconque court un risque qu'aucun administrateur de base de données soucieux de la sécurité ne prendrait. Un meilleur moyen consiste à masquer autant que possible la structure du schéma et à vérifier l'intégrité des données saisies par l'utilisateur. Bien que cela augmente dans une certaine mesure les coûts d'exploitation et de maintenance, ce n'est pas une question anodine en matière de sécurité.


Nous développons ici un outil de ligne de commande pour illustrer ce problème


Exigences : masquer la structure de la table, implémenter une requête dynamique et simuler les résultats sur la sortie MySQL G

版本: 
[root@DataHacker ~]# ./sesc.py --version 
1.0 
查看帮助: 
[root@DataHacker ~]# ./sesc.py -h 
Usage: sesc.py [options] <arg1> <arg2> [<arg3>...] 
Options: 
 --version       show program&#39;s version number and exit 
 -h, --help      show this help message and exit 
 -q TERM        assign where predicate 
 -c COL, --column=COL assign query column 
 -t TABLE       assign query table 
 -f, --format     -f must match up -o 
 -o OUTFILE      assign output file 
我们要的效果: 
[root@DataHacker ~]# ./sesc.py -t actor -c last_name -q s% -f -o output.txt 
[root@DataHacker ~]# cat output.txt 
************ 1 row ******************* 
actor_id: 180 
first_name: JEFF 
last_name: SILVERSTONE 
last_update: 2006-02-15 04:34:33 
************ 2 row ******************* 
actor_id: 195 
first_name: JAYNE 
last_name: SILVERSTONE 
last_update: 2006-02-15 04:34:33 
......<此处省略大部分输出>......

Veuillez consulter le code

#!/usr/bin/env python
import optparse
from dbapi import *

#构造OptionParser实例,配置期望的选项
parser = optparse.OptionParser(usage="%prog [options] <arg1> <arg2> [<arg3>...]",version=&#39;1.0&#39;,)
#定义命令行选项,用add_option一次增加一个
parser.add_option("-q",action="store",type="string",dest="term",help="assign where predicate")
parser.add_option("-c","--column",action="store",type="string",dest="col",help="assign query column")
parser.add_option("-t",action="store",type="string",dest="table",help="assign query table")
parser.add_option("-f","--format",action="store_true",dest="format",help="-f must match up -o")
parser.add_option("-o",action="store",type="string",dest="outfile",help="assign output file")
#解析命令行
options,args = parser.parse_args()
#把上述dest值赋给我们自定义的变量
table = options.table
column = options.col
term = options.term
format = options.format
#实现动态读查询
statement = "select * from %s where %s like &#39;%s&#39;"%(table,column,term)
cur = conn.cursor()
cur.execute(statement)
results = cur.fetchall()
#模拟 \G 输出形式
if format is True:
 columns_query = "describe %s"%(table)
 cur.execute(columns_query)
 heards = cur.fetchall()
 column_list = []
 for record in heards:
  column_list.append(record[0])
 output = ""
 count = 1
 for record in results:
  output = output + "************ %s row ************\n\n"%(count)
  for field_no in xrange(0, len(column_list)):
   output = output + column_list[field_no]+ ": " + str(record[field_no]) + "\n"
  output = output + "\n"
  count = count + 1
else:
 output = []
 for record in xrange(0,len(results)):
  output.append(results[record])
 output = &#39;&#39;.join(output)
#把输出结果定向到指定文件
if options.outfile:
 outfile = options.outfile
 with open(outfile,&#39;w&#39;) as out:
  out.write(output)
else:
 print output
#关闭游标与连接
conn.close()
cur.close()

Recommandations associées :

Explication détaillée de la différence entre table et schéma dans la base de données

Introduction détaillée à information_schema dans MySQL

Cluster distribué MySQL MyCAT (2) Explication détaillée du code de schéma

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn