もしかしてsqlite3について書いてないのでは?ってなったのでメモ書きを。
今回は日付情報込みでデータベースを作りながらメモを書く。
前回、エミィに実装したBeTSCAE.dbの話はここにはありません。というかこの記憶貯蔵庫にはなさそうです。何のための記憶貯蔵庫なのですか?
セットアップ
def SetUp(): import sqlite3 import datetime dbname = r' ' conn = sqlite3.connect(dbname, isolation_level=None, detect_types = sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) sqlite3.dbapi2.converters['DATETIME'] = sqlite3.dbapi2.converters['TIMESTAMP'] cursor = conn.cursor() sql = "CREATE TABLE IF NOT EXISTS main(ID INTEGER PRIMARY KEY AUTOINCREMENT, Registered datetime, price)" cursor.execute(sql) conn.commit() sql = "CREATE TABLE IF NOT EXISTS F_30(ID INTEGER PRIMARY KEY AUTOINCREMENT, Registered DATETIME, PRICE INTEGER)" cursor.execute(sql) conn.commit() conn.close()
解説のつもり
1つめのSQL文
「もしmainって名前のテーブルがなかったら作りなさい。」
「主キーはIDで数値、そして(指定がなければ)対象のカラムに格納されている最大の値に1を加えた値にしなさい。」
↑この時、データベースに何も入っていない場合、1から始まる。
「次はRegisteredでDATETIME。このDATETIMEはまあ上でなんやかんややってるから……うん……*1」
「もう1個はPRICE。これは数値。」
SELECT
def read_30(): import sqlite3 dbname = r' ' result = [] conn = sqlite3.connect(dbname, isolation_level=None, detect_types = sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) sqlite3.dbapi2.converters['DATETIME'] = sqlite3.dbapi2.converters['TIMESTAMP'] cursor = conn.cursor() sql = "SELECT PRICE FROM F_30 WHERE ID = (SELECT MAX(ID) FROM F_30)" for row in cursor.execute(sql): result.append(row) conn.close() return result[0][0]
何をやりたかったかの解説
テーブル「F_30」の中にあるもっとも新しいデータ*2のPRICEのキーを取得したかった。WHERE ID = (SELECT MAX(ID) FROM F_30)とすることで、IDが最も大きい行を見ることができる。SQL自信ないのよね。
なお、result[0][0]になっているのは、そのままresultで取得すると[(2855,)]のような形になるため。もうちょっといい方法ないかなぁ……?
Nullについて
= 演算子を使ってカラムの値を null と比較しても正しい結果が返ってこない。
少しだけデータを見たい
具体例
from contextlib import closing from random import choice import sqlite3 import SFamBasic as SFB l =[] dbname = "" with closing(sqlite3.connect(dbname)) as connection: cursor = connection.cursor() sql = "SELECT M0,M1,M2,M3,M4,M5,M6 FROM MPD WHERE M0 = 1 LIMIT 10" for row in cursor.execute(sql): l.append(row) print(l)
INSERT
def write(m,ns): from contextlib import closing import sqlite3 import SFamBasic as SFB dbname = r' ' now = SFB.now() conn = sqlite3.connect(dbname, isolation_level=None, detect_types = sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) sqlite3.dbapi2.converters['DATETIME'] = sqlite3.dbapi2.converters['TIMESTAMP'] cursor = conn.cursor() sql1 = "INSERT INTO main (Registered, PRICE) values (?, ?)" sql2 = "INSERT INTO F_30 (Registered, PRICE) values (?, ?)" try: cursor.execute(sql1, (now,m)) conn.commit() except Exception as e: print("Error in write() SQL1 : {}".format(e)) print() try: cursor.execute(sql2, (now,ns)) conn.commit() except Exception as e: print("Error in write() SQL2 : {}".format(e)) print() conn.close()
参考
https://qiita.com/t2psyto/items/e139b5d888d001d0673d
https://www.dbonline.jp/sqlite/table/index9.html#section1
https://techracho.bpsinc.jp/baba/2010_07_16/2130
補足
もしこれを読んでいる私がすべてを忘れた場合、これの元々のコードはAmesiorineではないうちの子の一部となっているはずです。探してください。271108として公開するにあたって雑にこのブログ記事編集画面で若干コードをいじりました。それに伴い、このままでは動かない可能性があります。
Incorrect number of bindings supplied. The current statement uses 1, [N>1] supplied.
executeの第2引数はタプルにしないといけません。
#ダメな例 db.execute('select * from users where name = ?', ('yamada')) #良い例 db.execute('select * from users where name = ?', ('yamada',))
参考元サイトからの引用
※後で実際に私の手元で使ったものに似たカタチに差し替える
特に、SQLで扱う者が1列の場合やらかしやすいので注意。
InterfaceError: Error binding parameter 1 - probably unsupported type.
SQLに入れた変数のtypeがおかしいときに出るエラー。例えばstrで入れるところがtupleになってたりlistになってたりtupleになってたりtupleになってたりtupleになってたりtupleになってたりしてないか確認すること。だいたいtupleになってるんじゃないの?
IntegrityError
ユニーク制約エラー。ユニークなキーに同じ値を入力しようとしてる時に出るエラーのはず。