SqlAlchemy Update-Anweisung, die die gesamte Zeile als Werte bindetPython

Python-Programme
Anonymous
 SqlAlchemy Update-Anweisung, die die gesamte Zeile als Werte bindet

Post by Anonymous »

Ich bin nicht sicher, ob dies anhand der Dokumente möglich ist, aber ich habe eine textbasierte Abfrage, die bei jeder Ausführung alle Zeilenwerte aktualisiert. Ursprünglich erfolgte dies über Oracle und seinen Cursor, wobei die Zeile übergeben und an die Parameter gebunden wurde. Wir stellen auf Postgres und Sqlalchemy um. Beim Versuch, einige dieser Dinge zu konvertieren, stoße ich also auf ein Problem, bei dem ich anscheinend jedes Mal, wenn ich die Abfrage aufrufe, jeden einzelnen Parameter binden muss, sonst kommt es zu einem Fehler, je nachdem, was ich versucht habe.
Die Abfrage:

Code: Select all

update_qc_sod = text(f"""
update {QcSodTable.__table__.fullname}
stn_ops = :stn_ops,
precip_trace = :precip_trace,
precip = :precip,
precip_period = :precip_period,
temp_max = :temp_max,
temp_min = :temp_min
where platformid = :platformid and
trim(networktype) = :networktype and
datetime = :datetime
""")
Ich habe versucht, die Ausführung folgendermaßen durchzuführen:
(nur die Werte aktualisieren, die in dieser Schleife geändert wurden)

Code: Select all

connection.execute(queries.update_qc_sod.bindparams(qc_flag=qc_sod_new_row.QcSodTable.qc_flag, remarks=qc_sod_new_row.QcSodTable.remarks))
(Versuchen Sie, alle Zeilen zu aktualisieren)

Code: Select all

connection.execute(queries.update_qc_sod.bindparams(qc_sod_new_row))
(Versuchen Sie, als Parameter zu übergeben)

Code: Select all

connection.execute(queries.update_qc_sod, qc_sod_new_row)
Ich kenne so etwas und es wäre viel einfacher, es so zu verwenden, wie es ist, anstatt für jede einzelne davon eine Abfrage mit den richtigen Parametern durchzuführen, um sie nur zu binden. Ich könnte jeden Parameter manuell zum Binden hinzufügen, aber das würde ihn unglaublich hässlich und groß machen. Wenn das der einzige Weg ist, dann werde ich das versuchen, aber wenn es einen besseren, saubereren Weg gibt, eine ganze Zeile als Aktualisierungsparameter zu übergeben, wäre das fantastisch.
Bearbeiten:
Um zu verdeutlichen, was ich versuche: Ich habe eine Select-Anweisung, die eine Union verwendet, um Zeilen aus der QcSodTable abzurufen. Anschließend durchläuft das Ergebnis eine Reihe von Qualitätskontrollen, um sicherzustellen, dass alle Daten gültig sind. Wenn die Daten geändert werden müssten, würden die Daten direkt danach eingefügt, damit sie später für andere Prüfungen bereit wären, die diese Daten möglicherweise verwenden müssen.

Code: Select all

qc_sod_row = connection.execute(queries.get_qc_sod_data).all()[0][0]
Hier ist ein kurzes Beispiel für eine der QC-Prüfungen:

Code: Select all

def check_datetimes(connection, qc_sod_row, algorithm, is_good):
"""
if local_time or date does not exist, then add remarks and
add alg flag of C00/01
"""
qc_sod_new_row = copy.deepcopy(qc_sod_row)

if not is_good:
qc_sod_new_row.remarks = utils.update_remarks(qc_sod_row.remarks, algorithm)
qc_sod_new_row.qc_flag = "F"
# Update the QC_SOD table with new values
diction = utils.bind_qc_sod(queries.update_qc_sod, qc_sod_new_row)
connection.execute(queries.update_qc_sod, diction)

return qc_sod_new_row
Der Fehler, auf den ich stoße, tritt während der Datei „connection.execute“ auf, bei der ich versuche, die Parameter zu übergeben. Es kommt zu einem Fehler mit einer Vielzahl von Problemen, je nachdem, wie ich versuche, die Parameter zu binden.
Die obige Diktionsvariable ist ein Wörterbuch jedes Zeilennamens und des Parameters, den ich binden möchte.

Code: Select all

    diction = dict(
stn_ops= qc_sod.stn_ops,
precip_trace= qc_sod.precip_trace,
precip= qc_sod.precip,
precip_period= qc_sod.precip_period,
temp_max= qc_sod.temp_max,
temp_min= qc_sod.temp_min,
wind_gust_dir= qc_sod.wind_gust_dir
)
Im obigen Beispiel würden Bemerkungen also eine neue Bemerkung verketten und das qc_flag aktualisieren. Alle anderen Daten würden gleich bleiben, daher möchte ich nur diese Felder aktualisieren, aber die Abfrage selbst wird in anderen Bereichen verwendet, um auch andere Spalten zu aktualisieren (precip, temp_max usw.).
So wurde es zuvor über die OracleCX-Bibliothek gemacht:

Code: Select all

def chk_localtime(qc_sod_row, time_conv, sod_connection):
ALG_FLAG = "C00"
qc_sod_row_new = qc_sod_row.copy()

if not local_time_check(time_conv):
cursor_sod = sod_connection.cursor()

qc_sod_row_new["REMARKS"] = utils.update_remarks(qc_sod_row, ALG_FLAG)
qc_sod_row_new["QC_FLAG"] = "F"

#Update the QC_SOD table with new values
cursor_sod.execute(qc_sod_queries.update_qc_sod, qc_sod_row_new)

cursor_sod.close()

return qc_sod_row_new
Im Wesentlichen habe ich eine Zeile, die in einigen Spalten aktualisiert wird und in anderen nicht. Ich möchte die geänderten Spalten aktualisieren. Da die Spalte, die sich ändern kann, immer eine andere ist, wäre es toll, einfach die neue, aktualisierte Zeile als alle Parameter zu übergeben und nur zu aktualisieren, was geändert wurde, wenn das Sinn macht.
Ich habe auch versucht, SqlAlchemy zu verwenden, um die Anweisung zu erstellen:

Code: Select all

update_qc_sod = (
update(QcSodTable)
.where(
QcSodTable.platformid == bindparam("platformid"),
func.trim(QcSodTable.networktype) == bindparam("networktype"),
QcSodTable.datetime == bindparam("datetime")
)
.values(
stn_ops=bindparam("stn_ops"),
precip_trace=bindparam("precip_trace"),
precip=bindparam("precip"),
precip_period=bindparam("precip_period"),
temp_max=bindparam("temp_max"),
temp_min=bindparam("temp_min"),
wind_gust_dir=bindparam("wind_gust_dir"),
)
)
Hoffentlich sorgt das für etwas Klarheit, andernfalls kann ich weitere Informationen/Beispiele hinzufügen

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post