web-dev-qa-db-ja.com

PythonでSQLiteの行の存在を確認する方法は?

次のように、クエリステートメントにカーソルがあります。

cursor.execute("select rowid from components where name = ?", (name,))

コンポーネントの存在を確認したい:名前とpython変数に戻ります。どうすればよいですか?

36
fx.

namesは一意であるため、fetchoneを使用するという最初の提案よりも、fetchallを使用する(OPの)方法またはSELECT count(*)を使用するAlex Martelliの方法をお勧めします] _。

fetchallは、結果(通常は複数行のデータ)をリストにラップします。 namesは一意であるため、fetchallは、リストにタプルを1つだけ含むリストを返します(例:[(rowid,),]または空のリスト[]rowidを知っている場合、fetchallを使用するには、リストを掘り下げてrowidにアクセスする必要があります。

(rowid,)またはfetchoneの1行のみを取得するため、この場合はNoneを使用することをお勧めします。 rowid(ある場合)を取得するには、タプルの最初の要素を選択するだけです。

特定のrowidを気にせず、ヒットがあることだけを知りたい場合は、Alex Martelliの提案SELECT count(*)を使用できます。これは(1,)を返しますまたは(0,)

コードの例を次に示します。

おもちゃのsqliteテーブルをセットアップするための最初の定型コード:

import sqlite3
connection = sqlite3.connect(':memory:')
cursor=connection.cursor()
cursor.execute('create table components (rowid int,name varchar(50))')    
cursor.execute('insert into components values(?,?)', (1,'foo',))

fetchall:を使用

for name in ('bar','foo'): 
    cursor.execute("SELECT rowid FROM components WHERE name = ?", (name,))
    data=cursor.fetchall()
    if len(data)==0:
        print('There is no component named %s'%name)
    else:
        print('Component %s found with rowids %s'%(name,','.join(map(str, next(Zip(*data))))))

収量:

There is no component named bar
Component foo found with rowids 1

fetchone:を使用

for name in ('bar','foo'): 
    cursor.execute("SELECT rowid FROM components WHERE name = ?", (name,))
    data=cursor.fetchone()
    if data is None:
        print('There is no component named %s'%name)
    else:
        print('Component %s found with rowid %s'%(name,data[0]))

収量:

There is no component named bar
Component foo found with rowid 1

SELECT count(*)を使用:

for name in ('bar','foo'): 
    cursor.execute("SELECT count(*) FROM components WHERE name = ?", (name,))
    data=cursor.fetchone()[0]
    if data==0:
        print('There is no component named %s'%name)
    else:
        print('Component %s found in %s row(s)'%(name,data))

収量:

There is no component named bar
Component foo found in 1 row(s)
79
unutbu

答えを見つけました。

exist = cursor.fetchone()
if exist is None:
  ... # does not exist
else:
  ... # exists
18
fx.

既存の回答(あなた自身と@unutbuの両方)が指摘しているように、トリックは、SELECTを実行した後にsome並べ替えを行う必要があるということです。選択に対する結果であるかどうか(単一のフェッチで実行して何もチェックしないか、全フェッチで空のリストをチェックするかは、UNIQUE制約は基本的に同等のアプローチです)。

非常に直接的な答えとして、rowidを選択するのではなく、select count(*) from components where name = ?を使用できます。nameに指定された値が存在するかどうか(反対に、どの行を気にするかもしあれば、id ;-)。この選択を実行し、結果を取得すると、0値が存在しない場合、1存在する場合(列UNIQUE;-のname制約についてのコメントで述べたことを考えると、他の結果は得られません)。

5
Alex Martelli

Python 3.8の開始、および 代入式(PEP 572):=演算子)の導入により、cursor.fetchone()の結果をキャプチャすることにより、以前の回答をわずかに変更できます。条件チェック内で結果コンテンツを抽出するためにそれを再利用します:

# cursor.execute("SELECT rowid FROM components WHERE name = ?", (name,))
if item := cursor.fetchone():
  print(f'Component {name} found with rowid {item[0]}')
else:
  print(f'There is no component named {name}')
0
Xavier Guihot