Python , MYSQL database - python

i have a table that records the attendance of students. The table have 4 columns , one for the student ID and the other are for week1 ,week2 and week3 (All the columns are integers). The attendance is recorded by entering only 1 for the certain week ( or zero if he was absent) . My problem is here , when i want to add the attendance i use the update statement as follow :
week_number=input('enter the week ( week1/week2/week3')
id=int(input('enter student ID'))
sat="UPDATE Attendance2 SET %s=1 WHERE ID=%s "
cur.execute(sat, (week_number,id,))
conn.commit()
As you can see ,I don't know what the column that the user will refer to ( it is a variable ) , so i have used %s behind the SET, but it is wrong.
Here is the error :
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 ''week1'=1 WHERE ID=300' at line 1
Any help please ? How do i write a variable column name in a execute statement ?
Note that i am updating only the attended students , that's why there is 1 in the UPDATE statement

AFAICT, it's supposed to be ok to surround keys with quotes. But as you say that all datatypes are integers, your values have no issues.
And because it says this is a syntax error (and not column issue, what it would yell if it was not finding week1), it leads me to believe the issues actually are your quotes, which if not expected by mysql's SQL grammar, it would indeed yell about a syntax issue.
mysql […] near ''week1'=1 WHERE ID=300' at line 1
^
What makes a python string gets surrounded by single quotes? It's the repr() version of the string, the one you get when you type a string on the REPL:
>>> x = '42'
>>> x
'42'
>>> print(repr(x))
'42'
>>> print(x)
42
I'm not sure why this issue would happen to you. A good ideais to use the python form of formatting strings, and run:
sat="UPDATE Attendance2 SET {}=1 WHERE ID={}".format(week_number, id)
if it still happens, you can try to force typing of week_number into a str(), using str(week_number).
Talking about formatting strings, you might want to enforce the typing, so you avoid surprises:
sat="UPDATE Attendance2 SET {:s}=1 WHERE ID={:d}".format(str(week_number), int(id))
which will make sure week_number is a valid string and formatted as a string, and id is a valid integer and formatted as an integer.
Nota Bene: avoid using id in your code, which is a python reserved keyword, and instead use _id, ident or idx. It's always a good idea to avoid shadowing global python keywords.
HTH

try
sat="UPDATE Attendance2 SET " + week_number + "='1' WHERE ID='" + student_id + "'"
cur.execute(sat)
...
hope this helps ^^-d
PS: It is easier to test the code if you set the variables week_number and student_id "hardwired", e.g.:
week_number = "week1"
student_id = "1"
PPS: The way you design your table is a bit redundant which may lead to update errors in the future. It might e.g. be better to have a 2 column table with the student_id and attended_week(as 1,2,3).

Related

sqlite3.OperationalError: near "values" syntax error [duplicate]

I'm trying out statements for creating a database, and after 10 entities without any issues I ran into this error
Error: Near line 83: near "Transaction": syntax error
The first line is line 83 with it's context of creating a table
CREATE TABLE Transaction (
TransactionID INTEGER,
AccountID INTEGER REFERENCES User (AccountID),
ItemID INTEGER REFERENCES Item (ItemID),
Method STRING,
Price INTEGER,
TransactionDate DATE,
PRIMARY KEY (TransactionID)
);
Now I can't seem to find the issue, and suggestion's of something with ASCII using the wrong space couldn't be solved by writing the same thing again manually.
I haven't even gotten around to checking the integrity of my foreign keys, and it's not working. Hopefully somebody could provide some insight on what I'm missing.
Transaction is one of the reserved names in SQLite. For a full list see here.
Ways to solve this issue are:
Change the Table name to a word that isn't reserved.
or
Quote the reserved name by using one of these 4 listed quote marks
'keyword'
"keyword"
[keyword]
`keyword`

Given table and column name, how to test if INSERT needs quotes ('') around the values to be inserted?

I have a dictionary of column name / values, to insert into a table. I have a function that generates the INSERT statement. I'm stuck because the function always puts quotes around the values, and some are integers.
e.g. If column 1 is type integer then the statement should be INSERT INTO myTable (col1) VALUES 5; vs
INSERT INTO myTable (col1) VALUES '5'; second one causes an error saying column 5 does not exist.
EDIT: I found the problem (I think). the value was in double quotes not single, so it was "5".
In Python, given a table and column name, how can I test if the INSERT statement needs to have '' around the VALUES ?
This question was tagged with "psycopg2" -- you can prepare the statement using a format string and have psycopg2 infer types for you in many cases.
cur.execute('INSERT INTO myTable (col1, col2) VALUES (%s, %s);', (5, 'abc'))
psycopg2 will deal with it for you, because Python knows that 5 is an integer and 'abc' is a string.
http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries
You certainly want to use a library function to decide whether or not to quote values you insert. If you are inserting anything input by a user, writing your own quoting function can lead to SQL Injection attacks.
It appears from your tags that you're using psycopg2 - I've found another response that may be able to answer your question, since I'm not familiar with that library. The main gist seems to be that you should use
cursor.execute("query with params %s %s", ("param1", "pa'ram2"))
Which will automatically handle any quoting needed for param1 and param2.
Although I personally don't like the idea, you can use single quotes around integers when you insert in Postgres.
Perhaps your problem is the lack of parentheses:
INSERT INTO myTable(col1)
VALUES('5');
Here is a SQL Fiddle illustrating this code.
As you note in the comments, double quotes do not work in Postgres.
You can put always the single quote (be careful, if the value contents a quote you must double it: insert into example (value_t) values ('O''Hara');
You can decide checking the value that you want to insert regardles of the type of de destination
You can decide checking the type of the target field
As you can see in http://sqlfiddle.com/#!15/8bfbd/3 theres no mater with inserting integers into a text field or string that represents an integer in a numeric field.
To check the field type you can use the information_schema:
select data_type from information_schema.columns
where table_schema='public'
and table_name='example'
and column_name='value_i';
http://sqlfiddle.com/#!15/8bfbd/7

Sqlite3 Updating Row Defined by a Variable

Not sure if I phrased the title correctly, but basically my question is is it possible to have sqlite update a row which is defined by a variable? For example:
db.execute('''UPDATE CUSTOMER SET ? = ? WHERE CUSTOMER_ID = ?''', (title, info.get(), k))
where 'title' (the first question mark) is the name of the 'row' I want to update within the table Customer. I have tried the above code but it doesn't work. Does anybody know if it is possible to do this with sqlite3 in any way?
SQL parameters are designed to never be interpretable as SQL objects (like column names); that is one of their major usecases. If they didn't they wouldn't prevent SQL injection attacks. Instead, the title value is either properly escaped as a value, or rejected altogether as the syntax doesn't allow a value in that location.
As such, you need to make sure that your title variable is a proper SQL object name (never take user input directly here) and use string formatting for just that value:
db.execute(
'''UPDATE CUSTOMER SET {} = ? WHERE CUSTOMER_ID = ?'''.format(title),
(info.get(), k))
You probably want to match title against a pre-defined set of possible column names first.
Can you try like this
query = "UPDATE CUSTOMER SET %s = '%s' WHERE CUSTOMER_ID = %d" %(title, info.get(), k)
db.execute(query)
May be you need to commit it.

Python cx_Oracle Update

In my Python code when I ask the user to input a string to SELECT, it works but when I try the UPDATE using the same input doesn't allow me to execute
Here is my code after the connection has been successfully done
curs = connection.cursor()
str_input1 = str(input("Input : "))
str_input2 = str(input("Input : "))
statement = "UPDATE table SET variable1 = "+str_input1+" WHERE name = "+str_input2
curs.execute(statement)
connection.commit
In theory this following code should work and update the variable, but instead I get the error at line curs.execute(statement) saying
cx_Oracle.DatabaseError: ORA-00904: John: invalid identifier
John was the str_input2 for where clause
Maybe its the format that was giving me an error but I'm not too sure.
Can someone point out what was the problem with my code?
The error is because you're not quoting the values. You'd get the exact same error from a SELECT statement.
These statements search for rows where the name column matches the string John:
SELECT * FROM table WHERE name = "John"
UPDATE table SET variable1 = "Hi" WHERE name = "John"
These statements search for rows where the name columns matches the John column—and if there is no John column, that's an error:
SELECT * FROM table WHERE name = John
UPDATE table SET variable1 = "Hi" WHERE name = John
So, you could fix this by just putting quotes around the values.
But you really, really, really shouldn't. This opens you up to SQL injection attacks, and stupid bugs where you don't quote or escape special characters properly, and performance problems where the database engine can't tell that you're running the same query over and over, and so on.
What you want to do is to use SQL parameters, instead of trying to format the string. I don't remember which parameter style cx_Oracle uses, but you can just import cx_Oracle; print(cx_Oracle.paramstyle), and look it up in the table to find out. And then do something like:
statement = "UPDATE table SET variable1 = :v WHERE name = :n"
curs.execute(statement, {'v': str_input1, 'n': str_input2})
Also, a few side notes:
connection.commit doesn't do anything; you're just referencing the commit method, not calling it. You need parentheses: connection.commit()
str(input()) is pointless. The input function always returns a string, so there's no reason to call str on it. (Unless you're using Python 2.x, in which case you should be using raw_input(), which returns a string, instead of using input to eval the string—opening up the same kinds of security problems as the SQL injection attack above—only to convert it back to a string.)

Commiting objects with long integers to MYSQL with SQLAlchemy

I am trying to add a large integer to a MySQL table with SQLAlchemy. As this answer explains, you cannot pass Integer a length argument like you can String. So following that answer I've defined my column with mysql.INTEGER like so:
from sqlalchemy.dialects import mysql
uniqueid = Column(mysql.INTEGER(20))
When I try to commit an object with a 14 digit uniqueid, however, I get the following error message: DataError: (DataError) (1264, "Out of range value for column 'uniqueid' at row 1"). When I try a shorter integer that is not a long, it has no problem committing the same object to the SQL database. I am running python 2.7, other discussions of the long type indicate that it should not behave any differently than int except for printing an L at the end of the number. One final piece of information is if I set the uniqueid to the same short number but make it a long, as in uniqueid = long(32423), I can still commit the object to the SQL database.
I did not solve the mystery of why the mysql.INTEGER class will not work with numbers that have to be long in python 2.7, but the practical solution is to use SQLalchemy's BigInteger class, which as the name suggests can handle big integers, including long.

Categories