Обновите таблицу Firebird данными из csv Python

#python #sql #csv #firebird

Вопрос:

Допустим, у нас есть CSV-файл с платежной информацией, подобной этой:

 somthing1:500.00
somthing2:300.00
somthing3:200.00
 

Мне нужно обновить разные строки tableB в базе данных Firebird, в которой есть столбец, называемый paid значениями во втором столбце CSV-файла. По этой причине я создал глобальную временную таблицу только для того, чтобы загрузить в нее данные, а затем обновить нужную таблицу. Что я пробовал, так это:

 idd = 0
with open('file.csv', 'r', encoding='utf-8', newline='') as file:
    reader = list(csv.reader(file, delimiter=':'))
    for row in reader:
        idd  = 1
            c.execute("""INSERT INTO temp_table (id,code,paid) VALUES (?,?,?)""", 
            (idd,str(row[0]),str(row[1]), ))
 

Это работает так, как ожидалось — таблица заполнена. После этого я попытался обновить другую таблицу, подобную этой:

 c.execute("""select paid from temp_table;""")
res = c.fetchall()
for r in res:
    c.execute(f"""UPDATE tableB SET paid = {r[0]} WHERE oid = 10;""")
 

Это действительно работает — для каждого результата SELECT запроса он обновляет все строки с одинаковым значением следующего результата. Я попробовал MERGE в самой базе данных с тем же результатом — каждая строка обновляется с одинаковым значением из temp_table :

 MERGE INTO tableB b
USING (SELECT paid FROM temp_table) e
ON b.paid = 0 AND oid = 10
WHEN MATCHED THEN
UPDATE SET b.paid = e.paid;
 

Мне нужен какой-то способ обновить первую строку tableB с помощью первой строки из CSV и так далее. Что я упускаю?

Ответ №1:

Проблема в том, что вы не сопоставляете строки из temp_table со строками в tableB .

При первой попытке вы обновляете все строки tableB с oid = 10 помощью . Аналогично, во второй попытке вы обновляете все строки с paid = 0 без корреляции temp_table .

Вам нужно добавить условие для сопоставления строк между таблицами, скажем, в обеих есть id столбец:

 MERGE INTO tableB b
USING (SELECT paid FROM temp_table) e
ON b.paid = 0 AND b.oid = 10 AND b.id = e.id
WHEN MATCHED THEN
  UPDATE SET b.paid = e.paid;
 

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

1. Будет ли это работать, если столбцы идентификаторов не равны, т. е. b.id = 10 , e.id = 5 ?

2. @T0ny1234 Для каждой строки tableB1 должен быть способ соотнести эту строку tableB не более чем с одной строкой (на самом temp_table деле Firebird позволяет сопоставлять одну строку с несколькими строками и может для этого обновляться несколько раз , но это следует считать ошибкой). Является ли это идентификатором (который был только моим примером) или совершенно другим условием, я не могу знать, потому что вы не предоставили достаточной информации в своем вопросе, чтобы сделать это определение.

3. Еще раз спасибо вам. То, что вы сказали, — это именно то, чего я боялся, и есть причина всего этого. Для того, чтобы я получил необходимую информацию, я должен сделать JOIN с другой таблицей в SELECT состоянии.

4. @T0ny1234 Добавление соединения должно быть простым, не так ли?

5. Да, так и есть. Спасибо.