MySQL Schema设计(三)利用Python操作Schema
生活随笔
收集整理的這篇文章主要介紹了
MySQL Schema设计(三)利用Python操作Schema
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
來(lái)源:http://blog.itpub.net/26515977/viewspace-1208256/ 本文中?SQLAlchemy部分可參考http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014320114981139589ac5f02944601ae22834e9c521415000 弓在箭要射出之前,低聲對(duì)箭說(shuō)道,“你的自由是我的”。Schema如箭,弓似Python,選擇Python,是Schema最大的自由。而自由應(yīng)是一個(gè)能使自己變得更好的機(jī)會(huì)。
數(shù)據(jù)庫(kù)連接模塊: [root@DataHacker ~]# cat dbapi.py #!/usr/bin/env ipython #coding = utf-8 #Author: linwaterbin@gmail.com #Time: 2014-1-29import MySQLdb as dbapiUSER = \'root\' PASSWD = \'oracle\' HOST = \'127.0.0.1\' DB = \'sakila\'conn = dbapi.connect(user=USER,passwd=PASSWD,host=HOST,db=DB)
1 打印列的元數(shù)據(jù) [root@DataHacker ~]# cat QueryColumnMetaData.py #!/usr/bin/env ipythonfrom 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 recordcur.close() conn.close()
2 通過(guò)列名訪問(wèn)列值 默認(rèn)情況下,獲取方法從數(shù)據(jù)庫(kù)作為"行"返回的值是元組 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]: 2LIn [5]: results = cur.fetchone()In [6]: print results[0] 58In [7]: print results[1] AKROYD
我們能夠借助cursorclass屬性來(lái)作為字典返回 In [2]: import MySQLdb.cursorsIn [3]: import MySQLdbIn [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]: 2LIn [8]: results = cur.fetchone()In [9]: print results[\'actor_id\'] 58In [10]: print results[\'last_name\'] AKROYD
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屬性指定要?jiǎng)h除的對(duì)象
example 3: 5種約束 3 .1 primary key 下面2種方式都可以,一個(gè)是列級(jí),一個(gè)是表級(jí) 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)
請(qǐng)看代碼 #!/usr/bin/env python import optparse from dbapi import *#構(gòu)造OptionParser實(shí)例,配置期望的選項(xiàng) parser = optparse.OptionParser(usage="%prog [options] <arg1> <arg2> [<arg3>...]",version=\'1.0\',) #定義命令行選項(xiàng),用add_option一次增加一個(gè) 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#實(shí)現(xiàn)動(dòng)態(tài)讀查詢 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 = 1for 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)#把輸出結(jié)果定向到指定文件 if options.outfile:outfile = options.outfilewith open(outfile,\'w\') as out:out.write(output) else:print output#關(guān)閉游標(biāo)與連接 conn.close() cur.close()
By DataHacker 2014-2-5 Good Luck!
㈠ MySQLdb部分
表結(jié)構(gòu): 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)數(shù)據(jù)庫(kù)連接模塊: [root@DataHacker ~]# cat dbapi.py #!/usr/bin/env ipython #coding = utf-8 #Author: linwaterbin@gmail.com #Time: 2014-1-29import MySQLdb as dbapiUSER = \'root\' PASSWD = \'oracle\' HOST = \'127.0.0.1\' DB = \'sakila\'conn = dbapi.connect(user=USER,passwd=PASSWD,host=HOST,db=DB)
1 打印列的元數(shù)據(jù) [root@DataHacker ~]# cat QueryColumnMetaData.py #!/usr/bin/env ipythonfrom 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 recordcur.close() conn.close()
1.)調(diào)用execute()之后,cursor應(yīng)當(dāng)設(shè)置其description屬性
2.)是個(gè)tuple,共7列:列名、類型、顯示大小、內(nèi)部大小、精度、范圍以及一個(gè)是否接受null值的標(biāo)記 [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 通過(guò)列名訪問(wèn)列值 默認(rèn)情況下,獲取方法從數(shù)據(jù)庫(kù)作為"行"返回的值是元組 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]: 2LIn [5]: results = cur.fetchone()In [6]: print results[0] 58In [7]: print results[1] AKROYD
我們能夠借助cursorclass屬性來(lái)作為字典返回 In [2]: import MySQLdb.cursorsIn [3]: import MySQLdbIn [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]: 2LIn [8]: results = cur.fetchone()In [9]: print results[\'actor_id\'] 58In [10]: print results[\'last_name\'] AKROYD
㈡ SQLAlchemy--SQL煉金術(shù)師
雖然SQL有國(guó)際標(biāo)準(zhǔn),但遺憾的是,各個(gè)數(shù)據(jù)庫(kù)廠商對(duì)這些標(biāo)準(zhǔn)的解讀都不一樣,并且都在標(biāo)準(zhǔn)的基礎(chǔ)上實(shí)現(xiàn)了各自的私有語(yǔ)法。為了隱藏不同SQL“方言”之間到區(qū)別,人們開(kāi)發(fā)了諸如SQLAlchemy之類的工具 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屬性指定要?jiǎng)h除的對(duì)象
example 3: 5種約束 3 .1 primary key 下面2種方式都可以,一個(gè)是列級(jí),一個(gè)是表級(jí) 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 默認(rèn)值
分2類:悲觀(值由DB Server提供)和樂(lè)觀(值由SQLAlshemy提供),其中樂(lè)觀又可分: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
數(shù)據(jù)的安全是否暴露在完全可信任的對(duì)象面前,這是任何有安全意識(shí)的DBA都不會(huì)去冒的風(fēng)險(xiǎn)。比較好的方式是盡可能隱藏Schema結(jié)構(gòu)并驗(yàn)證用戶輸入的數(shù)據(jù)完整性,這在一定程度上雖然增加了運(yùn)維成本,但安全無(wú)小事。 這里借助開(kāi)發(fā)一個(gè)命令行工具來(lái)闡述該問(wèn)題 需求:隱藏表結(jié)構(gòu),實(shí)現(xiàn)動(dòng)態(tài)查詢,并將結(jié)果模擬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 ......<此處省略大部分輸出>......請(qǐng)看代碼 #!/usr/bin/env python import optparse from dbapi import *#構(gòu)造OptionParser實(shí)例,配置期望的選項(xiàng) parser = optparse.OptionParser(usage="%prog [options] <arg1> <arg2> [<arg3>...]",version=\'1.0\',) #定義命令行選項(xiàng),用add_option一次增加一個(gè) 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#實(shí)現(xiàn)動(dòng)態(tài)讀查詢 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 = 1for 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)#把輸出結(jié)果定向到指定文件 if options.outfile:outfile = options.outfilewith open(outfile,\'w\') as out:out.write(output) else:print output#關(guān)閉游標(biāo)與連接 conn.close() cur.close()
By DataHacker 2014-2-5 Good Luck!
轉(zhuǎn)載于:https://www.cnblogs.com/stevenzeng/p/5154963.html
總結(jié)
以上是生活随笔為你收集整理的MySQL Schema设计(三)利用Python操作Schema的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: YunTable 0.1版正式发布!!!
- 下一篇: 在struts框架下实现文件的上传