O problema é que
('hello')
é uma string e ('hello',)
é uma tupla . Você precisa sempre passar uma tupla (ou outra coleção, como uma lista) como os valores para seus espaços reservados. O motivo é que seus espaços reservados são posicionais em sua consulta, então os argumentos também devem ter alguma ordem - e tuplas e listas são duas maneiras de obter uma seleção ordenada de objetos. Como está esperando uma tupla ou outra coleção,
106
é convertido para [1, 0, 6]
. Se você passar (106,)
, ele será interpretado corretamente. Nos bastidores, isso é o que está acontecendo:
>>> for i in '106':
... print(i)
...
1
0
6
>>> for i in ('106',):
... print(i)
...
106
Então, seu 'hack' é na verdade a solução correta, você só não precisa da variável extra:
q = 'SELECT Last_Request_Time FROM Products WHERE idProduct = %s'
cursor.execute(q, (idProduct,))