Делаете PostgreSQL немного более устойчивым к ошибкам? - PullRequest
0 голосов
/ 09 июня 2009

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

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

   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 из этих varchars - фипы, высота, население и т. Д. Должны быть целыми; но при попытке привести их к ошибке я получаю ошибки. В общем, я думаю, что мог бы решить большинство моих проблем, позволив Postgres принять пустую строку в качестве значения по умолчанию для столбца - скажем, 0 или -1 для типа int - при изменении столбца и изменении типа. Возможно ли это?

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

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

1 Ответ

3 голосов
/ 09 июня 2009

Не могли бы вы создать файл SQL из shp2pgsql и выполнить некоторую массивацию данных перед его выполнением? Если данные представлены в формате COPY, их должно быть легко проанализировать и заменить "" на "\ N" (вставить как ноль) для столбцов.

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

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

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

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)

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

...