0

関数の呼び出しごとに一度に1行だけSQLiteのテーブルからデータを選択しようとしていますが、呼び出しごとに行をインクリメントしたいです(self.countは他の場所で初期化され、「line」はここでは関係ありません)I Twistedのadbapi接続プールを使用してDBに接続しています。これが私が試したコードです:

def queryBTData4(self,line):
    self.count=self.count+1
    uuId=self.count
    query="SELECT co2_data, patient_Id FROM btdata4 WHERE uid=:uid",{"uid": uuId}          
    d = self.dbpool.runQuery(query)
    return d

このコードは、DBでuid = 1またはその他の数値を設定した場合(DBを作成したときにuidに自動インクリメントを使用した場合)に機能しますが、uidに値を割り当てようとすると(つまり、uuIdを介してself.count)、次のように報告されます。演算子は文字列またはユニコードである必要があります(両方を試しましたが、役に立たないようです)ただし、カーソルと実行コマンドを使用すると、上記のクエリステートメントは前のプログラムで問題なく機能することはわかっていますが、できませんここで機能しない理由を確認してください。あらゆる種類の組み合わせを試し、解決策を探しましたが、まだ機能するものは見つかりませんでした(角かっこやその他の形式のステートメントも試しました)

ヘルプやアドバイスをありがとう。

コード全体は次のとおりです。

from twisted.internet import protocol, reactor
from twisted.protocols import basic
from twisted.enterprise import adbapi
import sqlite3, time


class ServerProtocol(basic.LineReceiver):
    def __init__(self):
        self.conn = sqlite3.connect('biomed2.db',check_same_thread=False)
        self.dbpool =  adbapi.ConnectionPool("sqlite3" , 'biomed2.db',  check_same_thread=False)


    def connectionMade(self):
        self.sendLine("conn made")
        factory = protocol.ClientFactory()
        factory.protocol = ClientProtocol
        factory.originator = self
        reactor.connectTCP('localhost', 1234, factory)

    def lineReceived(self, line):
        self._received = line
        self.insertBTData4(self._received)
        self.sendLine("line recvd") 

    def forwardLine(self, recipient):
        recipient.sendLine(self._received)      


    def insertBTData4(self,data):
        print "data in insert is",data
        chx=data
        PID=2
        device_ID=5
        query="INSERT INTO btdata4(co2_data,patient_Id, sensor_Id) VALUES ('%s','%s','%s')" % (chx, PID, device_ID) 
        dF = self.dbpool.runQuery(query)
        return dF

class ClientProtocol(basic.LineReceiver):
    def __init__(self):
        self.conn = sqlite3.connect('biomed2.db',check_same_thread=False)
        self.dbpool =  adbapi.ConnectionPool("sqlite3" , 'biomed2.db',  check_same_thread=False)
        self.count=0


    def connectionMade(self):
        print "server-client made connection with client"
        self.factory.originator.forwardLine(self)
        #self.transport.loseConnection()


    def lineReceived(self, line):
        d=self.queryBTData4(self)
        d.addCallbacks(self.sendData,self.printError )


    def queryBTData4(self,line):
        self.count=self.count+1
        query=("SELECT co2_data, patient_Id FROM btdata4 WHERE uid=:uid",{"uid": uuId})          
        dF = self.dbpool.runQuery(query)
        return dF

    def sendData(self,line):
        data=str(line)
        self.sendLine(data) 

    def printError(self,error):
        print "Got Error: %r" % error
        error.printTraceback()


def main():
    factory = protocol.ServerFactory()
    factory.protocol = ServerProtocol
    reactor.listenTCP(4321, factory)
    reactor.run()

if __name__ == '__main__':
    main()

DBは別のプログラムで作成されるため、次のようになります。

import sqlite3, time, string
conn = sqlite3.connect('biomed2.db')

c = conn.cursor()
c.execute('''CREATE TABLE btdata4
             (uid INTEGER PRIMARY KEY, co2_data integer, patient_Id integer, sensor_Id   integer)''')

メインプログラムはデータをサーバーソケットに取り込み、DBに挿入します。クライアントソケット側では、データは一度に1行ずつDBから削除され、外部サーバーに送信されます。このプログラムには、必要に応じてサーバー側からクライアント側にデータを送信する機能もありますが、現時点では送信していません。

queryBTData()では、関数が呼び出されるたびにカウントが増分し、その値をuuIdに割り当て、それをクエリに渡します。このクエリステートメントは、adbapiを使用しないプログラムで機能しましたが、ここでは機能しないようです。これが十分に明確であることを願っていますが、そうでない場合はお知らせください。もう一度やり直します。

編集:

一度にDBから1行を取得するようにプログラムを変更しましたが(以下のqueryBTData()を参照)、別の問題が発生しました。

def queryBTData4(self,line):
    self.count=self.count+1
    xuId= self.count
    #xuId=10
    return self.dbpool.runQuery("SELECT co2_data FROM btdata4 WHERE uid = ?",xuId)
    #return self.dbpool.runQuery("SELECT co2_data FROM btdata4 WHERE uid = 10")

カウントが10に達すると、「提供されたバインディングの数が正しくありません。現在のステートメントは1を使用し、2が提供されています」というエラーが発生します(以下に投稿します)。

xuIdを10に設定しようとしましたが(コメントアウトされた行xuId = 10を参照)、それでも同じエラーが発生します。ただし、returnステートメントを(コメントアウトされたreturnに)切り替えると、エラーなしで正しい行が実際に取得されます。xuIdをUnicodeに変換しようとしましたが、違いはありません。それでも同じエラーが発生します。基本的に、IIがreturnステートメントでuidを10以上に設定した場合(コメントアウトされたreturn)は機能しますが、最初のreturnでuidをxuId(つまり、uid = ?, xuId)に設定した場合、xuIdが10未満の場合にのみ機能します。 。APIのドキュメントでは、私が知る限り、これが発生する理由についての手がかりはありません(これを排除するために、DBへの挿入を無効にし、SQLite3_の制限(999)を確認しました)

最初のreturnステートメントを使用したときに発生するエラーは次のとおりです。

Got Error: <twisted.python.failure.Failure <class 'sqlite3.ProgrammingError'>>
Traceback (most recent call last):
File "c:\python26\lib\threading.py", line 504, in __bootstrap
self.__bootstrap_inner()
File "c:\python26\lib\threading.py", line 532, in __bootstrap_inner
self.run()
File "c:\python26\lib\threading.py", line 484, in run
self.__target(*self.__args, **self.__kwargs)
--- <exception caught here> ---
File "c:\python26\lib\site-packages\twisted\python\threadpool.py", line 207, i
n _worker
result = context.call(ctx, function, *args, **kwargs)
File "c:\python26\lib\site-packages\twisted\python\context.py", line 118, in c
allWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "c:\python26\lib\site-packages\twisted\python\context.py", line 81, in ca
llWithContext
return func(*args,**kw)
File "c:\python26\lib\site-packages\twisted\enterprise\adbapi.py", line 448, i
n _runInteraction
result = interaction(trans, *args, **kw)
File "c:\python26\lib\site-packages\twisted\enterprise\adbapi.py", line 462, i
n _runQuery
trans.execute(*args, **kw)
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current sta
tement uses 1, and there are 2 supplied.

ありがとう。

4

1 に答える 1

0

runQuery の API ドキュメントを検討してください。次に、これら 3 つの関数呼び出しの違いを考えてみましょう。

c = a, b
f(a, b)
f((a, b))
f(c)

最後に、エラー メッセージを言い換えないでください。常に逐語的に引用します。可能な限りコピーして貼り付けてください。手動で転記した場合はメモしてください。

于 2012-06-14T14:04:07.903 に答える