简体   繁体   中英

Keyword search using python and sqlite

I have a plugin to a game server that writes down changes made to a map.The database contains entries formatted like this - id INTEGER PRIMARY KEY,matbefore INTEGER, matafter INTEGER, name VARCHAR(50), date DATE. I am trying to create a function that, when given a column name, an integer, string, or tuple of an integer or string, and a keyword, will find the selected entries. so far, this is the code that I have come to -

def readdb(self,keyword,column,returncolumn = "*"):
    self.memwrite
    if isinstance(keyword, int) or isinstance(keyword,str):
        entry = [keyword]
    qmarks = ("? OR " * len(entry))[:-4]
    statement = 'SELECT all {0} FROM main WHERE {1} is {2}'.format(returncolumn,column,qmarks)
    print(qmarks)
    self.memcursor.execute(statement, entry)
    return(self.memcursor.fetchall())

keyword is a keyword to search for, column is teh column to search in, and returncolumn is the column to return So I was wondering why this code always fetches no rows, EG - Returns None, no matter what I put for the function. It seems to work fine if I do these things in the console, but not if I wrap them in a function

If entry is a list (like in yesterday's question) , it's not going to work.

>>> returncolumn = "*"
>>> column = "name"
>>> entry = ["Able", "Baker", "Charlie"]
>>> qmarks = ("? OR " * len(entry))[:-4]
>>> statement = 'SELECT all {0} FROM main WHERE {1} is {2}'.format(returncolumn,
column,qmarks)
>>> print statement
SELECT all * FROM main WHERE name is ? OR ? OR ?

and what SQLite will see is:

SELECT all * FROM main WHERE name is 'Able' OR 'Baker' OR 'Charlie'

which is not valid syntax because you need = , not is .

Even if you fix that then (using an integer query for example):

SELECT all * FROM main WHERE id = 1 or 2 or 3

you will get mysterious results because that means WHERE ((id = 1) or 2) or 3) , not what you think it does ... you need WHERE id = 1 or id = 2 or id = 3 or (reverting to yesterday's question) WHERE id IN (1,2,3)

def readdb(self,keyword,column,returncolumn = "*"):
    self.memwrite                                             # 1. 
    if isinstance(keyword, int) or isinstance(keyword,str):   # 2.
        entry = [keyword]                                     # 3.
    qmarks = ("? OR " * len(entry))[:-4]                      # 4.
    statement = 'SELECT all {0} FROM main WHERE {1} is {2}'.format(returncolumn,column,qmarks)
    print(qmarks)                                             # 5.
    self.memcursor.execute(statement, entry)
    return(self.memcursor.fetchall())
  1. Not sure what this is supposed to do. Did you mean self.memwrite()?
  2. Can be changed to if isinstance(keyword, (int,str))

    Or better yet, don't test the type. As you've written it, keyword can not be a unicode string. Why restrict like this? In this case I think it would be better to use a try...except... block to catch the subsequent error than to restrict type.

  3. So at best len(entry) = 1 . Notice also, its possible to never reach this line if keyword is not of type int or str. In that case, you would get an error on line (4) since entry would not be defined..
  4. This could also be written as

     qmarks = ' OR '.join(['?']*len(entry)) 

    It avoids the need for the somewhat magic number 4 in ("? OR " *1)[:-4] .

  5. What are you seeing here? If it was empty, that should have been a clue. Also it would be worth running print(statement) to get a full picture of what is being sent to .execute() .

  6. Perhaps try

     statement = 'SELECT {0} FROM main WHERE {1} = ?'.format( returncolumn,column) 

    In particular, the is should be changed to = .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM