質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

Python SQliteについて。no such table というエラーが出てしまう。

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,453

inchoXD

score 4

Python初心者になります。
こちらのページを参考に家計簿アプリを作成しています。ウィンドウは問題なく表示され、入力し登録ボタンを押すと以下のエラーが発生します。

コンソール上の表示

no such table: acc_data

該当のソースコード(sqliteの部分のみ)

#空のデータベースを作成→接続
dbname = 'database.db'
c = sqlite3.connect(dbname)
c.execute("PRAGMA foreign_keys = 1")

#データベース登録済み→ddlでの発行エラーをexceptブロックで回避
try:
    #itemテーブルの定義
    ddl = """
    CREATE TABLE item
    (
        item_code INTEGER PRIMARY KEY AUTOINCREMENT,
        item_name TEXT NOT NULL UNIQUE
    );
    """
    #SQLの発行
    c.execute(ddl)
    #acc_dataテーブルの定義
    ddl = """
    CREATE TABLE acc_data
    (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        aac_date DATE NOT NULL,
        item_code INTEGER NOT NULL,
        amount INTEGER,
        FOREIGN KEY(item_code) REFERENCES item(item_code)
    );
    """
    #itemテーブルへリファランスデータの登録
    c.execute(ddl)
    c.execute("INSERT INTO item(item_name) VALUES('食費');")
    c.execute("INSERT INTO item(item_name) VALUES('住宅費');")
    c.execute("INSERT INTO item(item_name) VALUES('光熱費');")
    c.execute("COMMIT;")
except:
    pass

#データをdbに登録
def create_sql():
    #日付の読み取り
    acc_date = entrydy.get()
    #内訳の読み取り
    item_code = entrydt.get()
    #金額の読み取り
    amount = entrypr.get()

    #SQL発行→DBへ登録
    try:
        c.execute("""
        INSERT INTO acc_data(acc_date,item_code,amount)
        VALUES('{}',[{}],{});
        """.format(acc_date,item_code,amount))
        c.execute("COMMIT;")
        print("1件登録しました。")
    #登録できなかった場合(ドメインエラーなど)
    except Exception as e:
        print(e)

ソースコード全体

#-*- coding: utf-8 -*-

import tkinter as tk
import sqlite3

#空のデータベースを作成→接続
dbname = 'database.db'
c = sqlite3.connect(dbname)
c.execute("PRAGMA foreign_keys = 1")

#データベース登録済み→ddlでの発行エラーをexceptブロックで回避
try:
    #itemテーブルの定義
    ddl = """
    CREATE TABLE item
    (
        item_code INTEGER PRIMARY KEY AUTOINCREMENT,
        item_name TEXT NOT NULL UNIQUE
    );
    """
    #SQLの発行
    c.execute(ddl)
    #acc_dataテーブルの定義
    ddl = """
    CREATE TABLE acc_data
    (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        aac_date DATE NOT NULL,
        item_code INTEGER NOT NULL,
        amount INTEGER,
        FOREIGN KEY(item_code) REFERENCES item(item_code)
    );
    """
    #itemテーブルへリファランスデータの登録
    c.execute(ddl)
    c.execute("INSERT INTO item(item_name) VALUES('食費');")
    c.execute("INSERT INTO item(item_name) VALUES('住宅費');")
    c.execute("INSERT INTO item(item_name) VALUES('光熱費');")
    c.execute("COMMIT;")
except:
    pass

#データをdbに登録
def create_sql():
    #日付の読み取り
    acc_date = entrydy.get()
    #内訳の読み取り
    item_code = entrydt.get()
    #金額の読み取り
    amount = entrypr.get()

    #SQL発行→DBへ登録
    try:
        c.execute("""
        INSERT INTO acc_data(acc_date,item_code,amount)
        VALUES('{}',[{}],{});
        """.format(acc_date,item_code,amount))
        c.execute("COMMIT;")
        print("1件登録しました。")
    #登録できなかった場合(ドメインエラーなど)
    except Exception as e:
        print(e)

root = tk.Tk()
#ExpはExpenses(家計簿)の略称。
root.title("Exp")
root.geometry("300x300")

#メニューバー
frame = tk.LabelFrame(root,bd=2,relief="ridge",text="Menu")
frame.pack(fill="x")

#メニューバーのボタン
button1 = tk.Button(frame,text="入力")
button1.pack(side="left")
button2 = tk.Button(frame,text="表示")
button2.pack(side="left")
button3 = tk.Button(frame,text= "終了")
button3.pack(side="right")

#入力画面ラベル
labelmn = tk.Label(root,text="【入力画面】",font=("",16),height=2)
labelmn.pack(fill="x")

#日付ラベルとエントリー
framedy = tk.Frame(root,pady=10)
framedy.pack()
labeldy = tk.Label(framedy,font=("",14),text="日付")
labeldy.pack(side="left")
entrydy = tk.Entry(framedy,font=("",14),justify="center",width=15)
entrydy.pack(side="left")
#内訳ラベルとエントリー(内訳はdetails)
framedt = tk.Frame(root,pady=10)
framedt.pack()
labeldt = tk.Label(framedt,font=("",14),text="内訳")
labeldt.pack(side="left")
entrydt = tk.Entry(framedt,font=("",14),justify="center",width=15)
entrydt.pack(side="left")
#金額ラベルとエントリー(金額はprice)
framepr = tk.Frame(root,pady=10)
framepr.pack()
labelpr = tk.Label(framepr,font=("",14),text="金額")
labelpr.pack(side="left")
entrypr = tk.Entry(framepr,font=("",14),justify="center",width=15)
entrypr.pack(side="left")
#登録ボタン
buttonsb = tk.Button(root,text="登録",font=("",16),width=10,command=create_sql)
buttonsb.pack(side="right")

root.mainloop()

テーブルを生成できてないようなのですが、いくら検索をかけても自分の力では原因がわかりませんでした。
テーブルの定義の仕方が間違っているのでしょうか...

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Orlofsky

    2019/02/17 19:59

    URLは https://teratail.com/help#about-markdown の[リンク]に修正してください。

    キャンセル

  • inchoXD

    2019/02/17 20:02

    かしこまりました。ご指摘ありがとうございます。

    キャンセル

  • toshi17922062

    2019/02/17 22:34

    SQliteの専門家ではないですが、
    >テーブルの定義の仕方が間違っているのでしょうか
    まずはコマンド(ターミナル)でどんなテーブルが出来ているか、出来ていないか確認後、その定義文を流してみて、ちゃんとテーブルができるかどうかを確認したほうがよいのでは?要は切り分けです。
    acc_dataはもとより、itemもできているかどうか、確認するのが先だと思います。
    まずはプログラム化よりも、それぞれのSQLコマンドの実行確認が先で、確認がとれたら実装化すれば良いと思います。
    もし仮に、たまたま解決策が出て今回上手くいっても、そういう基本は大事だと思いますよ。

    キャンセル

  • firedfly

    2019/02/17 23:39 編集

    toshi17922062さんに同意です。
    長大なコードを投げて答えてくれる人は限られます。

    ・itemテーブルを作成して、できているか確認
    ・itemテーブルに定型データを登録して、できているか確認
    ・acc_dataテーブルを作成して、できているか確認
    ・acc_dataテーブルに定型データを登録して、できているか確認

    ここまでできてから、入力されたデータの登録に挑戦するという手順がおすすめです。
    一気にコードを書けば間違いはいくつも入り込みますし
    どこまで正しいかさえわからないコードを直すのは大変です。

    キャンセル

回答 1

0

こんにちは。

手元で実行したところ no such table: acc_data は発生しませんでした。
以下、3点修正してデータが登録されるところまで確認しました。

1.aac_date  → acc_date 

    ddl = """
    CREATE TABLE acc_data
    (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        acc_date DATE NOT NULL,
        item_code INTEGER NOT NULL,
        amount INTEGER
    );
    """

2.item_codeを追加

    c.execute(ddl)
    c.execute("INSERT INTO item(item_code, item_name) VALUES(1, '食費');")
    c.execute("INSERT INTO item(item_code, item_name) VALUES(2, '住宅費');")
    c.execute("INSERT INTO item(item_code, item_name) VALUES(3, '光熱費');")
    c.execute("COMMIT;")

3.[{}] → {}

        c.execute("""
        INSERT INTO acc_data(acc_date,item_code,amount)
        VALUES('{}',{},{});
        """.format(acc_date, item_code, amount))

以下、テストコード全文です。

import tkinter as tk
import sqlite3

#空のデータベースを作成→接続
dbname = 'database.db'
c = sqlite3.connect(dbname)
c.execute("PRAGMA foreign_keys = 1")

#データベース登録済み→ddlでの発行エラーをexceptブロックで回避
try:
    #itemテーブルの定義
    ddl = """
    CREATE TABLE item
    (
        item_code INTEGER PRIMARY KEY AUTOINCREMENT,
        item_name TEXT NOT NULL UNIQUE
    );
    """
    #SQLの発行
    c.execute(ddl)
    #acc_dataテーブルの定義
    ddl = """
    CREATE TABLE acc_data
    (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        acc_date DATE NOT NULL,
        item_code INTEGER NOT NULL,
        amount INTEGER,
        FOREIGN KEY(item_code) REFERENCES item(item_code)
    );
    """
    #itemテーブルへリファランスデータの登録
    c.execute(ddl)
    c.execute("INSERT INTO item(item_code, item_name) VALUES(1, '食費');")
    c.execute("INSERT INTO item(item_code, item_name) VALUES(2, '住宅費');")
    c.execute("INSERT INTO item(item_code, item_name) VALUES(3, '光熱費');")
    c.execute("COMMIT;")
except Exception as e:
    print(e)


def create_sql():
    #日付の読み取り
    acc_date = entrydy.get()
    #内訳の読み取り
    item_code = entrydt.get()
    #金額の読み取り
    amount = entrypr.get()

    #SQL発行→DBへ登録
    try:
        c.execute("""
        INSERT INTO acc_data(acc_date,item_code,amount)
        VALUES('{}',{},{});
        """.format(acc_date,item_code,amount))
        c.execute("COMMIT;")
        print("1件登録しました。")
    #登録できなかった場合(ドメインエラーなど)
    except Exception as e:
        print(e)


root = tk.Tk()
#ExpはExpenses(家計簿)の略称。
root.title("Exp")
root.geometry("300x300")

#メニューバー
frame = tk.LabelFrame(root,bd=2,relief="ridge",text="Menu")
frame.pack(fill="x")

#メニューバーのボタン
button1 = tk.Button(frame,text="入力")
button1.pack(side="left")
button2 = tk.Button(frame,text="表示")
button2.pack(side="left")
button3 = tk.Button(frame,text= "終了")
button3.pack(side="right")

#入力画面ラベル
labelmn = tk.Label(root,text="【入力画面】",font=("",16),height=2)
labelmn.pack(fill="x")

#日付ラベルとエントリー
framedy = tk.Frame(root,pady=10)
framedy.pack()
labeldy = tk.Label(framedy,font=("",14),text="日付")
labeldy.pack(side="left")
entrydy = tk.Entry(framedy,font=("",14),justify="center",width=15)
entrydy.pack(side="left")
#内訳ラベルとエントリー(内訳はdetails)
framedt = tk.Frame(root,pady=10)
framedt.pack()
labeldt = tk.Label(framedt,font=("",14),text="内訳")
labeldt.pack(side="left")
entrydt = tk.Entry(framedt,font=("",14),justify="center",width=15)
entrydt.pack(side="left")
#金額ラベルとエントリー(金額はprice)
framepr = tk.Frame(root,pady=10)
framepr.pack()
labelpr = tk.Label(framepr,font=("",14),text="金額")
labelpr.pack(side="left")
entrypr = tk.Entry(framepr,font=("",14),justify="center",width=15)
entrypr.pack(side="left")
#登録ボタン
buttonsb = tk.Button(root,text="登録",font=("",16),width=10,command=create_sql)
buttonsb.pack(side="right")

root.mainloop()

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる