python用另一个字段替代本字段的null_Python中的数据库
數據庫和Python
持久化存儲
在任何應用中,都需要持久化存儲,一般有三種基礎的存儲機制,文件,數據庫系統,以及一些混合類型,一種是使用普通文件或者python特定文件進行訪問,另一種是使用數據庫管理器訪問。
數據庫
底層存儲
數據庫通常使用文件系統作為基本的持久化存儲,他可以是普通的操作系統文件,專用的操作系統文件,甚至是原始的磁盤分區
數據庫
數據庫存儲可以抽象為一張表,每行數據都有一些字段對應數據庫的列,每一列的表定義的集合以及每個表的數據類型放到一起定義了數據庫的模式。
數據庫可以創建和刪除,表也一樣。當查詢一個數據庫的時候,可以一次性取回一次性結果,也可以逐條遍歷每個結果行,一些數據庫使用游標的概念來提交SQL命令,查詢以及獲取結果,不管是一次性獲取還是逐行獲取都可以使用這個概念。
在python中數據庫是通過適配器的方式進行訪問的,適配器是一個python模塊,使用它可以與關系數據庫的客戶端庫(通常是使用C語言編寫的)接口相連。一般情況下會推薦所有的python適配器應當符合python數據庫特殊興趣小組的API標準。
python數據庫應用的結構,包括使用和沒有使用ORM的情況,DB-API是連接到數據庫客戶端的C語言庫接口。
Python的DB-API
DB-API闡明一系列所需對象和數據庫訪問機制的標準,它可以為不同的數據庫適配器和底層數據庫系統提供一致性訪問。
模塊屬性
屬性描述apilevel需要適配器兼容的DB-API版本threadsafety本模塊線程安全級別paramstyle本模塊sql語句參數風格connect()Connect()函數
數據屬性
apilevel:該字符串指明了模塊要兼容的DB-API最高版本,比如,1.0,2.0等,默認值是1.0
threadsafety:這是一個整型值,可選值如下:
- 0,不支持線程安全,線程間不能共享模塊
- 1,最小化線程安全支持,線程間可以共享模塊,但是不能共享連接
- 2,適度的線程安全支持,線程間可以共享模塊和連接,但是不能共享游標
- 3,完整的線程安全支持,線程間可以共享模塊,連接和游標
參數風格
該參數是一個字符串,用于指定構建查詢行或命令時使用的字符串替代形式
參數風格描述示例numeric數值位置風格WHERE name=:1named命名風格WHERE name=:namepyformatPython字典printf()格式轉換WHERE name=%(name)sqmark問號風格WHERE name=?formatANSIC 的printf()格式風格WHERE name=%s
函數屬性
connect()函數通過Connection對象訪問數據,兼容模塊必須實現connect()函數,該函數創建并返回一個Connection對象.
可以使用包含多個參數的字符串(DSN)來傳遞數據庫連接信息,也可以按照位置傳遞每個參數,或者是使用關鍵字參數的形式傳入。
例子
connect(dsn="myhost:MYDB",user="guido",password="1234")1參數描述user用戶名password密碼host主機名database數據庫名dsn數據源名
使用DSN還是獨立參數主要基于所連接的系統,比如,你使用的像ODBC或者JDBC的API,這需要使用DSN,而如果你直接使用數據庫,則更傾向于使用獨立的登陸參數,另一個使用獨立參數的原因就是很多數據適配器并沒有實現對DSN的支持,比如mysqldb使用的db而不是database
- MySQLdb.connect(host=”dbsever”,db=”inv”,user=’root’)
- PgSQL.connect(database=”sales”)
- psycopg.connect(database=”temp”,user=”pgsql”)
- gadfly.dbapi20.connect(‘csrDB’,’/usr/loacl/database’)
- sqlites.connect(‘marketing/test’)
Connection對象
應用與數據庫之間進行通信需要建立數據庫連接,他是最基本的機制,只有通過數據庫連接才能吧命令傳遞給服務器,并得到返回結果。當一個鏈接建立后,可以創建一個游標,向數據庫發送請求。
Connection對象方法
方法名描述close關閉數據庫連接commit提交當前事務rollback取消當前事務cursor使用該鏈接創建(并返回)一個游標或者類游標的對象errorhandler(cxn,cur,errls,errval)作為給定連接的游標的處理程序
當使用close()的時候,這個鏈接將不在使用,否則會進入到異常的處理中如果數據庫不支持事務處理,或者啟用了自動提交功能,commit()方法都將無法使用。和commit()相似,rollback()方法也只有在支持事務處理的數據庫中才有用,發生異常之后,rollback()會將數據庫的狀態恢復到事務處理開始時。
如果RDBMS不支持游標,那么cursor()任然會返回一個盡可能模仿真實游標的對象,這是最基本的要求。
cursor對象
游標可以讓用戶提交數據庫命令,并獲得查詢的結果行。Python DB-API游標對象總能提供游標的功能。即使是那些不支持游標的數據庫。此時,如果你創建了一個數據庫適配器,那必須要實現cursor對象,以扮演類似游標的角色。
當游標創建好后,就可以執行查詢或者命令,,并從結果集中取回一行或者多行結果。對象屬性描述arraysize使用fetchmany()方法時,一次取出的結果行,默認為1connection創建此游標的連接description返回游標活動狀態:(name,type_code,dispaly_size,internal_size,precison,scale,null_ok)lastrowid上次修改行的行IDrowcount上次execute*()方法處理或影響的行數callproc(func [,args])調用存儲過程close()關閉游標execute(op [,args])執行數據庫查詢命令executemany(op,args)類似execute()和map()結合,為給定的所有參數準備并執行數據庫查詢或者命令fetchone()獲取查詢結果的下一行fetchmany([size=cursor.arraysize])獲取查詢結果的下面size行fetchall()獲取查詢結果的所有行
類型對象和構造函數
類型對象描述Date(yr,mo,dy)日期值對象Time(hr,min,sec)時間值對象Timestamp(yr,mo,dy,hr,min,sec)時間戳對象DateFromTicks(ticks)日期對象TimeFromTicks(ticks)時間對象TimestampFromTicks(ticks)時間戳對象Binary對應二進制字符串對象STRING表示基于字符串列的對象,比如varcharBINARY表示長二進制列對象 比如 RAW,BLOBNUMBER表示數值了列對象DATETIME表示日期/時間了列對象ROWID表示“行ID” 列對象
python的MySQLdb模塊
數據庫:
mysql> desc stu;+---------------+----------+------+-----+---------+----------------+| Field | Type | Null | Key | Default | Extra |+---------------+----------+------+-----+---------+----------------+| stu_id | int(11) | NO | PRI | NULL | auto_increment || name | char(32) | NO | | NULL | || age | int(11) | NO | | NULL | || register_date | date | YES | | NULL | |+---------------+----------+------+-----+---------+----------------+4 rows in set (0.00 sec)12345678910數據:
mysql> select * from stu;+--------+------+-----+---------------+| stu_id | name | age | register_date |+--------+------+-----+---------------+| 1 | v1 | 22 | 2016-10-17 || 2 | v2 | 24 | 2016-10-17 || 3 | v3 | 23 | 2016-10-17 || 4 | v2 | 25 | 2016-10-17 || 5 | v1 | 25 | 2016-10-17 || 6 | v1 | 23 | 2016-10-17 |+--------+------+-----+---------------+6 rows in set (0.00 sec)1234567891011121314連接數據庫
con=MySQLdb.connect(host='localhost',user='root',passwd='123456',db='notes')#獲取游標cur=con.cursor()123插入數據
t=datetime.datetime.now().strftime("%Y-%m-%d")name='v5'reConut=cur.execute("insert into stu (name,age,register_date) values(%s,%s,%s)",(name,22,t))print reConutcur.close()con.close()123456批量插入數據
li=[ ('v6',22,t), ('v7',45,t)]reConut=cur.executemany("insert into stu (name,age,register_date) values(%s,%s,%s)",li)print reConutcon.commit()cur.close()con.close()12345678910刪除數據
reCount=cur.execute("delete from stu where stu_id=11")print reCountcon.commit()cur.close()con.close()123456修改數據
reCount=cur.execute("update stu set age=%s where name=%s",(78,'v5'))print reCountcon.commit()cur.close()con.close()123456查找
re=cur.execute("select * from stu")print re#print cur,fetchone() #f一條print cur.fetchall() #所有的cur.close()con.close()1234567PostgreSQL
與Mysql不同,PostgreSQL至少包含三種Python適配器:psycopg(推薦),PyPgSQL和PyPgSQL。還有一種適配器,叫PoPy,目前已廢棄,并且在2003年將其項目與PyGreSQL進行了合并。
psycopg模塊
import psycopgcon=psycopg.connect(user='pgsql')cur=con.cursor()cur.execute('select * from pg_database')rows=cur.fetchall()for i in rows: print icur.close()con.commit()con.close()1234567891011SQLite
對于簡單的應用而言,使用文件作為持久化存儲通常就足夠了,但是大多數復雜的數據驅動的應用則需要全功能的關系數據庫,SQLite的目標則是介于兩者之間的中小系統,他量級輕,速度快,沒有服務器,很少或者不需要進行管理。
SQLite被打包在Python中,(即sqlite3模塊納入了標準庫中)。在標準庫中擁有該模塊,可以使你在Python中使用SQLite開發更加快速,并且使你在有需要時,能夠更加任意的移植到更加強大的RDBMS
import sqlite3con=sqlite3.connect('sqlite_test/test')cur=con.cursor()cur.execute('create table users(login varchar(8)),userid integer')cur.execute('insert into users values("join",100)')cur.execute('insert into users values("jane",100)')cur.execute('select * from users')for i in cur.fetchall(): print i"""(u'join',100)(u'jane',100)"""cur.close()con.commit()con.close()1234567891011121314151617ORM
ORM系統的作者將純SQL語句進行了抽象化處理,將其實現為Python中的對象,這樣你只操作這些對象就能完成與生成SQL語句相同的任務。
數據庫表被神器的轉化為Python類,其中的數據列作為屬性,而數據庫操作則會作為方法,讓你的應用支持ORM與標準數據庫適配器有點類似,由于ORM需要代替你執行很多工作,因此一些事情變得更加復雜,或者需要比直接使用適配器更多的代碼行。不過,帶來了更高的工作效率
python和ORM
目前最知名的python ORM是SQLalchemy和SQLObject,由于設計哲學的不同,這兩種ORM也會存在些許區別。
其他一些Python ORM還包括,Storm,PyDO/PyDO2、PDO、Dejavu、Durus、QLime和ForgetSQL。基于web的大型系統也會包含他們自己的ORM組件,如WebWare,MiddieKit和Django的數據庫API。
SQLAlchemy
SQLAlchemy是Python編程語言下的一款ORM(對象關系映射)框架,該框架建立在數據庫API之上,使用關系對象映射進行數據庫操作,簡言之便是:將對象轉換成SQL,然后使用數據API執行SQL并獲取執行結果。
內部處理
Dialect用于和數據API進行交流,根據配置文件的不同調用不同的數據庫API,從而實現對數據庫的操作,如:
MySQL-Python mysql+mysqldb://:@[:]/pymysql mysql+pymysql://:@/[?]MySQL-Connector mysql+mysqlconnector://:@[:]/cx_Oracle oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]更多詳見:http://docs.sqlalchemy.org/en/latest/dialects/index.html12345678910111213使用 Engine/ConnectionPooling/Dialect 進行數據庫操作,Engine使用ConnectionPooling連接數據庫,然后再通過Dialect執行SQL語句。
from sqlalchemy import create_engineimport datetimet=datetime.datetime.now().strftime('%Y-%m-%d')engine=create_engine("mysql+mysqldb://root:123456@localhost:3306/notes",max_overflow=5,echo=True) #最多5個是連接查詢,可以查看執行sql語句#單個插入engine.execute("insert into stu (name,age,register_date) values('t1',33,%s)",t)#或者engine.execute("insert into stu (name,age,register_date) values(%(name)s,%(age)s,%(date)s)",name='t2',age=31,date=t)#批量插入engine.execute("insert into stu (name,age,register_date) values(%s,%s,%s)",(('c1',33,t),('c2',43,t)))#查詢result=engine.execute("select * from stu")print result.fetchall()1234567891011121314151617181920ORM功能使用
創建表
使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 所有組件對數據進行操作。根據類創建對象,對象轉換成SQL,執行SQL
from sqlalchemy import create_engine,Table,Column,Integer,String,MetaData,ForeignKeymetadata=MetaData() #創建一個元數據對象,就是用來描述數據的數據,就跟字典里的詞一樣#接下來我們來創建兩個表user=Table( 'user',metadata, Column('id',Integer,primary_key=True), #默認自動加1 Column('name',String(20)))colo=Table( 'color',metadata, Column('id',Integer,primary_key=True), Column('name',String(20)))engine=create_engine("mysql+mysqldb://root:123456@localhost:3306/notes",max_overflow=5)#創建metadata.create_all(engine)#metadata.clear()#metadata.remove()123456789101112131415161718192021222324創建結果
mysql> desc user;+-------+-------------+------+-----+---------+----------------+| Field | Type | Null | Key | Default | Extra |+-------+-------------+------+-----+---------+----------------+| id | int(11) | NO | PRI | NULL | auto_increment || name | varchar(20) | YES | | NULL | |+-------+-------------+------+-----+---------+----------------+2 rows in set (0.00 sec)mysql> desc color;+-------+-------------+------+-----+---------+----------------+| Field | Type | Null | Key | Default | Extra |+-------+-------------+------+-----+---------+----------------+| id | int(11) | NO | PRI | NULL | auto_increment || name | varchar(20) | YES | | NULL | |+-------+-------------+------+-----+---------+----------------+2 rows in set (0.00 sec)1234567891011121314151617增刪查改
代碼前部分
from sqlalchemy import create_engine,Table,Column,Integer,String,MetaData,ForeignKeymetadata=MetaData() #創建一個元數據對象,就是用來描述數據的數據,就跟字典里的詞一樣#接下來連接數據庫user=Table( 'user',metadata, Column('id',Integer,primary_key=True), #默認自動加1 Column('name',String(20)))colo=Table( 'color',metadata, Column('id',Integer,primary_key=True), Column('name',String(20)))engine=create_engine("mysql+mysqldb://root:123456@localhost:3306/notes",max_overflow=5)con=engine.connect()1234567891011121314151617181920插入數據
#插入sql=user.insert().values(id=123,name='cheng')sql1=user.insert().values(id=134,name='wang')sql2=user.insert().values(id=111,name='chow')#提交執行con.excete(sql)con.execute(sql2)con.execute(sql1)mysql> select * from user;+-----+-------+| id | name |+-----+-------+| 111 | chow || 123 | cheng || 134 | wang |+-----+-------+3 rows in set (0.00 sec)1234567891011121314151617181920刪除
sql=user.delete().where(user.c.id>123)con.execute(sql)mysql> select * from user;+-----+-------+| id | name |+-----+-------+| 111 | chow || 123 | cheng |+-----+-------+1234567891011更新
sql = user.update().where(user.c.name == 'chow').values(name='ed')con.execute(sql)mysql> select * from user;+-----+-------+| id | name |+-----+-------+| 111 | ed || 123 | cheng |+-----+-------+2 rows in set (0.00 sec)1234567891011查詢
from sqlalchemy import create_engine,Table,Column,Integer,String,MetaData,ForeignKey,selectsql=select([user,])result=con.execute(sql)print result.fetchall() #[(111L, 'ed'), (123L, 'cheng')]sql1=select([user.c.name,])result=con.execute(sql1)print result.fetchall()sql=select([user.c.name,colo.c.name]).where(user.c.id==colo.c.id)result=con.execute(sql)print result.fetchall() #[('ed', 'kk')]# sql = select([user.c.name]).order_by(user.c.name)# sql = select([user]).group_by(user.c.name)#result=con.execute(sql)print result.fetchall()con.close()123456789101112131415161718192021繼承SqlORM類來操作數據庫
使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 所有組件對數據進行操作。根據類創建對象,對象轉換成SQL,執行SQL。
使用類創建表
#coding:utf-8from sqlalchemy import create_enginefrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy import String,Column,Integer,selectfrom sqlalchemy.orm import sessionmakerBase=declarative_base() #生成一個sqlORM基類,這個基類封裝了metadata這些#鏈接數據庫engine=create_engine("mysql+mysqldb://root:123456@localhost:3306/notes",echo=True) #echo可以看見創建過程#創建一個host表class Host(Base): __tablename__='host' id=Column(Integer,primary_key=True,nullable=False,autoincrement=True) hostname=Column(String(64),unique=True,nullable=True) ip_addr=Column(String(128),unique=True,nullable=True) port=Column(Integer,default=22)#創建所有表結構Base.metadata.create_all(engine)"""創建過程CREATE TABLE host ( id INTEGER NOT NULL AUTO_INCREMENT, hostname VARCHAR(64), ip_addr VARCHAR(128), port INTEGER, PRIMARY KEY (id), UNIQUE (hostname), UNIQUE (ip_addr))"""if __name__ == '__main__': #創建完成后,就可以開始使用了 SessionCls=sessionmaker(bind=engine) #創建與數據庫回話的session,注意,這里返回sessionCls是類,不是實例 session=SessionCls() #增加 # h1=Host(hostname="localhost",ip_addr="127.0.0.1") # h2=Host(hostname="ubuntu",ip_addr="192.168.2.243") # h3=Host(hostname="kali",ip_addr="172.17.135.1") # h4=Host(hostname="win32",ip_addr="10.0.0.1") #添加到session中 # session.add(h1) # session.add_all([h2,h3]) # session.add(h4) #只要沒有提交在這里也能修改, # h4.hostname="windows" # session.rollback() #如果事件沒有完成,可以在提交之前使用這個函數回滾數據庫 #提交 session.commit()建立表mysql> select * from host;+----+-----------+---------------+------+| id | hostname | ip_addr | port |+----+-----------+---------------+------+| 1 | localhost | 127.0.0.1 | 22 || 2 | ubuntu | 192.168.2.243 | 22 || 3 | kali | 172.17.135.1 | 22 || 4 | windows | 10.0.0.1 | 22 |+----+-----------+---------------+------+4 rows in set (0.00 sec)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869基本的增刪查改
刪除
session.query(Host).filter(Host.id>3).delete() #DELETE FROM host WHERE host.id > %s #提交 session.commit()"""mysql> select * from host;+----+-----------+---------------+------+| id | hostname | ip_addr | port |+----+-----------+---------------+------+| 1 | localhost | 127.0.0.1 | 22 || 2 | ubuntu | 192.168.2.243 | 22 || 3 | kali | 172.17.135.1 | 22 |+----+-----------+---------------+------+3 rows in set (0.00 sec)"""12345678910111213141516修改
session.query(Host).filter(Host.id==1).update({'ip_addr':'127.0.0.2','port':34})#UPDATE host SET ip_addr=%s, port=%s WHERE host.id = %ssession.commit()"""mysql> select * from host;+----+-----------+---------------+------+| id | hostname | ip_addr | port |+----+-----------+---------------+------+| 1 | localhost | 127.0.0.2 | 34 || 2 | ubuntu | 192.168.2.243 | 22 || 3 | kali | 172.17.135.1 | 22 |+----+-----------+---------------+------+3 rows in set (0.00 sec)"""123456789101112131415161718查詢
#查詢 ret=session.query(Host).filter_by(hostname='kali').all() #如果是查詢一條數據 #ret=session.query(Host).filter_by(hostname='kali').first() """ SELECT host.id AS host_id, host.hostname AS host_hostname, host.ip_addr AS host_ip_addr, host.port AS host_port FROM host WHERE host.hostname = %s """ for i in ret: print i.id,i.hostname,i.ip_addr #3 kali 172.17.135.1查找二:查找hostname中是localhost或者kali的行信息ret=session.query(Host).filter(Host.hostname.in_(['kali','localhost'])).all() """ SELECT host.id AS host_id, host.hostname AS host_hostname, host.ip_addr AS host_ip_addr, host.port AS host_port FROM host WHERE host.hostname IN (%s, %s) """ for i in ret: print ">>>",i.hostname,i.port ">>> localhost 34" ">>> kali 22"方式三:查詢host表根據id排序ret=session.query(Host).order_by(Host.id).all() """ SELECT host.id AS host_id, host.hostname AS host_hostname, host.ip_addr AS host_ip_addr, host.port AS host_port FROM host ORDER BY host.id """ for i in ret: print ">>>", i.hostname """ >>> localhost >>> ubuntu >>> kali """方式四:查詢Host表里根據id排序輸入0到2的字段ret = session.query(Host).order_by(Host.id)[0:2]print retfor i in ret:print(i.hostname) print(i.hostname) """ localhost ubuntu """方式五:創建Query查詢,filter是where條件,最后調用one()返回唯一行,如果調用all()則返回所有行:host = session.query(Host).filter(Host.id == 2).one() """ SELECT host.id AS host_id, host.hostname AS host_hostname, host.ip_addr AS host_ip_addr, host.port AS host_port FROM host WHERE host.id = %s """ # 打印類型和對象的name屬性: print 'name:', host.hostname #name: ubuntu12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364常見的查詢方法
- filter_by():將指定列的值作為關鍵字參數以獲取查詢結果
- filter():與filter_by()相似,不過更加靈活,還可以使用表達式。query.filter_by(userid=1)與query.filter(User.userid==1)相同
- order_by():與SQL的ORDER BY指令相似,默認情況下是升序的,需要到日sqlalchemy.desc()使其降序排列
- limit():與SQL的LIMIT指令類似
- offset():與SQL的offset指令類似
- all():返回匹配查詢的所有對象
- one():返回匹配查詢的唯一一個對象
- first():返回匹配的第一個對象
- join():按照給定的JOIN條件創建SQL JOIN對象
- update():批量更新行
- delete():批量刪除行
一個完整的例子
聲明層使用
#!/usr/bin/env python#coding:utf-8from distutils.log import warn as printffrom os.path import dirnamefrom random import randrange as randfrom sqlalchemy import Column,String,create_engine,Integer,exc,ormfrom sqlalchemy.ext.declarative import declarative_baseDBNAME='test2'NAMELEN=16FILEDS=('login','userid','projd')#定制字符串的格式tformat=lambda s:str(s).title().ljust(10)cformat=lambda s:s.upper().ljust(10)RDBMSs={'s':'sqlite','m':'mysql','g':'gadfly'}NAMES=( ('a',1232),('b',4545),('c',2343),('d',7345), ('e',3456),('f',5677),('g',6765),('h',3434), ('i',4566),('j',6755),('k',3466),('l',4544))def randName(): pick=set(NAMES) while pick: yield pick.pop()def setup(): return RDBMSs[raw_input(""" Choose a database system: (M)ysql (G)adfly (S)QLite Enter choice:""").strip().lower()[0]]DSNs={ 'mysql':'mysql+mysqldb://root:123456@localhost:3306/%s'%DBNAME, 'sqlite':'sqlite:///:memory'}Base=declarative_base()class Users(Base): #子類繼承這個Base類 __tablename__='users' #定義了映射的數據庫名,可以寫成__table__ #列屬性 login=Column(String(NAMELEN),nullable=False) userid=Column(Integer,primary_key=True,nullable=False) projid=Column(Integer) def __str__(self): return ''.join(map(tformat,(self.userid,self.login,self.projid))) #將序列中的每一個元素取出來傳入函數中,再將函數結果的返回值組成一個新的序列class SQLAlchemyTest(object): def __init__(self,dsn): try: eng=create_engine(dsn,echo=True) #創建數據庫引擎 except ImportError: #出現這個錯誤,意味著SQLalchemy不支持所選的數據庫 raise RuntimeError() try: eng.connect() #嘗試連接數據庫 except exc.OperationalError: #連接不上說明也可能不存在這個數據庫,于是我們創建這個數據庫 eng=create_engine(dirname(dsn)) # mysql+mysqldb://root:123456@localhost:3306 eng.execute('create database %s'%DBNAME).close() eng=create_engine(dsn,echo=True) #重新創建數據庫引擎 Base.metadata.create_all(eng) #創建所有表結構 Session=orm.sessionmaker(bind=eng) #創建一個會話對象,用于管理單獨的事物對象 self.ses=Session()#當涉及一個或者對個數據庫操作時,可以保證所有要寫入的數據都必須提交,然后將這個會話對象保存 #得結合使用 self.users=Users.__table__ self.eng=self.users.metadata.bind=eng #引擎與表的元數據進行額外的綁定,意味著這張表的所有操作都會綁定到這個指定的引擎中 def insert(self): self.ses.add_all( Users(login=who,userid=userid,projid=rand(1,5)) for who,userid in randName() ) self.ses.commit() def update(self): fr=rand(1,5) to=rand(1,5) i=-1 #使用query.filter_by()方法進行查找 users=self.ses.query(Users).filter_by(projid=fr).all() for i,user in enumerate(users): user.projid=to self.ses.commit() return fr,to,i+1 def delete(self): rm=rand(1,5) i=-1 users=self.ses.query(Users).filter_by(projid=rm).all() for i,user in enumerate(users): self.ses.delete(user) self.ses.commit() return rm,i+1 def dbDump(self): printf('%s'%''.join(map(cformat,FILEDS))) users=self.ses.query(Users).all() for user in users: printf(user) self.ses.commit() #授權 def __getattr__(self, item): return getattr(self.users,item) def finish(self): self.ses.connection().close()def main(): printf("***Connect to %r database"%DBNAME) db=setup() print db if db not in DSNs: printf('ERROR:%r not supported,exit'%db) return try: orm=SQLAlchemyTest(DSNs[db]) except RuntimeError: printf('ERROR:%r not supported.exit'%db) printf('***Create users trable (drop old one if appl)') orm.drop() orm.create() printf('*** Insert names into tables') orm.insert() orm.dbDump() printf('*** Move users to a random group') fr,to,num=orm.update() printf('(%d users moved) from (%d) to (%d)'%(num,fr,to)) orm.dbDump() printf('*** Randomly delete group') rm,num=orm.delete() printf('(group #%d; %d users removed)'%(rm,num)) orm.dbDump() printf('***Drop users table') orm.drop() printf('***Close cxns') orm.finish()if __name__ == '__main__': main()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163顯式使用
#! /usr/bin/env python#coding:utf-8from distutils.log import warn as printffrom random import randrange as randfrom sqlalchemy import Column,String,Integer,create_engine,orm,exc,MetaData,Tablefrom os.path import dirnameDBNAME='orm_test2'NAMELEN=16FILEDS=('login','userid','projd')#定制字符串的格式tformat=lambda s:str(s).title().ljust(10)cformat=lambda s:s.upper().ljust(10)RDBMSs={'s':'sqlite','m':'mysql','g':'gadfly'}NAMES=( ('a',1232),('b',4545),('c',2343),('d',7345), ('e',3456),('f',5677),('g',6765),('h',3434), ('i',4566),('j',6755),('k',3466),('l',4544))def randName(): pick=set(NAMES) while pick: yield pick.pop()def setup(): return RDBMSs[raw_input(""" Choose a database system: (M)ysql (G)adfly (S)QLite Enter choice:""").strip().lower()[0]]DSNs={ 'mysql':'mysql+mysqldb://root:123456@localhost:3306/%s'%DBNAME, 'sqlite':'sqlite:///:memory'}class SQLAlchemyTest(object): def __init__(self,dsn): try: eng=create_engine(dsn) except ImportError: raise RuntimeError() try: con=eng.connect() except exc.OperationalError: try: eng=create_engine(dirname(dsn)) eng.execute('create database %s charset "utf8"'%DBNAME).close() eng=create_engine(dsn) con=eng.connect() except exc.OperationalError: raise RuntimeError() metabase=MetaData() self.eng=metabase.bind=eng try: users=Table('users',metabase,autoload=True) #是否存在這個表,存在就自動加載,否則拋出異常,重新創建這個表 except exc.NoSuchTableError: users=Table( 'users',metabase, Column('login',String(NAMELEN)), Column('userid',Integer), Column('projid',Integer), ) self.con=con self.users=users def insert(self): d=[dict(zip(FILEDS,[who,uid,rand(1,5)])) for who,uid in randName()] return self.users.insert().execute(*d).rowcount def update(self): users=self.users fr=rand(1,5) to=rand(1,5) return (fr,to, users.update(users.c.projid==fr).execute(projid=to).rowcount) def delete(self): users=self.users rm=rand(1,5) return (rm,users.delete(users.c.projid==rm).execute().rowcount) def dbDump(self): printf('%s'%''.join(map(cformat,FILEDS))) users=self.users.select().execute() for user in users.fetchall(): printf(''.join(map(tformat,(user.login,user.userid,user.projid)))) def __getattr__(self, item): return getattr(self.users,item) def finish(self): self.con.close()def main(): printf('***Connect to %r database'%DBNAME) db=setup() if db not in DSNs: printf('ERROR:%r not supported.exit'%db) return try: orm=SQLAlchemyTest(DSNs[db]) except RuntimeError: printf('ERROR:%r not supported.exit'%db) return printf('***Create users table (drop old one if appl.)') orm.drop(checkfirst=True) orm.create() printf('***Insert name into table') orm.insert() orm.dbDump() printf('***Move users to a random group') fr,to,num=orm.update() printf('(%d users moved) from (%d) to (%d)'%(num,fr,to)) orm.dbDump() printf('***Randomly delete group') rm,num=orm.delete() printf('(group #%d; %d users removed'%(rm,num)) orm.dbDump() printf('***Drop users table') orm.drop() printf('***Close con') orm.finish()if __name__ == '__main__': main()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151MongoDB
他是介于簡單的鍵-值對存儲(如redis,Voldemort,Amazon Dynamo等)與列存儲之間,他有點像關系數據庫的無模式衍生品,比基于列的存儲更簡單,約束更少,但是比普通的鍵值對存儲更加靈活,一般情況下其數據會另存為JSON對象,并且允許諸如字符串,數值,列表設置嵌套等數據類型。
盡管python中有很多MongoDB驅動程序,不過最正式的是PyMongo。
ubuntu安裝:
sudo apt-get install mongodb1啟動
cmustard@cmustard:/var$ mongoMongoDB shell version: 2.6.10connecting to: testWelcome to the MongoDB shell.For interactive help, type "help".For more comprehensive documentation, see http://docs.mongodb.org/Questions? Try the support group http://groups.google.com/group/mongodb-user> lsfunction ls() { [native code] }> show dbsadmin (empty)local 0.078GB> use testswitched to db test> show dbsadmin (empty)local 0.078GBtest (empty)> db.post.insert({'Title':'Test','Name':'cmustard'})WriteResult({ "nInserted" : 1 })> db.post.findOne(){ "_id" : ObjectId("580ef9c273a1b01482410a74"), "Title" : "Test", "Name" : "cmustard"}bye1234567891011121314151617181920212223242526272829幫助
> help db.help() help on db methods db.mycoll.help() help on collection methods sh.help() sharding helpers rs.help() replica set helpers help admin administrative help help connect connecting to a db help help keys key shortcuts help misc misc things to know help mr mapreduce show dbs show database names show collections show collections in current database show users show users in current database show profile show most recent system.profile entries with time >= 1ms show logs show the accessible logger names show log [name] prints out the last segment of log in memory, 'global' is default use set current database db.foo.find() list objects in collection foo db.foo.find( { a : 1 } ) list objects in foo where a == 1 it result of the last line evaluated; use to further iterate DBQuery.shellBatchSize = x set default number of items to display on shell exit quit the mongo shell123456789101112131415161718192021222324代碼實例
#!/usr/bin/python#coding:utf-8from distutils.log import warn as printffrom random import randrange as randimport pymongofrom pymongo import errorsDBNAME='mongo_test'NAMELEN=16FILEDS=('login','userid','projid')NAMES=( ('a',1232),('b',4545),('c',2343),('d',7345), ('e',3456),('f',5677),('g',6765),('h',3434), ('i',4566),('j',6755),('k',3466),('l',4544))#定制字符串的格式tformat=lambda s:str(s).title().ljust(10)cformat=lambda s:s.upper().ljust(10)def randName(): pick=set(NAMES) while pick: yield pick.pop()COLLECTION='users' #集合的名字class MongoTest(object): def __init__(self): try: con=pymongo.MongoClient() #鏈接mongoDB數據庫 except errors.AutoReconnect: raise RuntimeError() self.con=con self.db=con[DBNAME] #連接數據庫mongo_test self.users=self.db[COLLECTION] def insert(self): self.users.insert( dict(login=who,userid=uid,projid=rand(1,5)) for who,uid in randName() ) def update(self): fr=rand(1,5) to=rand(1,5) i=-1 for i,user in enumerate(self.users.find({'projid':fr})): #集合的find方法將查詢條件傳進去 self.users.update(user,{'$set':{'projid':to}}) #$set指令可以顯式的修改已經存在的值 return fr,to,i+1 def delete(self): rm=rand(1,5) i=-1 for i ,user in enumerate(self.users.find({'projid':rm})): self.users.remove(user) #找到之后執行remove刪除操作 return rm,i+1 def dbDump(self): printf('%s' %''.join(map(cformat,FILEDS))) for user in self.users.find(): printf(''.join(map(tformat,(user[k] for k in FILEDS)))) def finish(self): self.con.close() #關閉數據庫 #授權 def __getattr__(self, item): return getattr(self.con,item)def main(): printf('***Connect to %r database'%DBNAME) try: mongo=MongoTest() except RuntimeError: printf('ERROR:MongoDB server unreachable,exit') return printf('***Insert names into table') mongo.insert() mongo.dbDump() printf('***Move users to a random group') fr,to,num=mongo.update() printf('(%d users moved) from (%d) to (%d) '%(num,fr,to)) mongo.dbDump() printf('*** Randomly delete group') rm,num=mongo.delete() printf('(group #%d; %d users removed) '%(rm,num)) mongo.dbDump() printf('***Drop users table') mongo.drop_database(DBNAME) printf('***Close conn') mongo.finish()if __name__ == '__main__': main()總結
以上是生活随笔為你收集整理的python用另一个字段替代本字段的null_Python中的数据库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 燃气热水器暗管怎么留(华润燃气欢迎您)
- 下一篇: python中random中unifor