title = article.title
title = re.sub(r' - Wikipedia, the free encyclopedia','',title)
title_lower = title.lower()
title_lower = title_lower.replace(' ','-')
print title
print title_lower
title_query = ("INSERT INTO myguests "
"(firstname) "
"VALUES (%s)")
cursor.execute("SELECT id FROM myguests "
"WHERE firstname='"+title+"'")
row = cursor.fetchall()
if row !=[]:
print "List is not empty"
if not row:
print "List is empty"
title_query = title
print title
For some reason in my if statement my title variable keeps coming back empty when it is called if not row:
I am trying to insert variable if the variable dose not exist in column.
If no rows are returned then it's probably because there is no data in the table with the requested firstname. Try adding some debugging to your code and use a parameterised query rather than string concatenation:
cursor.execute("SELECT id FROM myguests WHERE firstname = %s", (title,))
row = cursor.fetchall()
print 'Got row: {!r}'.format(row) # some debugging
if row:
print "Record for {} already exists".format(title)
else:
print "List is empty, attempting to insert"
cursor.execute(title_query, (title,))
But there is a potential race condition with this approach; what if some other process adds the value to the database between the initial check and the subsequent insert? Depending on your application this may or may not be a problem.
Regarding "insert if not exists", one way is to set a UNIQUE INDEX on the firstname column. and then simply attempt to insert a new row without checking first. If a row exists with the same value for firstname the insert will fail. If no such row exists, the insert will be attempted (it might still fail, but for other reasons). Your code needs to handle insertion failure due to duplicate key.
Or you could investigate use of INSERT IGNORE into myguests ..., or some of the other options discussed here: How to 'insert if not exists' in MySQL?.
But are you really sure that firstname should be unique? It seems to me likely that many guests could have the same first name.
Related
I had a quick question. I want to count how many times a user is logged into the system. To achieve this i add a 1 to the third part of the result. The only thing is that every time the user logs in the code fetches the first corresponding row. Thus resulting in the fact that the login_num will always be 2, since the first corresponding row always contains a 1.
On Stackoverflow i searched for several solutions. So i came up with the DESC at the end of the fetch syntax. However in every instance i tried this, i always end up getting an error in return. Does anyone have an idea why this is the case?
Python code:
cursor.execute("Select rfid_uid, name, login_num FROM users rfid_uid="+str(id) + "ORDER BY id DESC")
result = cursor.fetchone()
if cursor.rowcount >= 1:
print("Welkom " + result[1])
print(result)
result = (result[0], result[1], result[2] + 1)
sql_insert = "INSERT INTO users (rfid_uid, name, login_num) VALUES (%s, %s, %s)"
cursor.execute(sql_insert, (result))
db.commit()
Seems your SQL statement refers to table 'users'. I suppose it does contain info about users in general (a row per user), not user logins.
If you have each individual user login event registered in some table, I would let the database do the counting. Something like this:
SELECT COUNT(*) FROM user_logins WHERE rfid_uid='user_id';
You should get one row, which has your answer as an integer.
I have a table in postgresql where initially the table will be empty not as null value it will be empty
i am running a select query which will display the value as empty, but i need it to return null
this is my query
select job_status,refreshed_properties,total_number_of_properties_to_be_refreshed
from job_table
this is my python code
check_job_status = """select job_status,refreshed_properties,total_number_of_properties_to_be_refreshed
from job_table"""
cursor.execute(check_job_status)
job_status = cursor.fetchall()
print (job_status)
print("the above result is the job status ")
either i need to handle it in postgresql or need to handle in python
table structure
python output
Use nulliff():
select
nullif(job_status, '') as status,
refreshed_properties,
total_number_of_properties_to_be_refreshed
from job_table
If job_status is equal to the empty string, this returns a null value instead.
i am running a select query which will display the value as empty, but i need it to return null
I think you want to return None and not null. Isnt it?
Just check if the list is empty and print None if it is.
job_status = cursor.fetchall()
print (job_status if len(job_status) else None)
print("the above result is the job status ")
I am trying to create a definition using cx_oracle to insert data in to the database and in return get the record id. I searched the forum and found the solution as below.
def insert_data(self,SqlQry):
try:
idvar=self.__cursor.var(cx_Oracle.NUMBER)
SqlQry=SqlQry + " returning ID into :vrecord_id"
self.__cursor.execute(SqlQry,v1='test1',v2='test2',v3='test3',v4='test4', vrecord_id=idvar)
vid= idvar.getvalue()
self.__con.commit()
retuen vid
except cx_Oracle.DatabaseError as e:
return e
print("Error in data insert")
print(sql_insertData("INSERT INTO MYTABLE(Field1,Field2,Field3,Field4) VALUES(:v1, :v2, :v3,:v4)")
This works fine and i am able to get the ID. But i want to pass the values with the sql statement inplace of defining each individually as i have done now in .execute line.
cursor.execute(SqlQry,v1='test1',v2='test2',v3='test3',v4='test4', vrecord_id=idvar)
I want to change the current print statement to like this :
print(sql_insertData(
"""INSERT INTO RAP_RISK_TYPE(RISK_HEADER,RISK_TYPE_DISP,RISK_TYPE_DESC,RISK_TYPE_CAT)
VALUES
(:v1, :v2, :v3,:v4)""", ['newvalue1','newvalue2','newvalue3','newvalue4']
But if i do this how do i write the execute statement to get the ID, i get error if i do the below
def insert_data(self,SqlQry,parm):
try:
idvar=self.__cursor.var(cx_Oracle.NUMBER)
SqlQry=SqlQry + " returning ID into :vrecord_id"
self.__cursor.execute(SqlQry,parm, vrecord_id=idvar)
vid= idvar.getvalue()
self.__con.commit()
retuen vid
except cx_Oracle.DatabaseError as e:
return e
print("Error in data insert")
print(sql_insertData(
"""INSERT INTO RAP_RISK_TYPE(RISK_HEADER,RISK_TYPE_DISP,RISK_TYPE_DESC,RISK_TYPE_CAT)
VALUES
(:v1, :v2, :v3,:v4)""", ['newvalue1','newvalue2','newvalue3','newvalue4']
I am not able to pass the list from the print statement and add the "idvar" both at same time.
With cx_Oracle 7.3, you can access Cursor.lastRowid after executing the INSERT. See the cx_Oracle example LastRowid.py:
cursor = connection.cursor()
cursor.execute("insert into mytab (id, data) values (:1, :2)", [1, "First"])
print("Rowid 1:", cursor.lastrowid)
Otherwise use the RETURNING INTO clause you were looking at. There is a RETURNING INTO example at https://cx-oracle.readthedocs.io/en/latest/user_guide/bind.html#dml-returning-bind-variables.
Chris has given an excellent generic answer. If you are looking for the specific answer to your question, you need to do the following:
self.__cursor.execute(SqlQry, parm + [idvar])
In other words, you need to ensure that only one set of parameters is passed, not multiple!
lst = [{'Fruit':'Apple','HadToday':2},{'Fruit':'Banana','HadToday':8}]
I have a long list of dictionaries of the form above.
I have two fixed variables.
person = 'Sam'
date = datetime.datetime.now()
I wish to insert this information into a mysql table.
How I do it currently
for item in lst:
item['Person'] = person
item['Date'] = date
cursor.executemany("""
INSERT INTO myTable (Person,Date,Fruit,HadToday)
VALUES (%(Person)s, %(Date)s, %(Fruit)s, %(HadToday)s)""", lst)
conn.commit()
Is their a way to do it, that bypasses the loop as the person and date variables are constant. I have tried
lst = [{'Fruit':'Apple','HadToday':2},{'Fruit':'Banana','HadToday':8}]
cursor.executemany("""
INSERT INTO myTable (Person,Date,Fruit,HadToday)
VALUES (%s, %s, %(Fruit)s, %(HadToday)s)""", (person,date,lst))
conn.commit()
TypeError: not enough arguments for format string
Your problem here is, that it tries to apply all of lst into %(Fruit)s and nothing is left for %(HadToday)s).
You should not fix it by hardcoding the fixed values into the statement as you get into troubles if you have a name like "Tim O'Molligan" - its better to let the db handle the correct formatting.
Not mysql, but you get the gist: http://initd.org/psycopg/docs/usage.html#the-problem-with-the-query-parameters - learned this myself just a week ago ;o)
The probably cleanest way would be to use
cursor.execute("SET #myname = %s", (person,))
cursor.execute("SET #mydate = %s", (datetime.datetime.now(),))
and use
cursor.executemany("""
INSERT INTO myTable (Person,Date,Fruit,HadToday)
VALUES (#myname, #mydate, %(Fruit)s, %(HadToday)s)""", lst)
I am not 100% about the syntax, but I hope you get the idea. Comment/edit the answer if I have a misspell in it.
I'm trying to check whether a record already exists in the database (by similar title), and insert it if not. I've tried it two ways and neither quite works.
More elegant way (?) using IF NOT EXISTS
if mode=="update":
#check if book is already present in the system
cursor.execute('IF NOT EXISTS (SELECT * FROM book WHERE TITLE LIKE "%s") INSERT INTO book (title,author,isbn) VALUES ("%s","%s","%s") END IF;' % (title,title,author,isbn))
cursor.execute('SELECT bookID FROM book WHERE TITLE LIKE "%s";' % (title))
bookID = cursor.fetchall()
print('found the bookid %s' % (bookID))
#cursor.execute('INSERT INTO choice (uid,catID,priority,bookID) VALUES ("%d","%s","%s","%s");' % ('1',cat,priority,bookID)) #commented out because above doesn't work
With this, I get an error on the IF NOT EXISTS query saying that "author" isn't defined (although it is).
Less elegant way using count of matching records
if mode=="update":
#check if book is already present in the system
cursor.execute('SELECT COUNT(*) FROM book WHERE title LIKE "%s";' % (title))
anyresults = cursor.fetchall()
print('anyresults looks like %s' % (anyresults))
if anyresults[0] == 0: # if we didn't find a bookID
print("I'm in the loop for adding a book")
cursor.execute('INSERT INTO book (title,author,isbn) VALUES ("%s","%s","%s");' % (title,author,isbn))
cursor.execute('SELECT bookID FROM book WHERE TITLE LIKE "%s";' % (title))
bookID = cursor.fetchall()
print('found the bookid %s' % (bookID))
#cursor.execute('INSERT INTO choice (uid,catID,priority,bookID) VALUES ("%d","%s","%s","%s");' % ('1',cat,priority,bookID)) #commented out because above doesn't work
In this version, anyresults is a tuple that looks like (0L,) but I can't find a way of matching it that gets me into that "loop for adding a book." if anyresults[0] == 0, 0L, '0', '0L' -- none of these seem to get me into the loop.
I think I may not be using IF NOT EXISTS correctly--examples I've found are for separate procedures, which aren't really in the scope of this small project.
ADDITION:
I think unutbu's code will work great, but I'll still getting this dumb NameError saying author is undefined which prevents the INSERT from being tried, even when I am definitely passing it in.
if form.has_key("title"):
title = form['title'].value
mode = "update"
if form.has_key("author"):
author = form['author'].value
mode = "update"
print("I'm in here")
if form.has_key("isbn"):
isbn = form['isbn'].value
mode = "update"
It never prints that "I'm in here" test statement. What would stop it getting in there? It seems so obvious--I keep checking my indentation, and I'm testing it on the command line and definitely specifying all three parameters.
If you set up a UNIQUE index on book, then inserting unique rows is easy.
For example,
mysql> ALTER IGNORE TABLE book ADD UNIQUE INDEX book_index (title,author);
WARNING: if there are rows with non-unique (title,author) pairs, all but one such row will be dropped.
If you want just the author field to be unique, then just change (title,author) to (author).
Depending on how big the table, this may take a while...
Now, to insert a unique record,
sql='INSERT IGNORE INTO book (title,author,isbn) VALUES (%s, %s, %s)'
cursor.execute(sql,[title,author,isbn])
If (title,author) are unique, the triplet (title,author,isbn) is inserted into the book table.
If (title,author) are not unique, then the INSERT command is ignored.
Note, the second argument to cursor.execute. Passing arguments this way helps prevent SQL injection.
This doesn't answer your question since it's for Postgresql rather than MySQL, but I figured I'd drop it in for people searching their way here.
In Postgres, you can batch insert items if they don't exist:
CREATE TABLE book (title TEXT, author TEXT, isbn TEXT);
# Create a row of test data:
INSERT INTO book (title,author,isbn) VALUES ('a', 'b', 'c');
# Do the real batch insert:
INSERT INTO book
SELECT add.* FROM (VALUES
('a', 'b', 'c'),
('d', 'e', 'f'),
('g', 'h', 'i'),
) AS add (title, author, isbn)
LEFT JOIN book ON (book.title = add.title)
WHERE book.title IS NULL;
This is pretty simple. It selects the new rows as if they're a table, then left joins them against the existing data. The rows that don't already exist will join against a NULL row; we then filter out the ones that already exist (where book.title isn't NULL). This is extremely fast: it takes only a single database transaction to do a large batch of inserts, and lets the database backend do a bulk join, which it's very good at.
By the way, you really need to stop formatting your SQL queries directly (unless you really have to and really know what you're doing, which you don't here). Use query substitution, eg. cur.execute("SELECT * FROM table WHERE title=? and isbn=?", (title, isbn)).