Python - MySQLi parametized query with %d - mysql

This might be a question that has already been answered but I haven't found anything relating to it.
I think I might have a unique scenario, I need to add a parameter to the query for the LIMIT clause. Stack Overflow consider:
query = "SELECT * FROM `v_someview` WHERE `id` = %s LIMIT %s;"
x.execute(query,(str(id_variable),str(limit_variable))
Now it comes back with:
You have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use
near ''5'' at line 1
Am I supposed to use %d or is this specific use discouraged?
Note: the field from which this limit variable I drawn is a tinyint, so I don't see anyway for an SQL injection attack but I would still like to use parametized query with it.
Use with %d stops execution and bypasses the catch block:
try:
query = """SELECT * FROM `v_someview` WHERE `id` = %s LIMIT %d;"""
x.execute(query,(str(id),int(l)))
except Exception as ex:
#some code
The library in use is MySQLi.
Variable 'x' is a cursor.
Variable 'id_variable' is an int with the id

Just solved it myself by using:
try:
query = """SELECT * FROM `v_someview` WHERE `id` = %s LIMIT %s;"""
x.execute(query,(str(id),int(l)))
except Exception as ex:
#some code
So I'm declaring that i'm going to use a string (%s) but casting that parameter to an int().

Related

MySQL rejecting date

MySQL 8
My query:
"UPDATE `users` SET `start_date` = '2007-04-09' AND `eligibility` = 1 WHERE `user_id` = 36;
I am getting the following error:
Warning: #1292 Truncated incorrect DOUBLE value: '2007-04-09'
I checked the type for the start_date field and it it set to date.
When I check the row, I find that it has NOT been modified, even though this is a warning.
I am using the PHPMyAdmin interface to interact with the MySQL DB/Server.
Any ideas?
ANSWER:
The answer is that I used an AND statement, instead of a comma. I have not used MySQL for a while. I use ORM instead, so I did not notice the error, and the error message threw me off.
You are setting start_date to:
'2007-04-09' AND `eligibility` = 1
You need a comma instead of AND there if you want to set eligibility too.
That specific message comes because '2007-04-09' AND interprets that string as a Boolean, which it is calling a DOUBLE.

MySQL code to insert a username and password into a table if a licencing key exists in that table

I am trying to accomplish a simple licensing system in golang and have tried numerous ways to get it to work. Basically, I have input a couple of random licensing keys into my database and my golang program should check to see if the user-input key exists and if it does then add the user specified username and password into the database to login later.
This is the code that I have that hasn't been working:
"IF EXISTS (SELECT * FROM login WHERE LK = "+reglicenceEntry.Text()+") THEN
INSERT INTO `login` (`Username`, `Password`, `LK`) VALUES
('"+regusernameEntry.Text()+"', '"+regpasswordEntry.Text()+"', ''); "
This is the golang error:
Error 1064: 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 'IF EXISTS (SELECT * FROM login WHERE LK = '5qp515YHXEmSDzwqgoJh') THEN INSERT IN' at line 1
Thanks so much!
MySQL syntax doesn't support IF...THEN constructs except within stored routines and triggers and events. See https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-compound-statements.html
I suggest an alternative solution for your code:
INSERT INTO `login` (`Username`, `Password`, `LK`)
SELECT ?, ?, ''
FROM `login`
WHERE `LK` = ?
LIMIT 1
If your login table does not have the LK value, the SELECT above will return 0 rows, therefore it will not insert anything.
If your login table has the LK value, the SELECT above will return at least 1 row (and I limit it to 1), therefore it will insert a row. The row it inserts is comprised of your username and password, and a blank string for the LK.
I showed use of parameter placeholders. You should use parameters in SQL instead of concatenating variables into your query. This is good practice to avoid accidental SQL injection. See http://go-database-sql.org/prepared.html for examples.
The purpose of using parameters is to avoid SQL injection problems. See my answer to What is SQL injection? for an explanation of SQL injection.
Or my presentation SQL Injection Myths and Fallacies (or youtube video).
When using parameters, you do two steps.
The first step to prepare a query with placeholders (?) where you would otherwise concatenate variables into your SQL query.
The second step is to execute the prepared query, and this is the time you pass the variables to fill in the placeholders.
The point is to keep variables separate from your query, so if there's anything in the variable that could unintentionally change your SQL syntax (like imbalanced quotes), it is never combined with the SQL. After you do the prepare, the SQL has already been parsed by the MySQL server, and there's no way to change the syntax after that.
MySQL remembers which parts of the query need to be filled in, and when you pass variables during the execute step, MySQL fills in the missing parts of the query using your values — but this happens within the MySQL server, not in your application.
Thus the dynamic parts of the query — your variables — are kept separate from the SQL syntax and you avoid SQL injection problems.
For your task described in your question, it would look something like this (I have not tested this Go code, but it should put you on the right path).
stmt, err := tx.Prepare("INSERT INTO `login` (`Username`, `Password`, `LK`) SELECT ?, ?, '' FROM `login` WHERE `LK` = ? LIMIT 1")
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
_, err = stmt.Exec(regusernameEntry.Text(), regpasswordEntry.Text(), reglicenceEntry.Text())
if err != nil {
log.Fatal(err)
}
The order of parameters is important. The variables you pass to Exec() must be in the same order that the ? placeholders appear in your prepared SQL statement. They are matched up, one for one, in the same order, by the MySQL server.
Do not put quotes around the placeholders in your prepared SQL statement. That will work as a literal string '?' in SQL. Use an unquoted ? character for a placeholder. When it gets combined by MySQL in the server, it will work as if you had put quotes around the value like a string — but with no risk of SQL injection even if that string value containing special characters.
Here's another site that gives more code examples: https://github.com/go-sql-driver/mysql/wiki/Examples
The Exec() function is for executing SQL that has no result set, like INSERT, UPDATE, DELETE. There are other functions in the Go SQL driver like Query() and QueryRow() that also accept parameter arguments. You'd use these if your SQL returns a result set.

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?

Using MySQL in R - getting error trying to return variable as column

I have used the dbConnect and RMySQL packages to successfully connect to my company's database with R. However, I am struggling to run a query in R and am obtaining a frustrating error. The query works in the MySQL Workbench app that I use day to day, hence the frustration that it won't work in R. Here is a snippet of the SQL query:
USE mydb;
SELECT #theDate := '2017-05-03';
SELECT
#theDate AS today,
a.user_id AS user_id,
...
...
These are the first few lines of the query, and also the part of the query causing the error in R. I receive the following error:
my_query = " USE mydb;
SELECT #theDate := '2017-05-03';
SELECT
#theDate AS today,
a.user_id AS user_id,
...
... "
my_db = dbConnect(MySQL(), ...)
requested_query = dbSendQuery(my_db, my_query)
Error in .local(conn, statement, ...) :
could not run statement: 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 'SELECT
#theDate AS today,
a.user_id AS user_id,' at line 3
Sorry I cannot provide more reproducible code, but that would involve connecting to the company database and I can't share the database info.
Last comment - I believe the line has to do with the SELECT #theDate: := '2017-05-03'; line. This query was written by my coworker, not myself, and I hadn't before seen 2 select statements used like this before in a query. What's happening in the MySQL Workbench app is that #theDate is essentially a variable set to '2017-05-03'. The first column of the table returned by the query is all '2017-05-03'
Like I said, the query works in MySQL Workbench, but not in R. Quite frustrating. Any suggestions are appreciated!
Thanks!
EDIT - Realizing that this is more a question in trying to understand how setting variables works in SQL. Like I said I hadn't seen this before, but the first SELECT query is setting a variable and then the 2nd SELECT query uses that variable. Is this allowed? I wonder why its allowed in MYSQL Workbench but not R... still frustrating
I believe you cannot execute more than 1 sql query in a single dbSendQuery() call and this causes the error message.
Either execute the 2 queries separately or assign value to the session variable within the 2nd select:
SELECT #theDate := '2017-05-03' AS today, ....

Special Characters in Scriptella, jexl

I want to extract a text field from a database and insert it into some other database. So while extracting I used the REPLACE(message_text,'\'', '"') while selecting the test. I gave me an error. I changed that from my select statement and did it while initiating the global variable.
etl.globals['message_text'] = message_text;
still I'm getting an error at the insert statement
insert into lcs_al_user_likes(user_id,liked_user_id,post_content,loop_id) values('${etl.globals['posted_by']}','${etl.globals['liked_user_id']}','${etl.gl‌​obals['message_text']}',?batchLoopCounter);
saying
*You have an error in your SQL syntaxcheck the manual that corresponds to your MySQL server version for the right syntax to use near 'message_text']}')' at line 1*
I think it is not getting the global variable. That I say because when i print its value using log it just gives me
${etl.globals['message_text']}
as output. So please help me out here.
<query connection-id="lcsDBConnection">
SELECT forum_topic_post_id AS forum_topic_post_id, posted_by AS posted_by,message_text as message_text FROM lcs_tbl_forum_topic_post WHERE like_count>0 LIMIT ?batchSize OFFSET ?queryCounter ;
<script connection-id="jexl">
etl.globals['forum_topic_post_id'] = forum_topic_post_id;
etl.globals['posted_by'] = posted_by;
etl.globals['message_text'] = message_text.replace('\'', '"');
</script>
It looks like the problem is in INSERT statement, you should use prepared statement
parameters escaping:
INSERT INTO lcs_al_user_likes(user_id,liked_user_id,post_content,loop_id) values(?{etl.globals['posted_by']},?{etl.globals['liked_user_id']},?{etl.gl‌​obals['message_text']},?batchLoopCounter);
BTW As I understand, your original problem was quotes breaking the insert statement, so in this case with ?{parameter} syntax you don't need to use replace(...) function at all.