I am trying to delete rows in a sql table from python with sqlalchemy based on a condition. Here is the code I have so far
def delete_previous_month():
#creating connection object
connection = engine.connect()
meta = MetaData(engine).reflect()
user_t = meta.tables[f'{table_name}']
del_st = user_t.delete().where(
user_t.c.month == Current_Month - 1)
print('----- deleting previous records ')
connection.execute(del_st)
delete_previous_month()
I need to get the part of the code where it says:
user_t.c.month == Current_Month - 1)
to delete the rows like it would in sql if I did this:
DATEPART(m, month) = DATEPART(m, DATEADD(m, -1, getdate())
What is the equivalent sqlalchemy syntax for sql server datepart function?
Related
My objective is to show a kanban table by day, so the user could save their pending, in process or completed tasks for each day in the calendar. My program look as follows:
Every list is a QListWidget, where the user can add a new pending task by right clicking over them or move the tasks from the "Pendientes" list to the "En proceso" list or the "Completadas" list.
Now, for saving the task for every date of the QCalendarWidget, I'm trying to use a sqlite database that looks like this:
where the "tareas" column shows the tasks, "lista" shows a number corresponding to each of my three QListWidgets (0 = "Pendientes"; 1 = "En proceso" and 2 = "Completadas") and "fecha" shows the date. I'm able to show every task in the corresponding list by date just fine with this function, but only the tasks that I added directly in the Sqlite Browser:
def updateTaskList(self, date):
self.lista_pendientes.clear()
self.lista_enprogreso.clear()
self.lista_completadas.clear()
db = sqlite3.connect("todo.db")
cursor = db.cursor()
query = "SELECT tarea, lista FROM tareas WHERE fecha = ?"
row = (date,)
results = cursor.execute(query, row).fetchall()
for tarea, list in results:
item = QListWidgetItem(tarea)
if list == 0:
self.lista_pendientes.addItem(item)
elif list == 1:
self.lista_enprogreso.addItem(item)
elif list == 2:
self.lista_completadas.addItem(item)
But when I try to save the tasks that I added from my program it doesn't save the changes:
def saveChanges (self):
db = sqlite3.connect("todo.db")
cursor = db.cursor()
date = self.calendarWidget.selectedDate().toPython()
for i in range(self.lista_pendientes.count()):
item = self.lista_pendientes.item(i)
task = item.text()
query = "UPDATE tareas SET lista = '0' WHERE tarea = ? AND fecha = ? "
row = (task, date,)
cursor.execute(query,row)
db.commit()
In this function I'm trying to save only the tasks that are in the "pendientes" list, by assigning the index 0 to those tasks, but to no avail. What could I do to save the tasks from the three QListWidgets in my database?
EDIT-SOLVED
After experimenting a bit I founded an easier solution: to use three different tables in my sqlite database for each type of task. That way I can save each task individually without worrying about the list column.
I have one offset date to be stored in Postgres table -
latest_mod_date = max(data['last_modified'])
latest mod_date = 2022-04-16 05:50:00
Want this date to be updated in postgres -
Used this query -
The postgres table data_offset is like this -
_id offset_type offset_value
1 C [NULL]
2 P [NULL]
# # query to update - global is the schema and data_offset is the data table in postgres
sql = '''update global.data_offset set {offset_value=latest_mod_date} where {offset_type='C'}; '''
#
# # execute the query
cursor.execute(sql)
print("Table updated..")
print('Table after updation...')
# query to display table
sql2 = 'select * from global.data_offset;'
# execute query
cursor.execute(sql2);
# fetching all details
print(cursor.fetchall());
This query is giving error -
psycopg2.errors.SyntaxError: syntax error at or near "{"
LINE 1: update global.data_offset set {offset_value=latest_mo...
I want the latest_mod_date to be stored in the offset value where the offset_stypr is 'C'.
Any place you have seem {} is probably because people have been doing something like sql_str.format() which is the wrong thing to do. See Parameter passing for the correct way to pass variables in.
In your case what you need is:
sql = "update global.data_offset set offset_value = %s where offset_type='C'"
cursor.execute(sql, [latest_mod_date])
# Commit the changes.
con.commit()
I'm using pd.read_sql to generate dataframes. I'm using parameters in a list to generate separate dataframes based on filters. I did same query from my script in python on database and it worked.
In SQL database I always had data returned for months 1,2,3 and/or project x,y. But python SOMETIMES doesn't bring nonthing and I don't know. This generate empty dataframe
if I put months like [1,'2',3] sometimes the where condition works, but in my database the field is varchar, I don't why if I put int in a list the data comes or depend on type the filter doesn't works
server = 'xxxxx'
database = 'mydatabase'
username = 'user'
password = '*************'
driver = '{SQL Server Native Client 11.0}'
turbodbc_options = 'options'
timeout = '1'
project = ['x','y']
months = ['1','2','3']
def generatefile():
for pr in project:
for index in months:
print(type(index))
print(index)
print(pr)
db = pd.read_sql('''select * from table WHERE monthnumber =(?)and pro=(?)''',conn,params={str(index),(pr)})
print(db)
print("generate...")
db.to_excel('C:\\localfile\\' + pr + '\\' + pr + tp + str(index) + 'file.xlsx',index=False,engine='xlsxwriter' ),index=False,engine='xlsxwriter' )
generatefile()
consider the difference between:
1.
sql = '''
select * from table WHERE monthnumber = '1' and pro= 'x'
'''
sql = '''
select * from table WHERE monthnumber = 1 and pro= 'x'
'''
so, the sql should be something like below, if the field is varchar.
db = pd.read_sql(f'''
select * from table WHERE monthnumber ='{index}'and pro='{pr}'
''',conn)
I've a script that makes a query to my database on MySQL. And my doubt is if I can pass any parameter to that query through Python.
For example, on the following script I want to calculate the date_filter using Python and then apply that filter on the query.
now = dt.datetime.now()
date_filter = now - timedelta(days=3)
dq_connection = mysql.connector.connect(user='user', password='pass', host='localhost', database='db')
engine = create_engine('localhost/db')
cursor = connection.cursor(buffered=True)
query = ('''
SELECT *
FROM myTable
WHERE date >= ''' + date_filter + '''
''')
I try it on that way but I got the following error:
builtins.TypeError: can only concatenate str (not "datetime.datetime") to str
It is possible to apply the filter like that?
Thanks!
Yes, you can do it. To avoid sql injections, the best way is not using the python formatting facilities, but the sql parameters & placeholders (see that you donĀ“t need the single quotes ' as the placeholder does the job and converts the type of the variable):
now = dt.datetime.now()
date_filter = now - timedelta(days=3)
dq_connection = mysql.connector.connect(user='user', password='pass', host='localhost', database='db')
engine = create_engine('localhost/db')
cursor = db_connection.cursor(buffered=True)
query = "SELECT * FROM myTable WHERE date >=%s"
cursor.execute(query,(date_filter,))
Also, you had a mistake in your cursor, it should be db_connection.cursor. The last comma after date_filter is ok because you need to send a tuple.
In case you need more than one paremeter, you can place more than one placeholder:
query = "SELECT * FROM myTable WHERE date >=%s and date<=%s"
cursor.execute(query,(date_filter,other_date))
You can just do something like:
WHERE date >= ''' + str(date_filter) + '''
to represent the date as string as not a datetime object.
You can try with this:
date_f = str(date_filter)
query = ('''
SELECT *
FROM myTable
WHERE date >= "{}"
'''.format(date_f))
I have my python script which reads an excel column row by row and returns all rows str(values).
I want to write another script which will allow put these values to sql db. I've already written connect method:
def db_connect():
adr = 'some_addr'
uid = 'some_uid'
pwd = 'pwd'
port = port
dsn_tns = cx_Oracle.makedsn(adr, port, SID)
db = cx_Oracle.connect('username', 'pass', dsn_tns)
cur = db.cursor()
cur.execute('update TABLE set ROW = 666 where ANOTHER_ROW is null')
db.commit()
This method does an update but it sets 666 for ALL rows. How to do it by kind of iteration in sql? For example, first row of output == 1, second == 23, third == 888.
If I understand correctly what you are trying to do here it should be done in two phases. First select all rows for update (based on chosen condition), then you can iteratively update each of these rows.
It cannot be done in single query (or on only single condition that does not change through a number of queries), because SQL works on sets, that's why each time your query is executed you are updating whole table, and in the end only getting result of the last query.
You can use the "rownum" expression, as in:
cur.execute("update TABLE set ROW = rownum where ANOTHER_ROW is null")
This will start with the value 1 and increment up by one for each row updated.
If you want more control over the value to set, you can also do the following in PL/SQL (untested):
cur.execute("""
declare
t_NewValue number;
cursor c_Data is
select ROW, ANOTHER_ROW
from TABLE
where ANOTHER_ROW is null
for update;
begin
t_NewValue := 1;
for row in c_Data loop
update TABLE set ROW = t_NewValue
where current of c_Data;
t_NewValue := t_NewValue + 1;
end loop;
end;""")
This gives you the most control. You can use whatever logic you require to control what the new value should be.
Please take a look at another method which is writing to excel:
adr = 'some_addr'
uid = 'some_uid'
pwd = 'pwd'
port = port
dsn_tns = cx_Oracle.makedsn(adr, port, SID)
db = cx_Oracle.connect('username', 'pass', dsn_tns)
cur = db.cursor()
cells = excel.read_from_cell()
indices_and_statuses = []
stat = execute_script(some_js)
for req_id in cells:
indices_and_statuses.append((cells.index(req_id), stat))
cur.execute("""update TABLE set ROW ="""+"'"+req_id+"'"+"""where ANOTHER_ROW is null""")
db.commit()
db.close()
And in this code when you put print(req_id) in this FOR statement, you will see that req_id is changing. But in DB only the last req_id is saved.