Данные Postgresql: разъяснение массива строк - PullRequest
0 голосов
/ 03 мая 2018

В настоящее время я работаю над задачей, которая перенесет дату из PostgreSQL в другую базу данных PostgreSQL. Данные одного поля должны быть разделены на три столбца (например, имя_отца, должно быть разделено на f_name, f_middle_name, f_last_name). Я искал по сети, и я думаю, что я могу использовать string_to_array для этой задачи. Теперь моя проблема заключается в том, как назначить индекс массива строки полям целевой БД (целевая БД имеет имя f_name, f_middle_name, f_last_name, в то время как исходная БД имеет только поле папа-имя).

    cur_t.execute("""
    SELECT TRANSLATE(studentnumber, '- ', ''), string_to_array(father_name)
    cur_p.execute(""" INSERT INTO "a_recipient" (student_id, f_name,   f_middle_name, f_last_name) VALUES ('%s', '%s', '%s', '%s') """ % (row[0]
row[1][0], row[1][1], row[1][2]))

Я просто не знаю, как получить доступ к индексу массива и назначить его в качестве значения в полях назначения.

Ссылки: string_to_array string_to_array

Есть предложения?

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Пока можно превратить массив в набор столбцов у вас не будет фиксированного набора столбцов. Например, если вы разделите father_name на три части, это нормально для John Wilkes Booth, но как насчет Yarrow Hock? Или Beyoncé? Или Bernal Diaz Del Castillo? Вам нужно что-то более умное, чем просто разделение на пробелы.

Хотя вы могли бы написать что-то в Postgresql, вероятно, в виде хранимой процедуры , проще, хотя и медленнее, выполнять преобразования данных в Python. Так как вам все равно придется запускать данные через Python (или делать что-то сложное, чтобы связать две базы данных), и, поскольку (надеюсь) это разовая вещь, производительность не критична.

Я не очень хорош в Python, но было бы что-то вроде этого.

cur_t.execute("""SELECT studentnumber, father_name FROM something""")

for row in cur_t:
    father = parse_name(row['father_name'])
    student_id = fix_studentnumber(row['studentnumber'])

    cur_p.execute("""
        INSERT INTO "a_recipient" (student_id, f_name, f_middle_name, f_last_name)
        VALUES ('%s', '%s', '%s', '%s')
        """ % (student_id, father['first'], father['middle'], father['last'])
    )

Тогда вы напишите parse_name и fix_studentnumber и любые другие необходимые функции для очистки данных в Python. И вы можете их модульное тестирование.

Примечание: поскольку доступ к столбцам по номеру (т. Е. row[5]) трудно читать и поддерживать, вы, вероятно, захотите использовать conn_t.cursor(cursor_factory=psycopg2.extras.DictCursor), чтобы вы могли получить доступ к столбцам по имени, как я указал выше.

0 голосов
/ 03 мая 2018

почему бы не сделать это напрямую в SQL:

vao@so=# create table so12(a text, b text, c text);
CREATE TABLE
vao@so=# with a(i) as (values('1,2,5'))
, s as (select string_to_array(i,',') ar from a)
insert into so12 select ar[1],ar[2],ar[3] from s;
INSERT 0 1
vao@so=# select * from so12;
┌───┬───┬───┐
│ a │ b │ c │
├───┼───┼───┤
│ 1 │ 2 │ 5 │
└───┴───┴───┘
(1 row)

обновление Я упустил момент, что это происходит в рамках нескольких баз данных, поэтому вам нужно будет использовать dblink или создать postgres_fdw чужую таблицу. И то, и другое будет намного быстрее, чем выбор массива, а затем цикл по строкам с помощью оператора insert into .. values(..)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...