Сделать PostgreSQL немного более устойчивым к ошибкам?

StackOverflow https://stackoverflow.com/questions/967463

  •  12-09-2019
  •  | 
  •  

Вопрос

Это своего рода общий вопрос, который возникал в нескольких контекстах, приведенный ниже пример является репрезентативным, но не исчерпывающим.Меня интересуют любые способы научиться работать с Postgres на несовершенных (но достаточно близких) источниках данных.

Конкретный случай - я использую Postgres с PostGIS для работы с правительственными данными, опубликованными в шейп-файлах и xml.Использование модуля shp2pgsql, распространяемого вместе с PostGIS (например, на это dataset) Я часто получаю схему, подобную этой:

   Column   |         Type          | 
------------+-----------------------+-
 gid        | integer               |
 st_fips    | character varying(7)  | 
 sfips      | character varying(5)  | 
 county_fip | character varying(12) | 
 cfips      | character varying(6)  | 
 pl_fips    | character varying(7)  | 
 id         | character varying(7)  | 
 elevation  | character varying(11) | 
 pop_1990   | integer               | 
 population | character varying(12) | 
 name       | character varying(32) | 
 st         | character varying(12) | 
 state      | character varying(16) | 
 warngenlev | character varying(13) | 
 warngentyp | character varying(13) | 
 watch_warn | character varying(14) | 
 zwatch_war | bigint                | 
 prog_disc  | bigint                | 
 zprog_disc | bigint                | 
 comboflag  | bigint                | 
 land_water | character varying(13) | 
 recnum     | integer               | 
 lon        | numeric               | 
 lat        | numeric               | 
 the_geom   | geometry              |

Я знаю, что по крайней мере 10 из этих переменных - fips, elevation, population и т.д. - должны быть целыми числами;но при попытке использовать их как таковые я получаю ошибки.В общем, я думаю, что мог бы решить большинство своих проблем, разрешив Postgres принимать пустую строку в качестве значения по умолчанию для столбца - скажем, 0 или -1 для типа int - при изменении столбца и типа.Возможно ли это?

Если я создам таблицу перед импортом с объявлениями типов, сгенерированными из исходного источника данных, я получу лучшие типы, чем с shp2pgsql, и смогу перебирать исходные записи, передавая их в базу данных, отбрасывая все неудачные вставки.Основная проблема заключается в том, что если у меня будет 1% плохих полей, равномерно распределенных по 25 столбцам, я потеряю 25% своих данных, поскольку данная вставка завершится ошибкой, если какое-либо поле будет плохим.Я бы хотел иметь возможность сделать вставку с максимальным усилием и исправить любые проблемы позже, вместо того чтобы терять так много строк.

Любой вклад от людей, имевших дело с подобными проблемами, приветствуется - я не сторонник MySQL, пытающийся заставить PostgreSQL совершать все те же ошибки, к которым я привык, - просто имею дело с данными, над которыми у меня нет полного контроля.

Это было полезно?

Решение

Не могли бы вы создать SQL-файл из shp2pgsql и немного обработать данные перед его выполнением?Если данные находятся в формате КОПИРОВАНИЯ, их должно быть легко разобрать и изменить "" на " " (вставить как null) для столбцов.

Другой возможностью было бы использовать shp2pgsql для загрузки данных в промежуточную таблицу, где все поля определены как просто тип "text", а затем использовать INSERT...Оператор SELECT для копирования данных в ваше конечное местоположение, с возможностью массирования данных в SELECT для преобразования пустых строк в null и т.д.

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

Вы спрашивали об исправлении этого при изменении типа столбца:вы тоже можете это сделать, например:

steve@steve@[local] =# create table test_table(id serial primary key, testvalue text not null);
NOTICE:  CREATE TABLE will create implicit sequence "test_table_id_seq" for serial column "test_table.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "test_table_pkey" for table "test_table"
CREATE TABLE
steve@steve@[local] =# insert into test_table(testvalue) values('1'),('0'),('');
INSERT 0 3
steve@steve@[local] =# alter table test_table alter column testvalue type int using case testvalue when '' then 0 else testvalue::int end;
ALTER TABLE
steve@steve@[local] =# select * from test_table;
 id | testvalue
----+-----------
  1 |         1
  2 |         0
  3 |         0
(3 rows)

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top