Получите данные из базы данных и снова запишите их обратно

#python #sql #database #mariadb

#python #sql #База данных #mariadb

Вопрос:

Я написал функцию, прочитав файл Excel и записав его в базу данных. Это работает!

Получение данных из базы данных также работает.

Где я застрял, так это в том, что функция должна считывать каждую строку, вычислять ее и записывать результат обратно в базу данных.

Я также хочу узнать, сколько строк было записано в базе данных, а затем передать это число в цикл for.

Первая функция используется для чтения данных Excel и записи их в базу данных:

     def Load_into_database():
    file_path = label_file["text"]
    try:
        excel_filename = r"{}".format(file_path)
        if excel_filename[-4:] == ".csv":
            df = pd.read_csv(excel_filename, header=0, names=['Probe_Dehnung', 'Probe_Standardkraft'], sheet_name='Probe 1', skiprows=2, usecols="A:B")
        else:
            df = pd.read_excel(excel_filename, header=0, names=['Probe_Dehnung', 'Probe_Standardkraft'], sheet_name='Probe 1', skiprows=2, usecols="A:B")

    except ValueError:
        tk.messagebox.showerror("Information", "The file you have chosen is invalid")
        return None
    except FileNotFoundError:
        tk.messagebox.showerror("Information", f"No such file as {file_path}")
        return None

    engine = create_engine("mariadb mariadbconnector://root:pw123@127.0.0.1:3306/polymer")
    df.to_sql('zugversuch_probe_1',
              con=engine,
              if_exists='append',
              index=False)

    c.execute("SELECT * FROM zugversuch_probe_1")
    records = c.fetchall()
    print("Records", records)
    calculation(records)
 

Вторая функция заключается в чтении каждой строки из одного столбца и вычислении ее по строкам, а затем записи обратно в базу данных:

 def calculation(records):
    # query the database
    for record_id in records:
        c.execute("SELECT * FROM zugversuch_probe_1 WHERE ID = "   str(record_id))
        records = c.fetchall()[0]

        # Berechnung Dehnung
        dehnung = calc_dehnung(records[1])
        print("Dehnung", dehnung)

        sql_command = """
        INSERT INTO zugversuch_probe_1
        (Dehnung)
        VALUES(%s)"""

        c.execute("""UPDATE zugversuch_probe_1 SET
            Dehnung = %s
            WHERE ID = %s""",
                  (
                      dehnung.get(),
                      record_id
                  ))

        values = (dehnung.get())

        # commit changes
        conn.commit
        # close connection
        conn.close()

def calc_dehnung(value_list):
    return (value_list[0] / 0.123) * 100
 

После запуска моего кода я получаю сообщение об ошибке:

c.выполнить(«SELECT * FROM zugversuch_probe_1 WHERE ID = » str(record_id)) mariadb.Ошибка OperationalError: неизвестный столбец ‘None’ в предложении ‘where’

К сожалению, у меня также есть проблема, заключающаяся в том, что идентификатор в базе данных не запускается снова с 0 после того, как я удалил данные, но продолжает подсчитываться.

Вот скриншот базы данных: Скриншот базы данных

Вот скриншот файла Excel: Скриншот Excel

Заранее благодарю вас

Комментарии:

1. ваши операторы sql уязвимы для SQL-инъекций owasp.org/www-community/attacks/SQL_Injection

2. да, но это был не его вопрос. Кроме того, внедрение sql актуально только в том случае, если вы имеете дело с пользовательским вводом. Я не вижу здесь никакого пользовательского ввода, это похоже на автономный скрипт. Это нормально, чтобы упомянуть об этом, но это не то, что вызывает его ошибку.

Ответ №1:

c.fetchall() возвращает список кортежей, которые необходимо распаковать в вашем цикле

 c.execute("SELECT * FROM zugversuch_probe_1")
for record in c.fetchall():
    record_id, probe_dehnung, dehnung, probe_standardkraft = record
    dehnung = calc_dehnung(probe_dehnung)
    c.execute("""UPDATE zugversuch_probe_1 SET
        Dehnung = %s
        WHERE ID = %s""",
              (
                  dehnung,
                  record_id
              ))
 

Комментарии:

1. Спасибо. Я попробовал ваше предложение, но также получил сообщение об ошибке: «return (value_list[0] / 0.123) * 100 TypeError: объект ‘float’ не подлежит подписке» Я изменил строку dehnung = calc_dehnung(probe_dehnung) на dehnung = (probe_dehnung[0] / 0.123) * 100 и теперь получаю сообщение об ошибке: dehnung.get(), AttributeError: объект ‘float’ не имеетатрибут ‘get’ Что я могу сделать, чтобы исправить ошибку?

2. извините, что .get остался в вашем коде, я его удалил

3. Я не получаю сообщение об ошибке, но столбец «Dehnung» в базе данных по-прежнему остается пустым.

Ответ №2:

Я не вижу никаких причин, по которым вы используете dehnung.get() . Функция .get() используется при извлечении значений из словаря, но, похоже, что это список (или число?). Это может привести к неожиданному нарушению вашего кода и сбить с толку механизм sql.

вы печатаете эту переменную здесь

 print("Dehnung", dehnung)
 

если это значение, которое вы хотите вставить, просто удалите .get() в следующие 2 раза, когда вы его используете.

Вам также необходимо распаковать значения из переменной «record_id». Я предлагаю вам переименовать эту переменную в «record», потому что это не record_id — это одна строка результатов из базы данных, которая содержит все значения из этой строки, а идентификатор является только одним из них (первым). вы можете получить к нему доступ с помощью record_id[0]

 c.execute("SELECT * FROM zugversuch_probe_1 WHERE ID = "   str(record_id[0]))
 

возможно, вы также используете здесь неправильное значение:

 dehnung = calc_dehnung(records[1])
 

вероятно, вы имели в виду использовать record_id[1] вместо records[1] . Опять же, я настоятельно рекомендую вам переименовать переменную «record_id» в «record», это, по-видимому, является источником некоторой путаницы

Комментарии:

1. Хорошо, спасибо. Теперь я изменил «record_id» на «record», как вы описали, и две строки: c.execute(«SELECT * FROM zugversuch_probe_1 WHERE ID = » str(запись [0])) dehnung = calc_dehnung(запись [1]) Теперь я получаю сообщение об ошибке: return (value_list[0] / 0.123) * 100 TypeError: объект ‘float’ не подлежит подписке

2. Вам нужно переименовать записи [1] в запись [1], удалить [0] в функции calc_dehnung() . Я также рекомендую переименовать переменную «value_list» в «value», потому что теперь вы больше не отправляете список в эту функцию, а только само число (или число с плавающей запятой). С чем у вас возникла проблема, так это с пониманием того, что sql возвращает список списков (записей). Одна строка из них представляет собой список (запись), а одно значение этого списка — это число с плавающей запятой, которое вы хотите преобразовать. Вы должны попытаться отслеживать это, печатая и используя соответствующие имена переменных.

3. хорошо, спасибо, я попробовал, но теперь я получаю сообщение об ошибке: c.execute("""UPDATE zugversuch_probe_1 SET mariadb.DataError: Data type 'tuple' in column 1 not supported in MariaDB Connector/Python

4. Это новый код: def calculation(records): for record in records: c.execute("SELECT * FROM zugversuch_probe_1 WHERE ID = " str(record[0])) records = c.fetchall()[0] dehnung = calc_dehnung(record[1]) print("Dehnung", dehnung) sql_command = """INSERT INTO zugversuch_probe_1 (Dehnung) VALUES(%s)""" c.execute("""UPDATE zugversuch_probe_1 SET Dehnung = %s WHERE ID = %s""", (dehnung, record)) values = (dehnung) conn.commit conn.close()

Ответ №3:

да, это работает!

это не сработало по той причине, что я забыл скобки в conn.commit()

Вот мой новый код, который я получил от @vinzBad

     def update():
        c.execute("SELECT * FROM zugversuch_probe_1")
        for record in c.fetchall():
            try:
                record_id, probe_dehnung, dehnung, probe_standardkraft = record
                dehnung = (probe_dehnung / 0.123) * 100

                c.execute("""UPDATE zugversuch_probe_1 SET
                        Dehnung = %s
                        WHERE ID = %s""",
                          (
                              dehnung,
                              record_id
                          ))

                conn.commit()

            except mariadb.Error as e:
                print(f"Error connecting to MariaDB Platform: {e}")
                sys.exit(1)

        conn.close()
 

Вот скриншот mariadb

Спасибо за помощь!

Комментарии:

1. здорово, что вы смогли это решить. пожалуйста, проголосуйте за ответы, которые помогли вам найти решение, и вы также можете принять свой ответ, чтобы закрыть этот вопрос