久しぶりにQiitaを開いたら、半年前にちまちま作ってたこの記事を発見しました。
供養のために公開します。
CREATE TABLE(テーブル作成)
最もシンプルな例
sqlalchemy
from sqlalchemy import create_engine, String, Integer
from sqlalchemy.orm import declarative_base
from sqlalchemy.schema import Column
# 接続設定
engine = create_engine("sqlite:///:memory:")
Base = declarative_base()
class User(Base):
# テーブル名
__tablename__ = "users"
# カラムの設定
user_id = Column(String(255), primary_key=True)
name = Column(String(255))
age = Column(Integer)
# 全テーブル一括作成
Base.metadata.create_all(engine)
発行されるSQL
CREATE TABLE users (
user_id VARCHAR(255),
name VARCHAR(255),
age INTEGER,
PRIMARY KEY (user_id)
)
ただしColumnを使う方法だとMypyの型チェックに引っかかってしまいます。
それが気になる場合はMappedが使えます。
sqlalchemy
from sqlalchemy import String, Integer
from sqlalchemy.orm import Mapped, mapped_column
class User(Base):
# テーブル名
__tablename__ = "users"
# カラムの設定
user_id: Mapped[str] = mapped_column(String(255), primary_key=True)
name: Mapped[str] = mapped_column(String(255))
age:Mapped[int] = mapped_column()
追加情報を加えない場合はage:Mapped[int] = mapped_column()のように型クラスの記載を省略できます。
AUTO INCREMENT(自動採番)
主キーがINTEGER型の場合はAUTO_INCREMENTが適用されます。数字は1から追加されていきます。
sqlalchemy
class User(Base):
# テーブル名
__tablename__ = "users"
# カラムの設定
user_id = Column(Integer, primary_key=True)
name = Column(String(255))
age = Column(Integer)
# 全テーブル一括作成
Base.metadata.create_all(engine)
発行されるSQL
CREATE TABLE users (
user_id INTEGER NOT NULL AUTO_INCREMENT,
name VARCHAR(255),
age INTEGER,
PRIMARY KEY (user_id)
)
DEFAULT値の指定
sqlalchemy
class User(Base):
__tablename__ = "users"
user_id = Column(String(255), primary_key=True, default="default_id")
name = Column(String(255), default="default_name")
age = Column(Integer, default=0)
# 全テーブル一括作成
Base.metadata.create_all(engine)
発行されるSQL
CREATE TABLE users (
user_id VARCHAR(255) DEFAULT 'default_id',
name VARCHAR(255) DEFAULT 'default_name',
age INTEGER DEFAULT 0,
PRIMARY KEY (user_id)
)
NOT NULLの指定
sqlalchemy
class User(Base):
__tablename__ = "users"
user_id = Column(String(255), primary_key=True, nullable=False)
name = Column(String(255), nullable=False)
age = Column(Integer, nullable=False)
# 全テーブル一括作成
Base.metadata.create_all(engine)
発行されるSQL
CREATE TABLE users (
user_id VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
age INTEGER NOT NULL,
PRIMARY KEY (user_id)
)
CHECK(カラムの制約)
数値型にしか使えません。
sqlalchemy
from sqlalchemy import CheckConstraint
class User(Base):
__tablename__ = "users"
user_id = Column(String(255), primary_key=True)
name = Column(String(255))
age = Column(Integer, CheckConstraint("age >= 0"))
number_of_pets = Column(Integer, CheckConstraint("number_of_pets >= 0"))
CheckConstraint(age > number_of_pets)
# 全テーブル一括作成
Base.metadata.create_all(engine)
発行されるSQL
CREATE TABLE users (
user_id VARCHAR(255),
name VARCHAR(255),
age INTEGER CHECK(age >= 0),
number_of_pets INTEGER CHECK(number_of_pets >= 0)
PRIMARY KEY (user_id)
CONSTRAINT CHECK (age > number_of_pets)
)
UNIQUE(重複制限)
sqlalchemy
class User(Base):
__tablename__ = "users"
user_id = Column(String(255), primary_key=True, unique=True)
name = Column(String(255))
age = Column(Integer)
# 全テーブル一括作成
Base.metadata.create_all(engine)
発行されるSQL
CREATE TABLE users (
user_id VARCHAR(255) UNIQUE,
name VARCHAR(255),
age INTEGER,
PRIMARY KEY (user_id)
)
複合主キー
sqlalchemy
class User(Base):
__tablename__ = "users"
user_id = Column(String(255), primary_key=True)
name = Column(String(255), primary_key=True)
age = Column(Integer)
# 全テーブル一括作成
Base.metadata.create_all(engine)
発行されるSQL
CREATE TABLE users (
user_id VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
age INTEGER,
PRIMARY KEY (user_id, name)
)
FOREIGN KEY(外部キー)
sqliteはデフォルトでは外部キーを使用することはできません。ForeignKeyを指定したSQLを発行することはできますが、INSERT時に外部キー制約は無視されます。
sqlalchemy
class Sex(Base):
__tablename__ = "sex"
id = Column(Integer, primary_key=True)
sex = Column(String(6))
class User(Base):
__tablename__ = "users"
user_id = Column(String(255), primary_key=True)
name = Column(String(255))
age = Column(Integer)
sex = Column(Integer, ForeignKey("sex.id"))
# 全テーブル一括作成
Base.metadata.create_all(engine)
発行されるSQL
CREATE TABLE sex (
id INTEGER NOT NULL AUTO_INCREMENT,
sex VARCHAR(6),
PRIMARY KEY (id)
)
CREATE TABLE users (
user_id VARCHAR(255) NOT NULL,
name VARCHAR(255),
age INTEGER,
sex INTEGER,
PRIMARY KEY (user_id),
FOREIGN KEY(sex) REFERENCES sex (id)
)
ALTER TABLE(テーブル更新)
SQLAlchemyにはALTER TABLEに相当する構文はない(全くないわけではないが、もはやORMの書き方ではないため省略)。
DROP TABLE(テーブル削除)
sqlalchemy
Base.metadata.drop_all(engine)
発行されるSQL
DROP TABLE users
INSERT(挿入)
最もシンプルな例
sqlalchemy
user = User(user_id="test_id", name="test_name", age=30)
session.add(user)
session.commit()
発行されるSQL
INSERT INTO users
(user_id, user_name, age)
VALUES('test_id', 'test_name', 30)
SELECT(検索)
全件取得
sqlalchemy
users = session.query.(User).all()
発行されるSQL
SELECT users.user_id AS users_user_id, users.name AS users_name, users.age AS users_age
FROM users
WHERE(検索条件)
完全一致するレコードを全件取得
sqlalchemy
users = session.query.(User).where(User.user_id == "test_id_1").all()
発行されるSQL
SELECT users.user_id AS users_user_id, users.name AS users_name, users.age AS users_age
FROM users
WHERE users.user_id = 'user_id_1'
完全一致するレコードの最初の要素を取得
sqlalchemy
users = session.query.(User).where(User.user_id == "test_id_1").first()
発行されるSQL
SELECT users.user_id AS users_user_id, users.name AS users_name, users.age AS users_age
FROM users
WHERE users.user_id = 'user_id_1'
LIMIT 1
LIKE演算子(部分一致)
sqlalchemy
users = session.query(User).where(User.user_id.contains("test")).all()
発行されるSQL
SELECT users.user_id AS users_user_id, users.name AS users_name, users.age AS users_age
FROM users
WHERE (users.user_id LIKE concat('%', 'test', '%'))
LIKE演算子(前方一致)
sqlalchemy
users = session.query(User).where(User.user_id.startswith("test")).all()
発行されるSQL
SELECT users.user_id AS users_user_id, users.name AS users_name, users.age AS users_age
FROM users
WHERE (users.user_id LIKE concat('test', '%'))
LIKE演算子(後方一致)
sqlalchemy
users = session.query(User).where(User.user_id.endswith("test")).all()
発行されるSQL
SELECT users.user_id AS users_user_id, users.name AS users_name, users.age AS users_age
FROM users
WHERE (users.user_id LIKE concat('%', 'test'))
BETWEEN演算子(範囲検索)
sqlalchemy
users = session.query(User).where(User.age.between(20, 35)).all()
発行されるSQL
SELECT users.user_id AS users_user_id, users.name AS users_name, users.age AS users_age
FROM users
WHERE users.age BETWEEN 20 AND 35
IN演算子(複数値との比較)
sqlalchemy
users = session.query(User).where(User.age.in_([20, 35])).all()
発行されるSQL
SELECT users.user_id AS users_user_id, users.name AS users_name, users.age AS users_age
FROM users
WHERE users.age IN 20, 35