#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. Да, так и есть. Спасибо.