makoxti
@makoxti

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Insert時に(sqlite3.OperationalError) table users has no column named nameが発生する

OS

Mac

言語

Python

Frameword

FastAPI

DB

SQLite

git

解決したいこと

ユーザー作成APIを呼び出した時に、DBにInsertされるようにしたいです。

DBの状態

image.png

発生している問題・エラー

コンソールに出力されるエラーログです。

ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1808, in _execute_context
    self.dialect.do_execute(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 732, in do_execute
    cursor.execute(statement, parameters)
sqlite3.OperationalError: table users has no column named name

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/uvicorn/protocols/http/h11_impl.py", line 366, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
    return await self.app(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/fastapi/applications.py", line 261, in __call__
    await super().__call__(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/starlette/applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
    raise e
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/starlette/routing.py", line 656, in __call__
    await route.handle(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/starlette/routing.py", line 259, in handle
    await self.app(scope, receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/starlette/routing.py", line 61, in app
    response = await func(request)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/fastapi/routing.py", line 227, in app
    raw_response = await run_endpoint_function(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/fastapi/routing.py", line 162, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/starlette/concurrency.py", line 39, in run_in_threadpool
    return await anyio.to_thread.run_sync(func, *args)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/anyio/to_thread.py", line 28, in run_sync
    return await get_asynclib().run_sync_in_worker_thread(func, *args, cancellable=cancellable,
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/anyio/_backends/_asyncio.py", line 818, in run_sync_in_worker_thread
    return await future
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/anyio/_backends/_asyncio.py", line 754, in run
    result = context.run(func, *args)
  File "/Users/fukujuumakoto/workspace/python/book_fastapai/./code/blog/main.py", line 95, in create_user
    db.commit()
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1431, in commit
    self._transaction.commit(_to_root=self.future)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 829, in commit
    self._prepare_impl()
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 808, in _prepare_impl
    self.session.flush()
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 3363, in flush
    self._flush(objects)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 3503, in _flush
    transaction.rollback(_capture_exception=True)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
    raise exception
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 3463, in _flush
    flush_context.execute()
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/orm/unitofwork.py", line 456, in execute
    rec.execute(self)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/orm/unitofwork.py", line 630, in execute
    util.preloaded.orm_persistence.save_obj(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/orm/persistence.py", line 244, in save_obj
    _emit_insert_statements(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/orm/persistence.py", line 1237, in _emit_insert_statements
    result = connection._execute_20(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1620, in _execute_20
    return meth(self, args_10style, kwargs_10style, execution_options)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/sql/elements.py", line 325, in _execute_on_connection
    return connection._execute_clauseelement(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1487, in _execute_clauseelement
    ret = self._execute_context(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1851, in _execute_context
    self._handle_dbapi_exception(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2032, in _handle_dbapi_exception
    util.raise_(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
    raise exception
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1808, in _execute_context
    self.dialect.do_execute(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 732, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) table users has no column named name
[SQL: INSERT INTO users (name, email, password) VALUES (?, ?, ?)]
[parameters: ('string', 'string', 'string')]
(Background on this error at: https://sqlalche.me/e/14/e3q8)

該当するソースコード

@app.post("/user")
def create_user(request: User, db: Session = Depends(get_db)):
    new_user = models.User(
        name=request.name, email=request.email, password=request.password
    )
    db.add(new_user)
    db.commit()
    db.refresh(new_user)
    return new_user

自分で試したこと

テーブル再作成コマンド実行
.dbファイルを削除し、再度テーブル作成コマンド実行

わかる方いらっしゃいましたら、ご教授いただけると幸いです。
よろしくお願いいたします。

0

7Answer

 ちなみにですが、SQLalchemyはORMと呼ばれる既存のsqliteのライブラリを包んだものなので中でどんな処理がされているかわかりません。
 普通のセレクト処理とかであればsqlite3とは実行時間に大差ないですが、N+1問題対策などではちょっとやりにくいです。その点sqlite3であれば、クエリをすべて自分で管理できるため実行速度的にはsqlite3の方がよいと考えられます。

1Like

Comments

  1. @makoxti

    Questioner

    ありがとうございます!!

エラーによると
「usersっていうテーブルには、nameっていうカラムは存在しないよ」っていってます。
実行されたSQL文が間違っていると考えるのが妥当だと思います。
 コード全体を見たわけではないですが見た感じではタイプミスは見受けられなかったので、もしかしたらライブラリのバグがあるかもしれません。

 SQLalchemyを使われているのであれば、もしこのライブラリのバグだとするとどうしようもないので、Python標準搭載の「sqlite3」をご使用ください。

0Like

@OyaTomo
ありがとうございます。
以下の記事を参考にしてみます。
https://www.python.ambitious-engineer.com/archives/745

ライブラリのバグだったらめんどくさいですね。
個人的な考えなのですが、FastAPIならSQLalchemyで実装するのが一般的?な気がするので、残園です。

ちなみになのですが、、こちらのエラーもライブラリのバグ関係あるかわかりますか?
https://qiita.com/makoxti/questions/44f1db597a62cc8547e2

0Like

@OyaTomo
再オープンさせていただきました。
sqlite3で実装したのですが、nameカラムがないという同じエラーが吐かれました。

◆エラーログ

sqlite3.OperationalError: no such column: request.name

◆実装

@app.post("/user")
def create_user(request: User, db: Session = Depends(get_db)):
    conn = sqlite3.connect(dbname)
    c = conn.cursor()

    c.execute(
        "INSERT INTO users VALUES (request.name, request.email, request.password)"
    )

    # close処理
    conn.commit()
    c.close()
    conn.close()

    return "create completed"
0Like

request.name etc...は全部文字列の一部になっています。

c.execute("INSERT INTO users VALUES (request.name, request.email, request.password)")

これでは、正しい値が代入されていません。

僕が書いたテストコードです。

import sqlite3

con = sqlite3.connect("temp.db")
cur = con.cursor()

cur.execute("create table if not exists users (name str, age int);")
con.commit()

# これがパラメータを渡す機能 ?のところに値が入れられる。
cur.execute("insert into users values (?, ?);", ["name", 20])
con.commit()

まず、注意点があります。
 INSERTの値を渡すときは、必ずsqlite3のモジュールの機能でパラメータを渡す機能(公式も推奨)があるのでそれを使用してください。これは絶対です。str型のfromat()を使用して値を入れる人もいるのですが絶対にやめてください。(SQLインジェクション対策です。)
詳しい使い方は、Google先生のほうに聞いてください。
あとは、Pythonのドキュメントを読むのもおすすめですよ。

0Like

Comments

  1. @makoxti

    Questioner

    ありがとうございます!!

Your answer might help someone💌