1

I want to query a sqlite database using a f-string for the query, it is supposed to return a small description given a specific id that i stored in a local variable var. However some fields will be empty for some values of the variable. I'm specially interested in the value 0 has it will always return an empty description and is an isolated case that needs to be addressed differently from other values.

I want to iterate through a range until I find a not empty description field. Here is an example:

var = str(self.some_global_variable)  # In this case consider var = '0'

query = f'my sql query goes here WHERE this_id={var}'

description = self.function_to_fetch_db(query)

while not description and var == '0':
   for i in range (1, 31):
      var = str(i)
      description = self.function_to_fetch_db(query)
      print(description, var)
      print(query)

The output of this will be something like:

[] 1
my sql query goes here WHERE this_id=0
[] 2
my sql query goes here WHERE this_id=0
[] 3
my sql query goes here WHERE this_id=0
.
.
.

The local variable is updated but the query always keeps the original value from outside the while loop.

I also tried an if...else instead of the while loop but the result is the same. I don't think the SQLite part of the problem is relevant, it's just to illustrate my specific case, the query works for other values. I'm just having trouble to figure out this local variable and f-string relationship.

Hugo
  • 89
  • 1
  • 6
  • Does `print(query)` print a different query for each loop? – Magofoco Nov 23 '19 at 16:39
  • 2
    See also: [Why don't f-strings change when variables they reference change?](https://stackoverflow.com/questions/41306928/why-dont-f-strings-change-when-variables-they-reference-change) – Mark Nov 23 '19 at 16:45
  • No, ```print(query)``` will be ```my sql query goes here WHERE this_id=0```, following bereal's suggestion of moving the query inside the loop fixed it though and I can see why based on the link Mark posted (sorry, somehow missed that question when searching this but it really makes sense now). – Hugo Nov 23 '19 at 19:08

2 Answers2

4

There are two answers to your questions: the first one is formal, the second one is correct.

The formal answer: the string is computed once before the loop in your case. If you want it to alter it for every value, move it inside:

for i in range(31):
    query = f'my sql query goes here WHERE this_id={i}'
    description = self.function_to_fetch_db(query)

The correct answer: use parameterized queries instead, that will look like:

 conn.execute('my sql query goes here WHERE this_id=?', (i,))

(The substitution syntax may vary depending on your database / driver.)

bereal
  • 32,519
  • 6
  • 58
  • 104
1

you could use a named variable in a string:

var = str(self.some_global_variable)  # In this case consider var = '0'

fquery = 'my sql query goes here WHERE this_id={var}'

description = self.function_to_fetch_db(fquery.format(var=var))

while not description and var == '0':
    for i in range(1, 31):
        query = fquery.format(var=i)
        description = self.function_to_fetch_db(query)
        print(description, i)
        print(query)
daveg
  • 535
  • 2
  • 10