-
[1] 리스트와 스칼라 반환하기
query 객체의 all,one,first 메서드를 이용하여 non-iterator값을 반환한다.
1.first는 list를 반환한다.
query=session.query(User).filter(User.name.like('%air')).order_by(User.id)
query.all()
2.first는 첫번째 값만 scalar로 가져온다.
query.first()
3.one은 모든 행을참조하여 식별자를 값으로 가지지않거나 중복행이 있는 경우 에러생성
from sqlalchemy.orm.exc import MultipleResultsFound try: user = query.one() except MultipleResultsFound, e: print e from sqlalchemy.orm.exc import NoResultFound try: user = query.filter(User.id == 99).one() except NoResultFound, e: print e
[2] 문자로 sql을 사용할 수있음
-예를들어 filter()와 orfer_by()를 사용하는 구문에서 filter("id<224") order_by("id") 이렇게 사용 할 수 있다.
-콜론을 이용하여 매핑을 이용할 수 있다.
filter("id<:value and name=:name").params(value=1234,name="wee")
-stmt
from_statemnet("select * from users where name=:name").params(name="wee")
[3] .count()로 숫자를 카운팅할 수있다.
-session.query(User).filter(User.name.like('haru%')).count()
-func.count(User.name) 로 함수안에 컬럼을 지정할 수있다.
-pk로 카운트를 하면 select from이 필요없다
[4]관계 만들기 http://weejw.tistory.com/84 <-다시공부해봤다..이해도 부족
-테이블 설계시 바로 관계를 정의
user_id = Column(Integer, ForeignKey('users.id'))
user = relationship("User", backref=backref('addresses', order_by=id))
class Address(Base): ... __tablename__ = 'addresses' ... id = Column(Integer, primary_key=True) ... email_address = Column(String, nullable=False) ... user_id = Column(Integer, ForeignKey('users.id')) ... ... user = relationship("User", back_populates="addresses")
-backref , back_populates는 역으로도 참조가 가능하도록 함
-'addresses'처럼 문자열로 선언하는 이유는 선언되지 않은 클래스에 대한 오류때문
-외래키 컬럼은 자동으로 cascade
-관계가 맺어졌을때 는 객체에서 클래스를 참조하면 된다.
(ex. user와 address사이의 관계가 있을 때 wee=user("wee") 라는 객체생성시 wee.address로 address테이블 참조
[5]join과 함께 쿼리하기
-filter를 이용하여 join을 할 수 있다.
for u, a in session.query(User, Address).\ filter(User.id==Address.user_id).\ filter(Address.email_address=='jack@gmail.com')
-query.join()을 이용할 수 있다. (외래키 기준으로 join)
session.query(User).join(Address).\ filter(Address.email_address=='jack@gmail.com')
만약 외래키가 없다면 아래와같이 명시해줘야한다.
query.join(Address, User.id==Address.user_id) query.join(User.addresses) query.join(Address, User.addresses) query.join('addresses')
-outer join은 outerjoin()으로 하면된다.
query.outerjoin(User.addresses)
[6] 별칭 사용하기
-aliased()를 이용한다.
from sqlalchemy.orm import aliased adalias1 = aliased(Address) adalias2 = aliased(Address)
[7] 서브쿼리의 이용
- 아래와 같은쿼리를 alchemay로 변경할 수있다.
SELECT users.*, adr_count.address_count
FROM users LEFT OUTER JOIN ( SELECT user_id, count(*) AS address_count FROM addresses GROUP BY user_id ) AS adr_count ON users.id = adr_count.user_id
변경후
from sqlalchemy.sql import func stmt = session.query(Address.user_id, func.count('*').label('address_count')).\ group_by(Address.user_id).subquery()
for u, count in session.query(User, stmt.c.address_count).\ outerjoin(stmt, User.id==stmt.c.user_id).order_by(User.id): print u, count
이때 서브쿼리로 가져온걸 컬럼으로 이용해서 사용할 수 있다. aliased로 별칭을 지정해 이용
stmt = session.query(Address).\ filter(Address.email_address != 'jack@yahoo.com').\ subquery() adalias = aliased(Address, stmt) for user, address in session.query(User, adalias).\ join(adalias, User.addresses): print user, address
[8] exists 이용
from sqlalchemy.sql import exists stmt = exists().where(Address.user_id==User.id)
[9]any 이용
특정기준을 주어 제한적 매칭을 가능케함
filter(User.addresses.any(Address.email_address.like('%gmail%'))):
has도 동일한기능을 한다. (대신 다대일관계에서 사용)filter(~Address.user.has(User.name=='jack')).all()[10]contains 이용
query.filter(User.addresses.contains(someaddress))
[11] 선행로딩
lazy loading의 반대로 user.addresses 일경우 , addresses는 실제 adresses에 대한 쿼리가 실행될때 호출하지말고 user를 불렀을때 바로호출하도록 하는것이다. (쿼리호출의 수를 줄일 수 있다)
-서브쿼리로딩
jack = session.query(User).\ options(subqueryload(User.addresses)).\ filter_by(name='jack').one()
-연결된 로딩
from sqlalchemy.orm import joinedload jack = session.query(User).\ options(joinedload(User.addresses)).\ filter_by(name='jack').one()
joineload는 n:1의 관계에서 적합하고 subqueryload()는 관계컬렉션을 가져올때 적합.
-명시적join_선행로딩
n:1 객체를 미리 불러와 동일 객체에 필터링 할 경우 유용
jack_addresses = session.query(Address).\ join(Address.user).\ filter(User.name=='jack').\ options(contains_eager(Address.user)).\ all()
[12]삭제하기
-delete(객체)
alchemy는 제거를 종속적으로 하지 않는다.그래서 관계에서 행동자체를 변경시켜야한다.
존재하는 관계를 제거할때에는 맵핑을 완전히 새로시작해야한다.
1.session을 닫는다
session.close()
2.새로운 declarative_base() 객체를 생성한다.
Base=declarative_base()
3.User와 address 클래스를 선언한다.
class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String) fullname = Column(String) password = Column(String) addresses = relationship("Address", backref='user', cascade="all, delete, delete-orphan") def __repr__(self): return "<User('%s','%s','%s'>" % (self.name, self.fullname, self.password)
class Address(Base): __tablename__ = 'addresses' id = Column(Integer, primary_key=True) email_address = Column(String, nullable=False) user_id = Column(Integer, ForeignKey('users.id')) def __repr__(self): return "<Address('%s')>" % self.email_address
'2017년 > Database' 카테고리의 다른 글
mysql innodb table row rock에 대해 알아보자 (0) 2017.08.11 sqlite에서 지원하지 않는! 것들! (0) 2017.08.10 ggplot에 대해 알아보자 (0) 2017.08.04 R이란? 2부 (0) 2017.08.02 HBASE란? (0) 2017.07.21