简体   繁体   中英

Python SQLITE3 SELECT query with datetime calculated string not working

I have a SQLite3 DB with a table named TEST_TABLE , which looks like this:

("ID" TEXT,"DATE_IN" DATE,"WEEK_IN" number);

There are 2 entries in the table:

1|2012-03-25|13
2|2013-03-25|13

I'm trying to write a query that returns the ID for week 13 of this year. I want to use the program again next year, so I cannot hardcode "2013" as the year.

I used datetime to calculate a value for this year, creating a datetime.date object with content like this: "2013-01-01". I then converted this to a string:

this_year = (datetime.date(datetime.date.today().isocalendar()[0], 1, 1))
test2 = ("'"+str(this_year)+"'")

Then I queried the SQLite DB:

cursr = con.cursor()
con.text_factory = str
cursr.execute("""select ID from TEST_TABLE where WEEK_IN = 13 and DATE_IN > ? """,[test2])

result = cursr.fetchall()
print result

[('1',), ('2',)]

This returns the IDs 1 and 2, but this is no good, because ID 1 has '2012' as the year.

The strange thing is, if I don't use datetime for the string, but create the var manually, IT WORKS CORRECTLY.

test2 = ('2013-01-01')

cursr.execute("""select ID from TEST_TABLE where WEEK_IN = 13 and DATE_IN > ? """,[test2])
result = cursr.fetchall()
print result
[('2',)]

So why won't the query work correctly when I create the string via datetime? A string is a string, right? So what am I missing here?

Instead of converting this_year into a string, just leave it as a datetime.date object:

this_year = DT.date(DT.date.today().year,1,1)

import sqlite3
import datetime as DT

this_year = (DT.date(DT.date.today().isocalendar()[0], 1, 1))
# this_year = ("'"+str(this_year)+"'")
# this_year = DT.date(DT.date.today().year,1,1)
with sqlite3.connect(':memory:') as conn:
    cursor = conn.cursor()
    sql = '''CREATE TABLE TEST_TABLE
        ("ID" TEXT,
        "DATE_IN" DATE,
        "WEEK_IN" number)
    '''
    cursor.execute(sql)
    sql = 'INSERT INTO TEST_TABLE(ID, DATE_IN, WEEK_IN) VALUES (?,?,?)'
    cursor.executemany(sql, [[1,'2012-03-25',13],[2,'2013-03-25',13],])
    sql = 'SELECT ID FROM TEST_TABLE where WEEK_IN = 13 and DATE_IN > ?'
    cursor.execute(sql, [this_year])
    for row in cursor:
        print(row)

yields

(u'2',)

The sqlite3 database adapter will quote arguments for you when you write parametrized SQL and use the 2-argument form of cursor.execute . So you do not need (or want) to quote arguments manually yourself.

So

this_year = str(this_year)

instead of

this_year = ("'"+str(this_year)+"'")

also works, but as shown above, both lines are unnecessary, since sqlite3 will accept datetime objects as arguments as well.

also works.

Since sqlite3 automatically quotes arguments, when you manually add quotes, the final argument gets two sets of quotes. The SQL ends up comparing

In [59]: '2012-03-25' > "'2013-01-01'"
Out[59]: True

which is why both rows were (erroneously) returned.

I believe it's because of how you're creating your date in the test2 variable.

In the first example, when you use the datetime module , you accidentally introduce extra quotation marks:

>>> import datetime
>>> this_year = datetime.date(datetime.date.today().isocalendar()[0], 1, 1)
>>> test2 = "'" + str(this_year) + "'"
>>> print test2
"'2013-01-01'"

However, in your second example, you only set test2 to equal the date, which worked.

>>> test2 = '2013-01-01'
'2013-01-01'

To fix it, just modify your first example to look like this:

this_year = datetime.date(datetime.date.today().isocalendar()[0], 1, 1)
test2 = str(this_year)

As a side note, note that I've removed the parenthesis around your variables, since they were redundant.

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