Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Lisp tutorial for Pythonista.Day #4 : Work with RDBMS                                                          Ransui Iso ...
宿題できましたか?
今日は予告通り SQL !なんだかんだで RDBMS 使えないと   仕事では困っちゃう
CLSQL を使います
QuickLisp でインストールclsql と clsql­mysql と clsql­postgresql       をインストールしてくださいませ
REPL 環境下でテストしてみる ●   とりあえず selectCL­USER> (use­package :clsql)CL­USER> (connect ("achernar" "stats_master" "<user­name>" "...
プログラムで使う場合は●   例によって asdf でロードする●(asdf:oos asdf:load­op :clsql)(asdf:oos asdf:load­op :clsql­mysql) ●(asdf:oos asdf:load­o...
CLSQL はマニュアルが充実http://clsql.b9.com/manual/index.html      ここ読めば普通は困らないと思う
これだけだとあまりにアレなのでいくつか Tips など
MySQL を使う場合●   テーブル名の大文字 / 小文字区別問題      ●   Linux 上で動作している MySQL はデフォルトでテーブル名の大文            字と小文字を区別する ( 定義時の名前がそのまま使われる )...
connection オブジェクト●   connect 関数      ●   データベースへの接続オブジェクトを作成する      ●   同じ属性の接続を複数作ろうとするとデフォルトではエラー!      ●   :if­exists キ...
接続を切る●   disconnect 関数を使う      ●   :database キーワード引数で対象の接続オブジェクトを指定する      ●   省略時は clsql:*default­database* が指定されたものとみ   ...
SQL Quote の方法●   SQL 関数を使えば簡単CL­USER> (format nil "select * from foo where bar in ~a"            (sql ("Hello" "world")))C...
SQL テンプレ●   Lisp の構文そのものが拡張されちゃうので注意     ●   グローバルに有効化:   (enable-sql-reader-syntax)     ●   グローバルに無効化:   (disable-sql-rea...
取得した行について繰り返し処理●   do-query とか loop フォームが便利CL­USER> (do­query ((agency­name client­name)                    (sql [select [...
関数に仕立ててみる●   こんな感じとか(defun get­client­info­by­ids (ids)  (let ((result nil))    (multiple­value­bind (rows field­names)   ...
connection pool●   こんな感じでやるといいかも(defun get­client­info­by­ids (ids &key (database clsql:*default­database*))  (let ((resul...
create / drop table●   ここでもテンプレ使えますCL­USER> (create­table [test_table]                       (([id] integer :not­null :uni...
insert / update / delete●   それぞれ関数があるので使いましょうCL­USER> (insert­records :into [test_table]                          :attribu...
マニュアルをよく読むべし    Lisp 系のマニュアルの書かれ方はちょっと独特だけどCLSQL のマニュアルは例がいっぱいあるので大いに参考にしよう
宿題前回の宿題掲示板のストレージを   データベースにしてねちょこっと改造すれは OK のハズなので、簡単でしょ?         connection pool を使って with­database フォームを使うのがお勧めかも
Upcoming SlideShare
Loading in …5
×

Lisp Tutorial for Pythonista : Day 4

6,060 views

Published on

Common Lispのライブラリである clsqlを使ってRDBMSにアクセスする方法の基本部分をお勉強します。意外と簡単にアクセスできちゃうし、clsqlはよく出来てるのでデータのハンドリングとかでも楽できちゃいますよ。あとはプログラマの工夫次第でいくらでも。

Published in: Technology
  • D0WNL0AD FULL ▶ ▶ ▶ ▶ http://1lite.top/s0hLP ◀ ◀ ◀ ◀
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • なんか、どんどん for Pythonistaじゃなくなってきてるけど、細かいことは気にしない!
    お仕事で使う言語としては RDBMS をハンドリングできないと意味ないので、今回は CLSQL つかってデータベースとお話というお話。
    例によって実用というか、とにかくサクサク書いてサクサク使うをモットーにしてるので、ダサいコーディングとか伝統的なイディオムの無視とかやりまくってます。上級Lisper諸氏においては、生暖かく見守ってください。
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Lisp Tutorial for Pythonista : Day 4

  1. 1. Lisp tutorial for Pythonista.Day #4 : Work with RDBMS Ransui Iso Strategic Technology Group, X-Listing Co, Ltd.
  2. 2. 宿題できましたか?
  3. 3. 今日は予告通り SQL !なんだかんだで RDBMS 使えないと 仕事では困っちゃう
  4. 4. CLSQL を使います
  5. 5. QuickLisp でインストールclsql と clsql­mysql と clsql­postgresql をインストールしてくださいませ
  6. 6. REPL 環境下でテストしてみる ● とりあえず selectCL­USER> (use­package :clsql)CL­USER> (connect ("achernar" "stats_master" "<user­name>" "<password>")             :database­type :mysql)#<CLSQL­MYSQL:MYSQL­DATABASE achernar/stats_master/<user­name> OPEN {100343DEE1}>CL­USER> (query "select id, client_id from campaign_base limit 2")((1712 3736) (815 3371))("id" "client_id") ● 多値関数なので…CL­USER> (multiple­value­bind (rows field­names)             (query "select * from campaign_base limit 2")           (dolist (row rows)             (loop :for value :in row                   :for field­name :in field­names                   :do (format t "~a : ~a~%" field­name value))             (terpri))) (terpri) :標準出力に改行を送る関数
  7. 7. プログラムで使う場合は● 例によって asdf でロードする●(asdf:oos asdf:load­op :clsql)(asdf:oos asdf:load­op :clsql­mysql) ●(asdf:oos asdf:load­op :clsql­postgresql) ● SLIME の REPL で使う時も手動でロードしとく ● Backend は使いたいやつだけで OK よ● パッケージ名は clsql ● いちいちパッケージ名解決 (clsql:query ... ) とか面倒な人は(use­package :clsql) ● 個人的には use-package はあまりオススメしないけどね。 ● Python で言うところの from clsql import * だし…
  8. 8. CLSQL はマニュアルが充実http://clsql.b9.com/manual/index.html ここ読めば普通は困らないと思う
  9. 9. これだけだとあまりにアレなのでいくつか Tips など
  10. 10. MySQL を使う場合● テーブル名の大文字 / 小文字区別問題 ● Linux 上で動作している MySQL はデフォルトでテーブル名の大文 字と小文字を区別する ( 定義時の名前がそのまま使われる ) ● 標準 SQL では区別しない ● CLSQL は標準準拠 ( 基本的に大文字でサーバに送信する ) テーブル名が見つからないと怒られる● /etc/mysql/my.cnf に以下を追加 ● 追加場所 [mysqld] セクション# for Case insensitivelower_case_table_names          = 1 詳細: http://dev.mysql.com/doc/refman/5.1/ja/identifier-case-sensitivity.html
  11. 11. connection オブジェクト● connect 関数 ● データベースへの接続オブジェクトを作成する ● 同じ属性の接続を複数作ろうとするとデフォルトではエラー! ● :if­exists キーワード引数でどうするかを決める – :new 新しく接続オブジェクトを作る – :warn­new 警告出すけどオブジェクトを作る – :error エラーとする – :old すでに開いている接続オブジェクトを返す – :warn­old 警告出して、既存の接続オブジェクトを返す – デフォルト値は *connect­if­exists* 変数で設定できる● connected-databases 関数 ● 現時点で有効な全ての接続オブジェクトをリストで返す● *default-database* 変数 ● 既定の接続オブジェクトを保持する
  12. 12. 接続を切る● disconnect 関数を使う ● :database キーワード引数で対象の接続オブジェクトを指定する ● 省略時は clsql:*default­database* が指定されたものとみ なされるCL­USER> (defparameter db­conn nil)CL­USER> (setf db­conn             (connect ("achernar" "stats_master" "xlisting" "xlisting")               :database­type :mysql))CL­USER> (eq db­conn *default­database*)CL­USER> (disconnect :database db­conn)CL­USER> *default­database*
  13. 13. SQL Quote の方法● SQL 関数を使えば簡単CL­USER> (format nil "select * from foo where bar in ~a"            (sql ("Hello" "world")))CL­USER> (format nil "select * from foo where bar = ~a"             (sql " 波浪ワールド  Hello World"))CL­USER> (enable­sql­reader­syntax)CL­USER> (let ((msg "Hello lisp world!"))           (sql [select [foo] [bar] :from [baz] :where [= [name] msg]]))CL­USER> (sql [select                 [client_base name]                [agency_base name]                  :from ([client_base] [agency_base])                  :where [= [client_base agency_id] [agency_base id]]]) 値の埋め込みは format 使うよりも SQL テンプレの方がお勧め
  14. 14. SQL テンプレ● Lisp の構文そのものが拡張されちゃうので注意 ● グローバルに有効化: (enable-sql-reader-syntax) ● グローバルに無効化: (disable-sql-reader-syntax) ● ローカルに有効化: (locally-enable-sql-reader-syntax) ● ローカルに無効化: (locally-disable-sql-reader-syntax)● [ と ] に意味が追加されてる ● Reader マクロという機能を使っている
  15. 15. 取得した行について繰り返し処理● do-query とか loop フォームが便利CL­USER> (do­query ((agency­name client­name)                    (sql [select [agency_base name] [client_base name]                      :from ([agency_base] [client_base])                      :where [and [= [agency_base id] [client_base agency_id]]                                  [= [agency_base id] 22]]]))           (format t "~a : ~a~%" agency­name client­name))CL­USER> (loop :for (agency­name client­name) being each tuple in                     (sql [select [agency_base name] [client_base name]                      :from ([agency_base] [client_base])                      :where [and [= [agency_base id] [client_base agency_id]]                                  [= [agency_base id] 22]]])            :do (format t "~a : ~a~%" agency­name client­name))結果1行毎にガッツり処理したいとき do-queryカウントしたりちょっと加工して収集しなおしたいとか loopて感じで使い分けるといいかも。まぁこのへんは好みというかソースが見やすくなるほうを優先するのが吉。
  16. 16. 関数に仕立ててみる● こんな感じとか(defun get­client­info­by­ids (ids)  (let ((result nil))    (multiple­value­bind (rows field­names)        (query (sql [select [*] :from [client_base] :where [in [id] ids]]))              (dolist (row rows)         (push           (loop :for value in row                 :for field­name in field­names                 :collect (cons field­name value)) result)))    result))CL­USER> (get­client­info­by­ids (1 3 5))CL­USER> (dolist (result (get­client­info­by­ids (1 3 5)))           (print (cdr (assoc "name" result :test #string=))))
  17. 17. connection pool● こんな感じでやるといいかも(defun get­client­info­by­ids (ids &key (database clsql:*default­database*))  (let ((result nil))    (multiple­value­bind (rows field­names)        (query (sql [select [*] :from [client_base] :where [in [id] ids]])                 :database database)       (dolist (row rows)         (push          (loop :for value in row             :for field­name in field­names             :collect (cons field­name value)) result)))    result))(with­database    (db­conn ("achernar" "stats_master"                "<user­name>" "<password>") :pool t :database­type :mysql)           (get­client­info­by­ids (1 2 3) :database db­conn))
  18. 18. create / drop table● ここでもテンプレ使えますCL­USER> (create­table [test_table]                       (([id] integer :not­null :unique :primary­key)                         ([name] (varchar 255) :not­null)                         ([status] boolean :not­null)))CL­USER> (table­exists­p [test_table])CL­USER> (drop­table [test_table])CL­USER> (table­exists­p [test_table])
  19. 19. insert / update / delete● それぞれ関数があるので使いましょうCL­USER> (insert­records :into [test_table]                          :attribute (id name status)                         :values (1 "James random Hacker" 1))CL­USER> (select [*] :from [test_table])CL­USER> (update­records [test_table]                          :av­pairs ((name "foo bar")                                     (status 0))                         :where [= [id] 1])CL­USER> (select [*] :from [test_table])CL­USER> (delete­records :from [test_table] :where [= [name] "foo bar"])CL­USER> (select [*] :from [test_table])
  20. 20. マニュアルをよく読むべし Lisp 系のマニュアルの書かれ方はちょっと独特だけどCLSQL のマニュアルは例がいっぱいあるので大いに参考にしよう
  21. 21. 宿題前回の宿題掲示板のストレージを データベースにしてねちょこっと改造すれは OK のハズなので、簡単でしょ? connection pool を使って with­database フォームを使うのがお勧めかも

×