概要
tengのSQL書き方は、SQL::Maker::Conditionを踏襲しているようです。
https://metacpan.org/pod/SQL::Maker::Condition
※pluginのlookupだと、使えない条件指定が多い(特に{}を使う条件)ため、その場合はsingleを使ってください。
初期化
use Teng;
use Teng::Schema::Loader;
my $teng = Teng::Schema::Loader->load(
connect_info => ['dbi:mysql:dbname=myapp', 'username', 'password'],
namespace => 'MyApp::DB',
);
基本的なCRUD操作
Create (挿入)
my $row = $teng->insert('table_name', {
column1 => 'value1',
column2 => 'value2',
});
Read (検索)
単一行の取得:
my $row = $teng->single('table_name', { id => 1 });
複数行の取得:
my @rows = $teng->search('table_name', { status => 'active' });
Update (更新)
$teng->update('table_name',
{ column1 => 'new_value' }, # 更新するカラムと値
{ id => 1 } # WHERE 条件
);
Delete (削除)
$teng->delete('table_name', { id => 1 });
高度なクエリ
IN句
my @rows = $teng->search('table_name', {
status => { 'IN' => ['active', 'pending'] }
});
LIKE句
my @rows = $teng->search('table_name', {
name => { 'LIKE' => '%John%' }
});
AND条件
# -and を使用する場合(明示的)
my @rows = $teng->search('table_name', {
-and => [
status => 'active',
age => { '>' => 18 }
]
});
# -and を省略する場合(暗黙的)
my @rows = $teng->search('table_name', {
status => 'active',
age => { '>' => 18 }
});
注: Tengでは、-andキーワードは多くの場合省略可能です。複数の条件を単純にハッシュとして列挙すると、暗黙的にAND条件として扱われます。ただし、より複雑な条件やORとの組み合わせを使用する場合は、明示的に-andを使用すると可読性が向上することがあります。
OR条件
my @rows = $teng->search('table_name', {
-or => [
status => 'active',
status => 'pending'
]
});
NOT EQUAL条件 (<>)
my @rows = $teng->search('table_name', {
status => { '!=' => 'inactive' }
});
複合条件(AND, OR, NOT EQUALの組み合わせ)
# -and を使用する場合
my @rows = $teng->search('table_name', {
-and => [
status => { '!=' => 'deleted' },
-or => [
age => { '>' => 18 },
has_parent_consent => 1
]
]
});
# トップレベルの-andを省略する場合
my @rows = $teng->search('table_name', {
status => { '!=' => 'deleted' },
-or => [
age => { '>' => 18 },
has_parent_consent => 1
]
});
この例では、statusが'deleted'ではなく、かつ(年齢が18歳より上、または親の同意がある)レコードを検索しています。トップレベルの-andは省略可能ですが、内部の-orは明示的に指定する必要があります。
ORDER BY
my @rows = $teng->search('table_name',
{ status => 'active' },
{ order_by => 'created_at DESC' }
);
LIMIT と OFFSET
my @rows = $teng->search('table_name',
{},
{ limit => 10, offset => 20 }
);
トランザクション
$teng->txn_begin;
eval {
$teng->insert('table1', { ... });
$teng->update('table2', { ... }, { ... });
$teng->txn_commit;
};
if ($@) {
$teng->txn_rollback;
}
カスタムSQLの実行
my $itr = $teng->search_by_sql(q{
SELECT * FROM table_name WHERE column1 = ? AND column2 = ?
}, ['value1', 'value2']);
スキーマ情報の取得
my $table_info = $teng->schema->get_table('table_name');
関連テーブルの取得
my $row = $teng->single('users', { id => 1 });
my $related_rows = $row->cascade_fetch('posts'); # users.id = posts.user_id の関係を想定
count
(例)
my $count = $teng->count('order_table', '*', +{import_user => $editor, is_deleted => 0, last_edit_at => undef});
between
(例)
my $iter = $teng->search(attendance_tbl => +{attendance_date => +{between => [$begin_date, $end_date]}});
bulk_insertについて
$teng->bulk_insert('webedi_tbl', \@csv_datas_for_insert);
bulk_insertは早いと思っていたけど、早くない。
ログを見ると、tengのbulk_insertはinsertしてからselect文を発行する仕様(SQLiteのみ??)らしく、select文のぶんだけ遅くなってしまった。。
iteratorで取得するか、配列で取得するか?(性能観点)
search()結果を取得するには、以下の2通りの方法がある。
1.iteratorで取得し、iterator->next()でループ処理
2.配列で取得し、ループ処理
1は取得は早いが、next()で回す回数が多いほど処理が遅くなる。
2は1に比べて取得は若干遅くなる(内部で配列に変換するため?)が、その後のループ処理は早い。
ゆえに、取得データが多ければ多いほど、2のほうが早くなると思われる。