Google Android アプリケーション開発入門8章のSQLiteを使うサンプル
Google Android アプリケーション開発入門8章のSQLiteを使うサンプル
21章は短い
HDBC-2.1.0だと下のようなエラーがずらずらでるのでgitで入れる。
Database/HDBC/SqlValue.hs:585:9:
Duplicate instance declarations:
instance Typeable Day
-- Defined at Database/HDBC/SqlValue.hs:585:9-20
instance Typeable Day
-- Defined in time-1.1.4:Data.Time.Calendar.Days
使ってみる
Prelude> :m Database.HDBC Database.HDBC.Sqlite3
Prelude Database.HDBC Database.HDBC.Sqlite3> conn <- connectSqlite3 "drkcore.db"
Prelude Database.HDBC Database.HDBC.Sqlite3> getTables conn
["entries","entry_tags","roles","tags","user_roles","users"]
Prelude Database.HDBC Database.HDBC.Sqlite3> \
quickQuery' conn "select title from entries where pubdate > '2010-01-01'" []
[[SqlByteString "\229\155\155\229\173\163\230\161\156\227\129\174\232\138\ ...
これをutf8で出力したいのでWIKIも読んどく。
TurboGearsだとこんな感じでいけるじゃないですか?
pylonsはちょっとよく分からなくて結局
sqlite3 -separator , test.db ".import makeinu.csv test_table"
とやってしまった(なんじゃそりゃ)。
08012010 Python sqlite SQLAlchemy
多数の化合物のファイルはSMILES形式でsqliteのデータベースにしておくと、あつかいやすいのだけど、たまにさくっとアクセスしてゴニョりたいときにsqliteでSQL文発行してとかめんどくさかったりする。
で、SQLAlchemy使うとpythonの対話環境で使えてそのままpybelとかに持っていけるので便利なんだけど、いちいちマッピングしなくても良いらしい。
create_engineでsqliteのファイルを指定して、reflectをTrueにすればよい。
from sqlalchemy import * db = create_engine('sqlite:///test.db') metadata = MetaData(bind=db, reflect=True) table = metadata.tables['table_name']
このdrkcoreのファイルをつかって、タイトルを抜き出してみる。
>>> execfile("satest.py") >>> stmt = entries.select() >>> result = stmt.execute() >>> for row in result: ... print row.title ... blogを変えてみた 卓次郎商店でつけ麺 かど乃やで黒びしおラーメン
らくちん。
4章くらいまで読んだ。データの永続化用にsqlalchemy使えるようにしとくと仕事が非常に楽になりそうなので、ちゃんと読む。
多対多のサンプルとしてTags: Database schemasの“Toxi” solutionをDBICで書いてみる。
関連を表すテーブルに対しては、1対多の関係を設定しておいて、更にmany_to_manyを追加する
図にしてみたらわかりやすくなった。
ちなみに、1対多はこちらを、多対多はこちらを参考にしました。
use 5.008008; use strict; use warnings; use base 'DBIx::Class::Schema'; our $VERSION = '0.01'; __PACKAGE__->load_classes(qw/Tag Bookmark TagMap/); 1;
use strict; use warnings; use base 'Kzfm::Schema'; __PACKAGE__->load_components(qw/PK::Auto::SQLite Core/); __PACKAGE__->table('tag'); __PACKAGE__->add_columns(qw/id name/); __PACKAGE__->set_primary_key('id'); __PACKAGE__->has_many(tagmap => 'Kzfm::Schema::TagMap','tag_id'); __PACKAGE__->many_to_many('bookmarks' => 'tagmap','bookmark_id'); 1;
use strict; use warnings; use base 'Kzfm::Schema'; __PACKAGE__->load_components(qw/PK::Auto::SQLite Core/); __PACKAGE__->table('bookmark'); __PACKAGE__->add_columns(qw/id name uri description time_created/); __PACKAGE__->set_primary_key('id'); __PACKAGE__->has_many(tagmap => 'Kzfm::Schema::TagMap','bookmark_id'); __PACKAGE__->many_to_many('tags' => 'tagmap','tag_id'); 1;
use strict; use warnings; use base 'Kzfm::Schema'; __PACKAGE__->load_components(qw/PK::Auto::SQLite Core/); __PACKAGE__->table('tagmap'); __PACKAGE__->add_columns(qw/id bookmark_id tag_id/); __PACKAGE__->set_primary_key('id'); __PACKAGE__->belongs_to('bookmark_id' => 'Kzfm::Schema::Bookmark'); __PACKAGE__->belongs_to('tag_id' => 'Kzfm::Schema::Tag'); 1;
制約の部分だけ、考えてみる。
__PACKAGE__->belongs_to('カラム名(アクセサ?)' => 'スキーマ(pm)'); __PACKAGE__->has_many(テーブル名 => 'スキーマ(pm)','カラム名(アクセサ?)'); __PACKAGE__->many_to_many('任意のキー名' => 'テーブル名','多対多関係のカラム');
あと、さらにユーザーを追加する場合に、ユーザーとブックマークも多対多の関係になるけど、こっちも正規化したほうがいいのか、むしろやりすぎないほうがむしろいいのか悩む。
最近はmysqlでデータベースを作ることが多かったんだけど、ちょっとしたもの作るのにmysqlはでかすぎるなあとSQLite+DBICをさわり始めてる。
サンプルはPerl/DBIC - Nekokak's core dumpが、よくまとまっていて非常にわかりやすかったので、これの流れで書いた。が、二箇所ほど悩んだのでメモ。ちなみに、SQLiteのせいかどうかはわかりません。
ちなみに、
というバージョン。
1:多の関係を試す をSQLiteで試す。
まずsqlはこんな感じ
create table user ( id integer PRIMARY KEY not null, name varchar(256) not null, time date ); create table bookmark ( id integer NOT NULL PRIMARY KEY, user_id integer NOT NULL, url text NOT NULL, FOREIGN KEY (user_id) REFERENCES user(id) ); CREATE INDEX user_id_idx ON bookmark (user_id);
で、データベース作成
sqlite3 kzfm.db < test.sql
Schema,User,Bookmarkモジュールはほとんど同じだがload_componentsにPK::Auto::SQLiteを使う。
use strict; use warnings; use base 'DBIx::Class'; __PACKAGE__->load_components(qw/ PK::Auto::SQLite Core/); __PACKAGE__->table('user'); __PACKAGE__->add_columns(qw/id name/); __PACKAGE__->set_primary_key('id'); __PACKAGE__->has_many(bookmark => 'Kzfm::Schema::Bookmark', 'user_id'); 1;
こんな感じ。
で、実行してみると、、、
my $i = $schema->resultset('User')->create({name => 'kzfm'}); $schema->resultset('Bookmark')->create({ user_id => $i->last_insert_id , url => 'http://test.com/'} );
last_insert_idがないと言われた。単にidだけでよいのか?
のとこでUser,Loginお互いにmight_haveを指定すると->idでIDがゲットできなかった。
use strict; use warnings; use base 'DBIx::Class'; __PACKAGE__->load_components(qw/ PK::Auto::SQLite Core/); __PACKAGE__->table('user'); __PACKAGE__->add_columns(qw/id name/); __PACKAGE__->set_primary_key('id'); __PACKAGE__->has_many(bookmark => 'Kzfm::Schema::Bookmark', 'user_id'); #__PACKAGE__->might_have(id => 'Kzfm::Schema::Login'); 1; package Kzfm::Schema::Login; use strict; use warnings; use base 'DBIx::Class'; use DateTime::Format::MySQL; __PACKAGE__->load_components(qw/PK::Auto::SQLite Core/); __PACKAGE__->table('login'); __PACKAGE__->add_columns(qw/id login_time/); __PACKAGE__->set_primary_key('id'); __PACKAGE__->might_have(id => 'Kzfm::Schema::User'); __PACKAGE__->inflate_column('login_time', { inflate => sub { DateTime::Format::MySQL->parse_datetime(shift); }, deflate => sub { DateTime::Format::MySQL->format_datetime(shift); }, });
幾つかのパターンを試した結果、参照するほうにmight_haveをつけるらしい。あと、SQLiteの場合日付まわりをどう処理すればいいのかよくわかってない。とりあえずMySQLのフォーマットでも動くような気がするんだけど。
というわけで、時間のあるうち(気力のあるうち?)に、多対多まではいっときたい。
24112006 sqlite
SQLite+DBICで色々やるために、SQLiteまわりをみてたらtrigger使えるという事実を知った。
そういえば、O/Rマッパーとトリガーを一緒に使うと調子いい例ってあるのかな?
とか思った。
23112006 sqlite
sqliteのlinux用バイナリをFedoraCoreで使うと、コマンドプロンプトはバックスペースが効かず、^Hが表示されてしまい、SQL文の修正ができず面倒だ。
と思ってたらCtrl-BackspaceでOKなことを発見した。
でも、コマンド履歴はCtrl-(矢印 or p)では動かなかった。