• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    MySQL数据库设计之利用Python操作Schema方法详解

    弓在箭要射出之前,低声对箭说道,“你的自由是我的”。Schema如箭,弓似Python,选择Python,是Schema最大的自由。而自由应是一个能使自己变得更好的机会。

    Schema是什么?

    不管我们做什么应用,只要和用户输入打交道,就有一个原则--永远不要相信用户的输入数据。意味着我们要对用户输入进行严格的验证,web开发时一般输入数据都以JSON形式发送到后端API,API要对输入数据做验证。一般我都是加很多判断,各种if,导致代码很丑陋,能不能有一种方式比较优雅的验证用户数据呢?Schema就派上用场了。

    ㈠ MySQLdb部分

    表结构:

    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) 

    数据库连接模块:

    [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 打印列的元数据

    [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.)调用execute()之后,cursor应当设置其description属性
    2.)是个tuple,共7列:列名、类型、显示大小、内部大小、精度、范围以及一个是否接受null值的标记

    [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 通过列名访问列值

    默认情况下,获取方法从数据库作为"行"返回的值是元组

    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 

    我们能够借助cursorclass属性来作为字典返回

    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炼金术师

    虽然SQL有国际标准,但遗憾的是,各个数据库厂商对这些标准的解读都不一样,并且都在标准的基础上实现了各自的私有语法。为了隐藏不同SQL“方言”之间到区别,人们开发了诸如SQLAlchemy之类的工具

    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() 

    example 1:表定义

    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) 

    example 2:表删除

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

    example 3: 5种约束

    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 默认值

    分2类:悲观(值由DB Server提供)和乐观(值由SQLAlshemy提供),其中乐观又可分:insert和update

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

    ㈢ 隐藏Schema

    数据的安全是否暴露在完全可信任的对象面前,这是任何有安全意识的DBA都不会去冒的风险。比较好的方式是尽可能隐藏Schema结构并验证用户输入的数据完整性,这在一定程度上虽然增加了运维成本,但安全无小事。

    这里借助开发一个命令行工具来阐述该问题

    需求:隐藏表结构,实现动态查询,并将结果模拟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'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 
    ......此处省略大部分输出>...... 

    请看代码

    #!/usr/bin/env python
    import optparse
    from dbapi import *
    
    #构造OptionParser实例,配置期望的选项
    parser = optparse.OptionParser(usage="%prog [options] arg1> arg2> [arg3>...]",version='1.0',)
    #定义命令行选项,用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 '%s'"%(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 = ''.join(output)
    #把输出结果定向到指定文件
    if options.outfile:
     outfile = options.outfile
     with open(outfile,'w') as out:
      out.write(output)
    else:
     print output
    #关闭游标与连接
    conn.close()
    cur.close()
    

    总结

    以上就是本文关于MySQL数据库设计之利用Python操作Schema方法详解的全部内容,希望对大家有所帮助。欢迎参阅:Python定时器实例代码、Python生成数字图片代码分享等,有什么问题可以随时留言,小编会及时回复大家的,欢迎留言交流讨论。

    您可能感兴趣的文章:
    • Python通过Schema实现数据验证方式
    • python导出hive数据表的schema实例代码
    • python读取hdfs上的parquet文件方式
    • 解决python将xml格式文件转换成txt文件的问题(xml.etree方法)
    • python 如何将字典写为json文件
    • Python 标准库zipfile将文件夹加入压缩包的操作方法
    • python文件处理--文件读写详解
    • 用 Python 定义 Schema 并生成 Parquet 文件详情
    上一篇:windows 10下解压版MySql安装配置方法教程
    下一篇:Oracle和MySQL的高可用方案对比分析
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    MySQL数据库设计之利用Python操作Schema方法详解 MySQL,数据库,设计,之,利用,