Basado en la plataforma de análisis de datos Pandas, ¿se debe utilizar el ORM de SqlAlchemy para la conexión de datos?
Primer uso:
desde sqlalchemy import create_engine
desde sqlalchemy.orm import sessionmaker
DB_CONNECT_STRING = 'mysql mysqldb:// root : 123@localhost/ooxx?charset=utf8'
motor = create_engine(DB_CONNECT_STRING, echo=True)
DB_Session = sessionmaker(bind=motor)
create_engine() Devuelve el parámetro de eco del motor de la base de datos True para mostrar cada instrucción SQL ejecutada y el entorno está cerrado
sessionmaker() La conexión de la base de datos de la instancia de la clase de base de datos registra algunos datos de la consulta y decide ejecutar SQL La declaración se inicializa mediante el grupo de conexiones de base de datos automantenido de SQLAlchemy (5 conexiones predeterminadas) y la inicialización BaseHandler inicialize() de Tornado:
clase BaseHandler(tornado.web.RequestHandler):
def inicializar (self):
self.session = models.DB_Session()
def on_finish(self):
self.session.close()
El servidor web dijo que usar sqlalchemy.orm.scoped_session puede garantizar que cada subproceso obtenga una sesión, pero el propio Tornado puede causar problemas al usar un solo subproceso asincrónico y no lo usa
Usar la sesión para ejecutar SQL: p>
session.execute('crear base de datos abc')
imprimir sesión.execute('mostrar bases de datos').fetchall()
session.execute('use abc ')
# Crear tabla de usuarios brevemente
imprimir session.execute('select * del usuario donde id = 1').first()
print session.execute('select * from user where id = :id', {'id': 1}).first()
No hay diferencia si usas MySQL -Python directamente; el método ORM usa SQLAlchemy Weiyuan
En la tabla de definición:
de sqlalchemy import Column
de sqlalchem;
y.types importa CHAR, Entero, Cadena
desde sqlalchemy.ext.declarative import declarative_base
BaseModel = declarative_base()
def init_db(): p>
p>
BaseModel.metadata.create_all(motor)
def drop_db():
BaseModel.metadata.drop_all(motor)
clase Usuario( Modelo Base):
__tablename__ = 'usuario'
id = Columna(Entero, clave_primaria=Verdadero)
nombre = Columna(CHAR( 30)) # o Column(String(30))
init_db()
declarative_base() crea una clase BaseModel y la asocia con la tabla
Usuario clase ejemplo__tablename__ atributo base de datos El nombre de la tabla tiene dos campos y es un número entero de 30 caracteres. Explicaré algunos de sus parámetros.
BaseModel.metadata.create_all(motor) encuentra la clase BaseModel y la crea. algunas tablas en la base de datos; drop_all() elimina alguna tabla
Luego comienza a usar la tabla:
de sqlalchemy import func, or_, not_
usuario = Usuario (nombre='a')
sesión.add(usuario)
usuario = Usuario(nombre='b')
sesión.add(usuario)
usuario = Usuario( nombre='a')
sesión.add(usuario)
usuario = Usuario()
sesión .add(usuario)
session.commit()
consulta = session.query(Usuario)
imprimir consulta # Mostrar sentencia SQL
imprimir consulta.declaración # Igual que
para el usuario en la consulta: # Consulta transversal
imprimir usuario.nombre
imprimir consulta.all() # Retornar imagen de lista similar
imprimir consulta .first().name # Guardar el primer registro() y devolver Ninguno
# imprimir consulta.one().name # Guardar o registrar en fila y tirar excepción
print query.filter(User .id == 2).first().name
print query.get(2).name #Obtener la clave principal equivale a la oración
imprimir query.filter('id = 2').first().name # Soporta cadenas
query2 = session.query(User.name)
imprimir
query2.all() # Tupla por línea
imprimir query2.limit(1).all() # Devolver 1 registro
imprimir query2.offset(1).all() # Se devuelve el segundo registro
print query2.order_by(User.name).all()
print query2.order_by('name').all() p>
imprimir consulta2.order_by(User.name.desc()).all()
imprimir consulta2.order_by('nombre desc').all()
imprimir sesión. query(User.id).order_by(User.name.desc(), User.id).all()
imprimir consulta2.filter(User.id == 1).scalar() #Registro el elemento del registro devuelto
print session.query('id').select_from(User).filter('id = 1').scalar()
print query2. filter(User.id gt; 1, User.name != 'a').scalar() # and
query3 = query2.filter(User.id gt; 1) # Empalmar filtros y p>
consulta3 = consulta3.filter(Usuario.nombre!= 'a')
imprimir consulta3.scalar()
imprimir consulta2.filtro(o_( Usuario.id == 1, User.id == 2)).all() # o
imprimir consulta2.filter(User.id.in_((1, 2))).all() # en
consulta4 = sesión.consulta(Usuario.id)
imprimir consulta4.filtro(Usuario.nombre == Ninguno).scalar()
imprimir consulta4.filtro ('el nombre es nulo').scalar()
imprimir consulta4.filter(not_(User.name == Ninguno)).all() # no
imprimir consulta4.filter (Usuario.nombre!= Ninguno).all()
imprimir consulta4.count()
imprimir sesión.query(func.count('*')). ).scalar()
imprimir sesión.query(func.count('1')).select_from(Usuario).scalar()
imprimir sesión.query( func.count (User.id)).scalar()
imprimir sesión.query(func.count('*')).filter(User.id gt; 0).scalar
() # filter() contiene Usuario y necesita especificar la tabla
print session.query(func.count('*')).filter(User.name == 'a').limit( 1). escalar() == 1 # Utilice limit() para limitar el retorno del recuento()
print session.query(func.sum(User.id)).scalar()
print session.query(func.now()).scalar() # func seguido de cualquier nombre de función debe ser compatible con la base de datos
print session.query(func.current_timestamp()).scalar ()
imprimir sesión.query(func.md5(Usuario.nombre)).filter(Usuario.id == 1).scalar()
query.filter(Usuario. id == 1). actualizar({Usuario.nombre: 'c'})
usuario = query.get(1)
imprimir usuario.nombre
user.name = ' d'
session.flush() # Escribir en la base de datos y enviar
imprimir query.get(1).name
session.delete(usuario)
session.delete(usuario)
p>
session.flush()
imprimir consulta.get(1)
sesión.rollback()
imprimir consulta.get(1) .nombre
query.filter(User.id == 1).delete()
session.commit()
print query.get(1)
2. Conocimientos avanzados
1) Cómo insertar lotes datos en lotes
Utilice un método que no sea ORM:
session.execute(
User.__table__.insert(),
[ {'nombre': `randint(1, 100)`, 'edad': randint(1, 100)} para i en xrange(10000)]
)
sesión. commit()
Cómo insertar datos por lotes en lotes
Usar un método que no sea ORM:
session.execute(
User. __table__.insert(),
[{'nombre': `randint(1, 100)`, 'edad': randint(1, 100)} para i en xrange(10000)]
)
session.commit()
Insertar 10,000 registros en lotes Completado en segundos; el estilo ORM lleva tiempo
2) Cómo agregar un prefijo a la declaración SQL ejecutada
Utilice consultas como prefix_with():
session.query (User.name).prefix_with('HIGH_PRIORITY').all()
sesión
.execute(User.__table__.insert().prefix_with('IGNORE'), {'id': 1, 'name': '1'})
3) Cómo reemplazar el registro de clave principal p>
Utilice session.merge() en lugar de session.add() De hecho, SELECCIONE ACTUALIZACIÓN:
usuario = Usuario(id=1, nombre='ooxx')
session .merge(user)
session.commit()
O usar MySQL INSERT... EN LA ACTUALIZACIÓN DE CLAVE DUPLICADA necesita usar el decorador @compiles. un poco difícil de entender Eche un vistazo a: "SQLAlchemy ON DUPLICATE" KEY UPDATE》 sqlalchemy_mysql_ext
4) Cómo usar enteros con signo
Usando MySQL:
. de sqlalchemy.dialects.mysql import INTEGER
id = Column(INTEGER(unsigned=True), Primary_key=True)
5) El nombre del atributo del modelo requiere administración del nombre del campo de la tabla p>
Encontré un requisito extraño: la tabla del sistema contiene el campo from. Las palabras clave de Python pueden procesarse:
from_ = Column('from', CHAR(10))
6) Cómo obtener el grado de campo
Imaginación compleja de columnas Es problemático obtener User.name Ejemplo:
User.name.property.columns[0].type. longitud
7) Cómo especificar el uso de codificación InnoDB y UTF-8
La modificación simple de la configuración de la base de datos predeterminada requiere la especificación del código:
clase Usuario( BaseModel):
__table_args__ = {
'mysql_engine' : 'InnoDB',
'mysql_charset': 'utf8'
}
MySQL 5.5 comienza a soportar el almacenamiento de caracteres codificados UTF-8 de 4 bytes que vienen con iOS emoji (carácter?) pertenece a la especie
Código de superficie de configuración de tabla cambio utf8 cambio de conjunto de caracteres utf8mb4DB_CONNECT_STRING
La configuración de biblioteca o campo son sentencias SQL escritas por usted mismo. Para obtener más información, consulte "Cómo admitir Unicode completo" en bases de datos MySQL》
Se recomienda utilizar utf8mb4 en lugar de. utf8. El primero es más lento y el índice ocupa más espacio
8) Cómo establecer restricciones de clave externa
desde randint de importación aleatoria
desde sqlalchemy import ForeignKey
clase Usuario(BaseModel):
__tablename__ = 'usuario'
id = Columna(Entero, clave_primaria= Verdadero)
edad = Columna(Entero)
clase Amistad(ModeloBase):
>__tablename__ = 'amistad'
id = Columna(Entero, clave_primaria=Verdadero)
user_id1 = Columna(Entero, ForeignKey('usuario.id'))
user_id2 = Columna(Integer, ForeignKey('user.id'))
para i en xrange(100):
session.add(User(age=randint(1 , 100)))
session.flush() # o session.commit() se ejecuta antes de acceder al atributo de identificación de la imagen del usuario (la identificación se incrementa)
para i en xrange (100):
session.add(Amistad(user_id1=randint(1, 100), user_id2=randint(1, 100)))
session.commit() p>
session.query(User).filter(User.age lt; 50).delete()
Debe ocurrir un error al ejecutar el código:
sqlalchemy. exc.IntegrityError: (IntegrityError) (1451, 'No se puede eliminar o actualizar una fila principal: falla una restricción de clave externa (`ooxx`.`friendship`, CONSTRAINT `friendship_ibfk_1` CLAVE EXTRANJERA (`user_id1`) REFERENCIAS `usuario` (` id`)) ') 'DELETE FROM user WHERE user.age lt; (50,) La eliminación original de los datos de la tabla de usuario puede hacer que la clave externa de amistad apunte al registro almacenado real. De forma predeterminada, MySQL rechaza esta operación. RESTRICTInnoDB permite especificar ON DELETE CASCADE SET NULL. El primero elimina el efecto de amistad. Las claves externas de algunos registros de la grabadora se establecen en NULL.
Excepto que la eliminación puede cambiar la clave principal, lo que hace que la clave externa de amistad. deja de ser válido en el ON UPDATE correspondiente y su cambio en CASCADA para actualizar la clave externa correspondiente y eliminarla
Procesamiento de SQLAlchemy:
clase Friendship(BaseModel):
__tablename__ = 'amistad'
id = Columna(Entero, clave_primaria=Verdadero)
user_id1 = Columna( Entero, ForeignKey('usuario.id', ondelete='CASCADE', onupdate ='CASCADE'))
user_id2 = Column(Integer, ForeignKey('user.id', ondelete='CASCADE', onupdate='CASCADE'))
9) Cómo para conectar la tabla
desde sqlalchemy importar distinta
<p>de sqlalchemy.orm importar aliased
Amigo = aliased(Usuario, nombre='Amigo')
imprimir session.query(User.id).join(Amistad, Usuario. id == Friendship.user_id1).all() # Todos los usuarios amigos
imprimir session.query(distinct(User.id)).join(Friendship, User.id == Friendship.user_id1).all () # Todos los usuarios amigos (eliminar duplicados)
imprimir session.query(User.id).join(Friendship, User.id == Friendship.user_id1).distinct().all() # Igual as
print session.query(Friendship.user_id2).join(User, User.id == Friendship.user_id1).order_by(Friendship.user_id2).distinct().all() # Diferentes usuarios amigos
imprimir session.query(Friendship.user_id2).select_from(User).join(Friendship, User.id == Friendship.user_id1).order_by(Friendship.user_id2).distinct().all() # Igual que unirse pero opuesto al orden autoseleccionado de MySQL de STRAIGHT_JOIN
print session.query(User.id, Friendship.user_id2).join(Friendship, User.id == Friendship.user_id1). all() # Usuarios y sus amigos
print session.query(User.id, Friendship.user_id2).join(Friendship, User.id == Friendship.user_id1).filter(User.id lt; 10).all () # id en 10 usuarios y sus amigos
print session.query(User.id, Friend.id).join(Friendship, User.id == Friendship.user_id1).join (Friend, Friend .id == Friendship.user_id2).all() # Las dos uniones requieren alias porque usan la misma tabla
print session.query(User.id, Friendship.user_id2).outerjoin (Friendship, User.id = = Friendship.user_id1).all() # Usuario y sus amigos (Ninguno para amigos, use la unión izquierda)
-
-