Python Sqlite UPDATE multiple values - python

Is there a way to do these two updates in a single instruction?
cur.execute("UPDATE table_name1 SET email = 'foo#bar.com' WHERE id = 4")
cur.execute("UPDATE table_name1 SET phone = '0400-123-456' WHERE id = 4")
I've tried all sort of variations but can't get it to work.
Edit: I want to pass email, phone and I'd as parameters.

You're solution opens you up to SQL injections. If you read the first section of the documentation, it specifically says not to do it the way you are proposing:
Never do this -- insecure!
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)
Do this instead
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
So you should change your code to something along the following lines:
conn = sqlite3.connect('connex.db')
cur = conn.cursor()
mobileval = '0400-123-456'
emailval = 'foo#bar.com'
constrain = 4
q = "UPDATE licontacts310317 SET (?, ?)
WHERE (?)=(?)"
cur.execute(q, (liemailval, limobileval, id, constrain) )
conn.commit()
conn.close()
I haven't tested it, but hopefully you get the idea =)

The following works: Its just standard SQL at this point.
cur.execute("""UPDATE table_name1
SET email = 'foo#bar.com', phone = '0400-123-456'
WHERE id = 4""")

I was facing a similar issue with my own code and was able to get my code working using the following:
cur.execute("UPDATE licontacts310317 SET liemail=?, limobile=? WHERE id=? ", (liemailval, limobileval, constrain))
Someone else already commented this, but it's better to use the ? placeholder and not the string formatting operations because those leave your db vulnerable to SQL injection attacks (basically, hackers).

OK. I made a solution that works with parameters.
First thanks to David for his original answer. It had a small syntax error (corrected in the comments for that answer) but it was enough to help me work out how to get it working without parametising.
(Note:I think David posted his reply before I edited the question to add the need to working with parameters.)
Then this answer helped me parametise the solution.
Here is my solution to the question. I'm poting it in case someone else has the same problem because I did quite a bit of searching before posting the original question and couldn't find the answer.
conn = sqlite3.connect('connex.db')
cur = conn.cursor()
mobileval = '0400-123-456'
emailval = 'foo#bar.com'
constrain = 4
cur.execute("UPDATE licontacts310317 SET liemail=%s, limobile=%s
WHERE %s=?" % (liemailval, limobileval, id), (constrain,))
conn.commit()
conn.close()

Use Dictionaries!
They seem to work well:
cur.execute(
"""UPDATE table_name1
SET email =:email,
phone =:phone
WHERE id = 4
""",
{"email": "foo#bar.com", "phone": '0400-123-456'}
)
So you can just post a dictionary in like so, provided they contain the keys:
cur.execute(
"""UPDATE table_name1
SET email =:email,
phone =:phone
WHERE id = 4
""",
the_dictionary
)
Where the_dictionary = {"email": "foo#bar.com", "phone": "0400-123-456"}. You can put in as many as you'd like. This seems more readable as well I feel.

Related

sqlite3.OperationalError: incomplete input on my code

Can someone help me understand what's incomplete about my code, no matter what I try I keep getting the sqlite3.OperationalError: incomplete input. My code is
editor = Tk()
editor.title('Edit Record')
editor.geometry('400x400')
#Creating database
conn = sqlite3.connect('Student_info.db')
c = conn.cursor()
record_id = delete_box.get()
#Query the database
c.execute("SELECT * FROM Student_info WHERE oid ="+(record_id))<-----
records = c.fetchall()
The line that sublime is referring to is the one I've drawn an arrow to, if anyone could help that would be great!
Your syntax for execute() is off. You should be using a prepared statement as the first parameter, followed by a tuple of parameters as the second function parameter:
record_id = delete_box.get()
c.execute("SELECT * FROM Student_info WHERE oid = %s", (record_id,))
records = c.fetchall()

I try to update data in my sqlite3 address book python program, but the function cannot update my data

I try to update data in my sqlite3 address book python program, therefore I type this function. However, the function cannot update my data. There's no syntax error, but the code just doesn't work. It said 'near 'set' there is a syntax error. Can anyone help me fix this? Thank you.
def update_contact():
name = input('update which name?')
a = input('phone')
b = input('address')
results = cur.execute("UPDATE contact_book set phone = ? set address = ? WHERE name = ?",
(a, b, name,))
#cur = con.cursor(), con = sq.connect('contact_book.db')
view_contact()
You need to commit the changes to the database whenever you change the contents, for it to be saved
results = cur.execute("UPDATE contact_book set phone = ? set address = ? WHERE name = ?", (a, b, name,))
con.commit()
There should be only one SET keyword in an UPDATE query:
UPDATE contact_book set phone = ?, address = ? WHERE name = ?

Retrieving identity of most recent insert in Oracle DB 12c

I'd like to have returned to me (via cx_oracle in python) the value of the Identity that's created for a row that I'm inserting. I think I can figure out the python bit on my own, if someone could please state how to modify my SQL statement to get the ID of the newly-created row.
I have a table that's created with something like the following:
CREATE TABLE hypervisor
(
id NUMBER GENERATED BY DEFAULT AS IDENTITY (
START WITH 1 NOCACHE ORDER ) NOT NULL ,
name VARCHAR2 (50)
)
LOGGING ;
ALTER TABLE hypervisor ADD CONSTRAINT hypervisor_PK PRIMARY KEY ( id ) ;
And I have SQL that's similar to the following:
insert into hypervisor ( name ) values ('my hypervisor')
Is there an easy way to obtain the id of the newly inserted row? I'm happy to modify my SQL statement to have it returned, if that's possible.
Most of the google hits on this issue were for version 11 and below, which don't support automatically-generated identity columns so hopefully someone here can help out.
Taking what user2502422 said above and adding the python bit:
newest_id_wrapper = cursor.var(cx_Oracle.STRING)
sql_params = { "newest_id_sql_param" : newest_id_wrapper }
sql = "insert into hypervisor ( name ) values ('my hypervisor') " + \
"returning id into :python_var"
cursor.execute(sql, sql_params)
newest_id=newest_id_wrapper.getvalue()
This example taken from learncodeshare.net has helped me grasp the correct syntax.
cur = con.cursor()
new_id = cur.var(cx_Oracle.NUMBER)
statement = 'insert into cx_people(name, age, notes) values (:1, :2, :3) returning id into :4'
cur.execute(statement, ('Sandy', 31, 'I like horses', new_id))
sandy_id = new_id.getvalue()
pet_statement = 'insert into cx_pets (name, owner, type) values (:1, :2, :3)'
cur.execute(pet_statement, ('Big Red', sandy_id, 'horse'))
con.commit()
It's only slightly different from ragerdl's answer, but different enough to be added here I believe!
Notice the absence of sql_params = { "newest_id_sql_param" : newest_id_wrapper }
Use the returning clause of the insert statement.
insert into hypervisor (name ) values ('my hypervisor')
returning id into :python_var
You said you could handle the Python bit ? You should be able to "bind" the return parameter in your program.
I liked the answer by Marco Polo, but it is incomplete.
The answer from FelDev is good too but does not address named parameters.
Here is a more complete example from code I wrote with a simplified table (less fields). I have omitted code on how to set up a cursor since that is well documented elsewhere.
import cx_Oracle
INSERT_A_LOG = '''INSERT INTO A_LOG(A_KEY, REGION, DIR_NAME, FILENAME)
VALUES(A_KEY_Sequence.nextval, :REGION, :DIR_NAME, :FILENAME)
RETURNING A_KEY INTO :A_LOG_ID'''
CURSOR = None
class DataProcessor(Process):
# Other code for setting up connection to DB and storing it in CURSOR
def save_log_entry(self, row):
global CURSOR
# Oracle variable to hold value of last insert
log_var = CURSOR.var(cx_Oracle.NUMBER)
row['A_LOG_ID'] = log_var
row['REGION'] = 'R7' # Other entries set elsewhere
try:
# This will fail unless row.keys() =
# ['REGION', 'DIR_NAME', 'FILE_NAME', 'A_LOG_ID']
CURSOR.execute(INSERT_A_LOG, row)
except Exception as e:
row['REJCTN_CD'] = 'InsertFailed'
raise
# Get last inserted ID from Oracle for update
self.last_log_id = log_var.getvalue()
print('Insert id was {}'.format(self.last_log_id))
Agreeing with the older answers. However, depending on your version of cx_Oracle (7.0 and newer), var.getvalue() might return an array instead of a scalar.
This is to support multiple return values as stated in this comment.
Also note, that cx_Oracle is deprecated and has moved to oracledb now.
Example:
newId = cur.var(oracledb.NUMBER, outconverter=int)
sql = """insert into Locations(latitude, longitude) values (:latitude, :longitude) returning locationId into :newId"""
sqlParam = [latitude, longitude, newId]
cur.execute(sql, sqlParam)
newIdValue = newId.getvalue()
newIdValue would return [1] instead of 1

Sqlite operationalError: syntax for IF NOT EXISTS

I am getting a sql lite operational syntax error for this code:
def checkIn(uname, title):
bookid = findBookID(title) #returns an int bookid given the title
print bookid
with libDB:
checkCur = libDB.cursor()
checkCur.execute(
"IF NOT EXISTS(SELECT 1 FROM Checks WHERE Username =? AND bookID =?) INSERT INTO Checks VALUES(?,?)",
(uname, bookid, uname, bookid))
checkCur.close()
mess = "OK::CHKIN::", uname, "::", title
return mess
The error is:
sqlite3.OperationalError: near "IF": syntax error
This is how I defined the table:
with libDB:
checkCur = libDB.cursor()
checkCur.execute(
"CREATE TABLE Checks(bookID INTEGER, Username TEXT, FOREIGN KEY(bookID) REFERENCES Books(bookID),FOREIGN KEY(Username) REFERENCES Users(Username))")
checkCur.close()
My apologies if I am missing something simple. I looked over the code several times and search online and I don't see where the syntax error is. I compared my query to those I found online and it seems to match. The only thing I can think of that could be wrong is if my parameters are not correct but I tried altering them and I still can't get it to work.
Thank you in advance for any help.
-CJ
IF NOT EXISTS is incompatible with sqlite. The insert statement you want is as follows:
INSERT INTO Checks (bookID, Username)
SELECT 7, 'Bob' /* for example */
WHERE NOT EXISTS (SELECT 1 FROM Checks WHERE bookID = 7 and Username = 'Bob');
Note that NOT EXISTS is in the WHERE clause. This sort of insert statement is compatible with sqlite. You can play with the sql fiddle here.
So in your Python function, try this instead:
insert_stmt = ("INSERT INTO Checks (bookID, Username) " # note the space at end of string
"SELECT ?, ? "
"WHERE NOT EXISTS (SELECT 1 FROM Checks WHERE bookID = ? and Username = ?)")
checkCur.execute(insert_stmt, (bookid, uname) * 2) # no need to repeat the bookid, uname combo twice; just multiply the tuple by 2

Getting the id of the last record inserted for Postgresql SERIAL KEY with Python

I am using SQLAlchemy without the ORM, i.e. using hand-crafted SQL statements to directly interact with the backend database. I am using PG as my backend database (psycopg2 as DB driver) in this instance - I don't know if that affects the answer.
I have statements like this,for brevity, assume that conn is a valid connection to the database:
conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
Assume also that the user table consists of the columns (id [SERIAL PRIMARY KEY], name, country_id)
How may I obtain the id of the new user, ideally, without hitting the database again?
You might be able to use the RETURNING clause of the INSERT statement like this:
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
RETURNING *")
If you only want the resulting id:
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
RETURNING id")
[new_id] = result.fetchone()
User lastrowid
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
result.lastrowid
Current SQLAlchemy documentation suggests
result.inserted_primary_key should work!
Python + SQLAlchemy
after commit, you get the primary_key column id (autoincremeted) updated in your object.
db.session.add(new_usr)
db.session.commit() #will insert the new_usr data into database AND retrieve id
idd = new_usr.usrID # usrID is the autoincremented primary_key column.
return jsonify(idd),201 #usrID = 12, correct id from table User in Database.
this question has been asked many times on stackoverflow and no answer I have seen is comprehensive. Googling 'sqlalchemy insert get id of new row' brings up a lot of them.
There are three levels to SQLAlchemy.
Top: the ORM.
Middle: Database abstraction (DBA) with Table classes etc.
Bottom: SQL using the text function.
To an OO programmer the ORM level looks natural, but to a database programmer it looks ugly and the ORM gets in the way. The DBA layer is an OK compromise. The SQL layer looks natural to database programmers and would look alien to an OO-only programmer.
Each level has it own syntax, similar but different enough to be frustrating. On top of this there is almost too much documentation online, very hard to find the answer.
I will describe how to get the inserted id AT THE SQL LAYER for the RDBMS I use.
Table: User(user_id integer primary autoincrement key, user_name string)
conn: Is a Connection obtained within SQLAlchemy to the DBMS you are using.
SQLite
======
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm) ''' )
# Execute within a transaction (optional)
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.lastrowid
txn.commit()
MS SQL Server
=============
insstmt = text(
'''INSERT INTO user (user_name)
OUTPUT inserted.record_id
VALUES (:usernm) ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.fetchone()[0]
txn.commit()
MariaDB/MySQL
=============
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm) ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = conn.execute(text('SELECT LAST_INSERT_ID()')).fetchone()[0]
txn.commit()
Postgres
========
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm)
RETURNING user_id ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.fetchone()[0]
txn.commit()
result.inserted_primary_key
Worked for me. The only thing to note is that this returns a list that contains that last_insert_id.
Make sure you use fetchrow/fetch to receive the returning object
insert_stmt = user.insert().values(name="homer", country_id="123").returning(user.c.id)
row_id = await conn.fetchrow(insert_stmt)
For Postgress inserts from python code is simple to use "RETURNING" keyword with the "col_id" (name of the column which you want to get the last inserted row id) in insert statement at end
syntax -
from sqlalchemy import create_engine
conn_string = "postgresql://USERNAME:PSWD#HOSTNAME/DATABASE_NAME"
db = create_engine(conn_string)
conn = db.connect()
INSERT INTO emp_table (col_id, Name ,Age)
VALUES(3,'xyz',30) RETURNING col_id;
or
(if col_id column is auto increment)
insert_sql = (INSERT INTO emp_table (Name ,Age)
VALUES('xyz',30) RETURNING col_id;)
result = conn.execute(insert_sql)
[last_row_id] = result.fetchone()
print(last_row_id)
#output = 3
ex -

Categories