473,398 Members | 2,165 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,398 software developers and data experts.

help with mysql cursor.execute()

I have been trying to pass parameters as indicated in the api.
when I use:

sql= 'select * from %s where cusid = %s ' % name,recID)
Cursor.execute(sql)

it works fine, but when I try :

sql= 'select * from %s where cusid like %s '
Cursor.execute(sql,(name,recID))

or

sql= 'select * from ? where cusid like ? '
Cursor.execute(sql,(name,recID))

it fails.

Can someone help me with the semantics of using parameterized queries?

Bill
Aug 14 '05 #1
7 8628
William Gill wrote:
I have been trying to pass parameters as indicated in the api.
when I use:
sql= 'select * from %s where cusid = %s ' % name,recID)
Cursor.execute(sql)
it works fine, but when I try :
sql= 'select * from %s where cusid like %s '
Cursor.execute(sql,(name,recID))
or
sql= 'select * from ? where cusid like ? '
Cursor.execute(sql,(name,recID))
it fails.
Can someone help me with the semantics of using parameterized queries?


Neither column names nor table names can be parameters to
fixed SQL. Values are what you fiddle with. This squares with
the DBMS being allowed to plan the query before looking at the
parameters (deciding which indices to use, which tables to join
first, ...), then reusing the plan for identical queries with
different values. MySQL may not take advantage of this two-step
approach, but the DB interface is designed to allow it, so
the parameterization is constrained.

See if something like this works:

sql = 'select * from %s where cusid like ? ' % name
Cursor.execute(sql, (recID,))

--Scott David Daniels
Sc***********@Acm.Org
Aug 14 '05 #2
I have been testing and it seems that:

1- Cursor.execute does not like '?' as a placeholder in sql

2- Cursor.execute accepts '%s' but puts the quotation mark around the
substitution.

sql = 'select * from %s where cusid = ? ' % name
Cursor.execute(sql, (recID,))

still fails, but:

sql = 'select * from basedata where cusid = %s '
Cursor.execute(sql, (recID,))

works regardless of recID being a string or an int. Obviously this
stems from trying to parameterize the table name.

If I use:

sql = 'select * from %s where cusid = %%s ' % name
Cursor.execute(sql, (recID,))

It makes 1 substitution in the first line, and another in the execute()

sql = 'select * from %s where cusid = %%s ' % name
# sql now == 'select * from basedata where cusid = %s '
Cursor.execute(sql, (recID,))

and it works.

Between your comments re: column names and table names , and the notes
in cursor.py, I was able to figure it out.

FYI I wanted to create a tableHandler class that could be extended for
individual tables. That's why the query needs to accept variables for
tablename.

Thanks.

Bill

Scott David Daniels wrote:
William Gill wrote:
I have been trying to pass parameters as indicated in the api.
when I use:
sql= 'select * from %s where cusid = %s ' % name,recID)
Cursor.execute(sql)
it works fine, but when I try :
sql= 'select * from %s where cusid like %s '
Cursor.execute(sql,(name,recID))
or
sql= 'select * from ? where cusid like ? '
Cursor.execute(sql,(name,recID))
it fails.
Can someone help me with the semantics of using parameterized queries?

Neither column names nor table names can be parameters to
fixed SQL. Values are what you fiddle with. This squares with
the DBMS being allowed to plan the query before looking at the
parameters (deciding which indices to use, which tables to join
first, ...), then reusing the plan for identical queries with
different values. MySQL may not take advantage of this two-step
approach, but the DB interface is designed to allow it, so
the parameterization is constrained.

See if something like this works:

sql = 'select * from %s where cusid like ? ' % name
Cursor.execute(sql, (recID,))

--Scott David Daniels
Sc***********@Acm.Org

Aug 14 '05 #3
William Gill wrote:
I have been testing and it seems that:

1- Cursor.execute does not like '?' as a placeholder in sql
The particular format required by each DBI-compatible module should be
available as the module's "paramstyle" variable. mxODBC, for example,
uses the "qmark" style, but MySQLdb uses "format".
2- Cursor.execute accepts '%s' but puts the quotation mark around the
substitution.

sql = 'select * from %s where cusid = ? ' % name
Cursor.execute(sql, (recID,))

still fails, but:

sql = 'select * from basedata where cusid = %s '
Cursor.execute(sql, (recID,))

works regardless of recID being a string or an int. Obviously this
stems from trying to parameterize the table name.
That's correct, as Scott has pointed out (with a good explanation of why).
If I use:

sql = 'select * from %s where cusid = %%s ' % name
Cursor.execute(sql, (recID,))

It makes 1 substitution in the first line, and another in the execute()

sql = 'select * from %s where cusid = %%s ' % name
# sql now == 'select * from basedata where cusid = %s '
Cursor.execute(sql, (recID,))

and it works.
That's right: you are now building a table-dependent query (i.e. the
table name is hard-wired in the SQL string) parameterized to the
required value for cusid.
Between your comments re: column names and table names , and the notes
in cursor.py, I was able to figure it out.

FYI I wanted to create a tableHandler class that could be extended for
individual tables. That's why the query needs to accept variables for
tablename.
You might want to take a look at how some existing object-mappers
achieve this - Ian Bicking's sqlobject module might be a good place to
start.

regards
Steve

Thanks.

Bill

Scott David Daniels wrote:
William Gill wrote:

I have been trying to pass parameters as indicated in the api.
when I use:
sql= 'select * from %s where cusid = %s ' % name,recID)
Cursor.execute(sql)
it works fine, but when I try :
sql= 'select * from %s where cusid like %s '
Cursor.execute(sql,(name,recID))
or
sql= 'select * from ? where cusid like ? '
Cursor.execute(sql,(name,recID))
it fails.
Can someone help me with the semantics of using parameterized queries?

Neither column names nor table names can be parameters to
fixed SQL. Values are what you fiddle with. This squares with
the DBMS being allowed to plan the query before looking at the
parameters (deciding which indices to use, which tables to join
first, ...), then reusing the plan for identical queries with
different values. MySQL may not take advantage of this two-step
approach, but the DB interface is designed to allow it, so
the parameterization is constrained.

See if something like this works:

sql = 'select * from %s where cusid like ? ' % name
Cursor.execute(sql, (recID,))

--Scott David Daniels
Sc***********@Acm.Org

--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Aug 15 '05 #4


Steve Holden wrote:
William Gill wrote:
I have been testing and it seems that:

1- Cursor.execute does not like '?' as a placeholder in sql
The particular format required by each DBI-compatible module should be
available as the module's "paramstyle" variable. mxODBC, for example,
uses the "qmark" style, but MySQLdb uses "format".
2- Cursor.execute accepts '%s' but puts the quotation mark around the
substitution.

sql = 'select * from %s where cusid = ? ' % name
Cursor.execute(sql, (recID,))

still fails, but:

sql = 'select * from basedata where cusid = %s '
Cursor.execute(sql, (recID,))

works regardless of recID being a string or an int. Obviously this
stems from trying to parameterize the table name.

That's correct, as Scott has pointed out (with a good explanation of why).
If I use:

sql = 'select * from %s where cusid = %%s ' % name
Cursor.execute(sql, (recID,))

It makes 1 substitution in the first line, and another in the execute()

sql = 'select * from %s where cusid = %%s ' % name
# sql now == 'select * from basedata where cusid = %s '
Cursor.execute(sql, (recID,))

and it works.

That's right: you are now building a table-dependent query (i.e. the
table name is hard-wired in the SQL string) parameterized to the
required value for cusid.
Between your comments re: column names and table names , and the notes
in cursor.py, I was able to figure it out.

FYI I wanted to create a tableHandler class that could be extended for
individual tables. That's why the query needs to accept variables for
tablename.

You might want to take a look at how some existing object-mappers
achieve this - Ian Bicking's sqlobject module might be a good place to
start.


I also might want to take a tutorial on searching. This looks like it
could have saved me lots of wheel re-inventing.

Thanks,

Bill

regards
Steve

Thanks.

Bill

Scott David Daniels wrote:
William Gill wrote:
I have been trying to pass parameters as indicated in the api.
when I use:
sql= 'select * from %s where cusid = %s ' % name,recID)
Cursor.execute(sql)
it works fine, but when I try :
sql= 'select * from %s where cusid like %s '
Cursor.execute(sql,(name,recID))
or
sql= 'select * from ? where cusid like ? '
Cursor.execute(sql,(name,recID))
it fails.
Can someone help me with the semantics of using parameterized queries?

Neither column names nor table names can be parameters to
fixed SQL. Values are what you fiddle with. This squares with
the DBMS being allowed to plan the query before looking at the
parameters (deciding which indices to use, which tables to join
first, ...), then reusing the plan for identical queries with
different values. MySQL may not take advantage of this two-step
approach, but the DB interface is designed to allow it, so
the parameterization is constrained.

See if something like this works:

sql = 'select * from %s where cusid like ? ' % name
Cursor.execute(sql, (recID,))

--Scott David Daniels
Sc***********@Acm.Org


Aug 15 '05 #5
On Sun, 14 Aug 2005 19:28:04 GMT, William Gill <no*****@gcgroup.net>
declaimed the following in comp.lang.python:
I have been trying to pass parameters as indicated in the api.
when I use:

sql= 'select * from %s where cusid = %s ' % name,recID)
Cursor.execute(sql)

it works fine, but when I try :

sql= 'select * from %s where cusid like %s '
Cursor.execute(sql,(name,recID))
Hypothesis: the database TABLE may need to be filled in externally.
..execute() parsing is designed to properly quote arguments for data
fields where needed.

I suspect you are getting quote marks around the table name, which
is not a position they are expected.

You'll likely have to use a two-step process: use string formatting
to fill in table and field names (if you are getting those from user
input, you'll have to validate that there isn't an injection attack --
ie, user didn't enter "name; delete from name" as the table to be
processed); then use .execute() to pass the field values.

If using MySQLdb, you could always read the source files... (Though,
unfortunately, the very bottom is a compiled library and hence
unreadable...
You'll find .execute() invokes an .escape()

Py> escape(...)
Py> escape(obj, dict) -- escape any special characters in object
obj
Py> using mapping dict to provide quoting functions for each
type.
Py> Returns a SQL literal string.

Note the last line: it returns a "literal string" -- in the form
needed to pass /data/. That won't work for field and table names, and
MySQLdb doesn't attempt any semantic parsing to find out is being
substituted -- if just converts (escapes) ALL parameters based on
datatype, THEN does a normal Python string formatting operation.
-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Aug 15 '05 #6

Dennis Lee Bieber wrote:
On Sun, 14 Aug 2005 19:28:04 GMT, William Gill <no*****@gcgroup.net>
declaimed the following in comp.lang.python:

I have been trying to pass parameters as indicated in the api.
when I use:

sql= 'select * from %s where cusid = %s ' % name,recID)
Cursor.execute(sql)

it works fine, but when I try :

sql= 'select * from %s where cusid like %s '
Cursor.execute(sql,(name,recID))

Hypothesis: the database TABLE may need to be filled in externally.
.execute() parsing is designed to properly quote arguments for data
fields where needed.

I suspect you are getting quote marks around the table name, which
is not a position they are expected.


From my testing, your suspicion is correct, as is your suggestion.

sql = 'select * from %s where cusid = %%s ' % tablename
Cursor.execute(sql, (recID,))

works,

Bill You'll likely have to use a two-step process: use string formatting
to fill in table and field names (if you are getting those from user
input, you'll have to validate that there isn't an injection attack --
ie, user didn't enter "name; delete from name" as the table to be
processed); then use .execute() to pass the field values.

If using MySQLdb, you could always read the source files... (Though,
unfortunately, the very bottom is a compiled library and hence
unreadable...
You'll find .execute() invokes an .escape()

Py> escape(...)
Py> escape(obj, dict) -- escape any special characters in object
obj
Py> using mapping dict to provide quoting functions for each
type.
Py> Returns a SQL literal string.

Note the last line: it returns a "literal string" -- in the form
needed to pass /data/. That won't work for field and table names, and
MySQLdb doesn't attempt any semantic parsing to find out is being
substituted -- if just converts (escapes) ALL parameters based on
datatype, THEN does a normal Python string formatting operation.

Aug 16 '05 #7
On Mon, 15 Aug 2005 22:03:05 GMT, Dennis Lee Bieber
<wl*****@ix.netcom.com> declaimed the following in comp.lang.python:
On Sun, 14 Aug 2005 19:28:04 GMT, William Gill <no*****@gcgroup.net>
declaimed the following in comp.lang.python:
My apologies for the late posting... I forgot to log in to send the
message(s)...

I ordered an upgrade from (unlimited) dial-up to DSL; the DSL
includes 20-hrs of dial-up for roaming. Problem is that I suspect the
20-hrs took effect immediately, but I won't have the DSL hardware and
activated line for another two weeks...
-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Aug 16 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Randy Rodent | last post by:
I have a problem with some SQL code that can be run at the mySQL command prompt, and in PHP, I can prepare it with no problem, but I get a syntax error when I try and exexute it. $sql = <<< EOF...
2
by: Tim Williams | last post by:
I'm trying to write a simple python program to access a MySQL database. I'm having a problem with using MySQLdb to get the results of a SQL command in a cursor. Sometimes the cursor.execute works,...
5
by: What-a-Tool | last post by:
What is the proper format for my SQL str using command.execute? Even though I know I have matching data in my table, I keep coming up with a ..RecordCount of -1. What am I doing wrong? Thanks in...
4
by: Schorschi | last post by:
I am trying to mimic the following (which works) but Use the stock GetManifestResourceStream route. For example Public Declare Unicode Function LoadCursorFromFile Lib "USER32.DLL" Alias...
8
by: johnlichtenstein | last post by:
I am using cx_Oracle and MySQLdb to pull a lot of data from some tables and I find that the cursor.execute method uses a lot of memory that never gets garbage collected. Using fetchmany instead of...
2
by: Florian Lindner | last post by:
Hello, I have a function that executes a SQL statement with MySQLdb: def executeSQL(sql, *args): print sql % args cursor = conn.cursor() cursor.execute(sql, args) cursor.close() it's...
5
by: Florian Lindner | last post by:
Hello, I have a string: INSERT INTO mailboxes (`name`, `login`, `home`, `maildir`, `uid`, `gid`, `password`) VALUES (%s, %s, %s, %s, %i, %i, %s) that is passed to a MySQL cursor from MySQLdb:...
0
by: gpspocket | last post by:
help me -CURSOR backward insert from End Date > to Start Date how to insert dates from end to start like this SELECT 111111,1,CONVERT(DATETIME, '17/03/2008', 103), CONVERT(DATETIME,...
1
by: theschaef | last post by:
Hi there. I am using perl to connect to a database and then pull the rows off of the table one by one to manipulate the data. If I use a smaller table (~8 MB), I wait for around 20 seconds but...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.