1

What is the most used way to create a Sqlite query in Python?

  1. query = 'insert into events (date, title, col3, col4, int5, int6) 
        values("%s", "%s", "%s", "%s", %s, %s)' % (date, title, col3, col4, int5, int6)
    print query
    c.execute(query)
    

    Problem: it won't work for example if title contains a quote ".

  2. query = 'insert into events (date, title, col3, col4, int5, int6) 
                 values(?, ?, ?, ?, ?, ?)'
    c.execute(query, (date, title, col3, col4, int5, int6))
    

    Problem: in solution 1., we could display/print the query (to log it); here in solution 2. we can't log the query string anymore because the "replace" of each ? by a variable is done during the execute.

  3. Another cleaner way to do it? Can we avoid to repeat ?, ?, ?, ..., ? and have one single values(?) and still have it replaced by all the parameters in the tuple?

2
  • to q3, no, then sounds like your issue is query logging? Commented Mar 2, 2018 at 10:55
  • @georgexsh yes and also avoiding quotes and weird char problems Commented Mar 2, 2018 at 12:20

2 Answers 2

4

You should always use parameter substitution of DB API, to avoid SQL injection, query logging is relatively trivial by subclassing sqlite3.Cursor:

import sqlite3


class MyConnection(sqlite3.Connection):

    def cursor(self):
        return super().cursor(MyCursor)


class MyCursor(sqlite3.Cursor):

    def execute(self, sql, parameters=''):
        print(f'statement: {sql!r}, parameters: {parameters!r}')
        return super().execute(sql, parameters)


conn = sqlite3.connect(':memory:', timeout=60, factory=MyConnection)
conn.execute('create table if not exists "test" (id integer, value integer)')
conn.execute('insert into test values (?, ?)', (1, 0));
conn.commit()

yields:

statement: 'create table if not exists "test" (id integer, value integer)', parameters: ''
statement: 'insert into test values (?, ?)', parameters: (1, 0)
Sign up to request clarification or add additional context in comments.

Comments

2

To avoid formatting problems and SQL injection attacks, you should always use parameters.

When you want to log the query, you can simply log the parameter list together with the query string. (SQLite has a function to get the expanded query, but Python does not expose it.)

Each parameter markers corresponds to exactly one value. If writing many markers is too tedious for you, let the computer do it:

parms = (1, 2, 3)
markers = ",".join("?" * len(parms))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.