Python: Error in SQL Syntax - mysql

I am trying to get my Python code to count the number of records in my table. However, the Python shell keeps throwing up a "error in your SQL syntax" message. Does anyone have any ideas on what is wrong?
def count_rows(table):
cur.execute(
"SELECT COUNT(*) FROM %s",
(table,)
)
cur.connection.commit()
count_rows("home_service")

Bound parameters, such as the execute function has can only be used to represent values - not object names or syntactic elements. If you want to dynamically determine set the table name, you'd have to resort to string manipulation:
cur.execute("SELECT COUNT(*) FROM %s" % table)

Related

mysql-connector-python adds single quotes around table name when table is passed as argument. Table name comes from Flask session variable

I am new to MySQL and I am building a Flask project and using mysql.connector to query a MySQL Database. I know this question has been answered many times before but this is more specific to using MySQL with Flask.
I need to pass a query where I want to plug in the table name into the query, dynamically, depending on the value stored in the session variable in Flask. But the problem is, if I try to do:
Method 1:
cur.execute('SELECT * FROM %s;',(session['table_name'],))
the database throws an error stating that such a table is not found. However, the problem is mysql.connector keeps enclosing the table name with single quotes, hence the error.
Sample Error Statement:
mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''52_data'' at line 1
Here the table name should be 52_data and not '52_data'.
Only other workaround, I figured, is using:
Method 2:
cur.execute('SELECT * FROM '+session['table_name']+';')
which is working but it does not escape SQL Injection, I am guessing, since it's direct concatenation, unlike Method 1, where the cur.execute() function handles the escaping, as per this question.
The value being passed is stored in a sessions variable in Flask, which is not so secure, as per Miguel's Video. Hence, I want to escape that string, without triggering off an error.
Is it possible to implement Method 1 in a way that it does not add the quotes, or maybe escape the string using some function? Or maybe any other Python/Flask package that can handle this problem better?
Or if nothing works, is checking for SQL Injection manually using regex is a wiser option?
Thanks in advance.
Note: The package name for this mysql.connector is mysql-connector-python and not any other same sounding package.
For identifiers, you can use something like:
table_name = conn.converter.escape(session['table_name'])
cur.execute('SELECT * FROM `{}`'.format(table_name))
For values placeholders, you can use your Method 1, by using the parameters in the cur.execute() method. They will be escaped and quoted.
More details in https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html
NOTE: You don't need to end the SQL statements with ;

Please suggest me the right way to use python variable in sql query

I want to run below code, But I am getting syntax error.
cur.execute("USE Test") # select the database
cur.execute("SHOW TABLES")
for (table_name,) in cur:
print(table_name)
trunc_table="truncate table %s"
cur.execute(trunc_table, table_name)
con.commit()
Prepared statement parameters can only be used where SQL allows expressions. Table names are not expressions, they have to be literals in the query. You can use string formatting to substitute into the string.
trunc_table = "truncate table %s" % table_name
cur.execute(trunc_table)
Also, I think you need to use a different cursor to execute the second query while you're looping through the results of the first query. So before the loop, do:
cur2 = connection.cursor()
cur2.execute("USE Test")
and then use
cur2.execute(trunc_table)
in the loop. Another option would be to use cur.fetchall() to get all the rows first, then you can reuse the cursor.
for (table_name,) in cur.fetchall():

MySQL SUM(BIGINT) query returns bytearray instead of BIGINT, but only when called as a prepared statement

I have the following MySQL query:
SELECT COUNT(billable_size),
SUM(billable_size),
MIN(billable_size),
MAX(billable_size)
FROM inv_files
WHERE billable_size >= %s
AND billable_size < %s
The billable_size column is a BIGINT, and the SUM() of its values can get anywhere up to about 1e+14.
When I run this query using simple string interpolation --
cursor = cnx.cursor()
cursor.execute(query_sql % (from_size, to_size))
-- MySQL Connector/Python correctly returns the sum value as a Python Decimal.
But when I try to run it as a prepared statement --
cursor = cnx.cursor(prepared=True)
cursor.execute(query_sql, (from_size, to_size))
-- the sum instead gets returned as a bytearray, causing any number of headaches. (Apparently there are some known issues with MySQL returning byte arrays when it should return something else? Maybe I should count myself lucky it works with plain string interpolation.)
Is there a SQL "type hint" or some other way I can get MySQL Connector/Python to correctly return the right type?

Getting "could not run statement: Incorrect string value:" error when trying to insert Chinese to MySQL via dbExecute()

I am using R (IDE:RStudio) to insert some data back to MySQL via DBI.dbExecute.
the SQL as follows:
"INSERT INTO t_tmp(AnalysisDate, Dimension, Indicator, IndicatorType, Value) VALUES('2016-01-17', '维度1', '指标1', '指标类型', 101) ON DUPLICATE KEY UPDATE Value = 101;"
in which "Dimension","Indicator","IndicatorType" are Chinese.
when running DBI.dbExecute, I get the error message:
"Error in .local(conn, statement, ...) :
could not run statement: Incorrect string value: '\xB6\xC81' for column 'Dimension'"
I am trying to paste the SQL to mySQL CLI, and works out just fine(MySQL encoding has set to UTF-8).
How can I fix this problem? Thanks!
I have solved this problem. The problem is still Encoding. My MySQL's encoding is "UTF-8", so after you construct your SQL, transfer it Encoding to "UTF-8" using iconv(...), then pass it to the dbSendQuery or dbExecute function. then codes are like: statement = "[your sql here with/ without Unicode characters like Chinese]"; statement = iconv(x = statement, to = "UTF-8"); dbSendQuery(conn, statement). hope this helps

I was trying to concatenate 3 columns in SQL from dbvisualizer

I was trying to concatenate 3 columns in SQL, but I getting error message as
1) [Error Code: -440, SQL State: 42884] DB2 SQL error: SQLCODE:
-440, SQLSTATE: 42884, SQLERRMC: CONCAT;FUNCTION. 2) [Error Code: -727, SQL State: 56098] DB2 SQL error: SQLCODE: -727, SQLSTATE: 56098, SQLERRMC: 2;-440;42884;CONCAT|FUNCTION
This is my query
select concat(number,ID,name) as MemberDetails from Member where number = '123'
This looks like a problem with the schema. Specifically, it involves functions and procedures.
You have two SQL return codes, both of which are errors. The two codes are
-440: Routine &1 in &2 not found with specified parameters. A function or procedure with the specified name and compatible arguments was not found
and
-727: There actually isn't an error code named this. Did you mean -747?
In SQL, a negative number represents an unsuccessful call with an error.
You need a separate alias name. Also you might want to add the alias before the column name just in case there's disambiguation. Here's what it should look like.
select concat(number,ID,name) as M from Member where M.number = '123'
If neither of them worked, it is a problem with the SCHEMA, not with the above query.