Pergunta

Essa é uma espécie de pergunta geral que surgiu em vários contextos, o exemplo abaixo é representativo, mas não exaustivo. Estou interessado em aprender a trabalhar com o Postgres sobre fontes de dados imperfeitas (mas próximas o suficiente).

O caso específico - estou usando o Postgres com o PostGIS para trabalhar com dados do governo publicados em Shapefiles e XML. Usando o módulo shp2pgsql distribuído com pós -gis (por exemplo isto conjunto de dados) Eu costumo obter esquema assim:

   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              |

Eu sei que pelo menos 10 desses varchars - os FIPs, elevação, população etc. devem ser ints; Mas ao tentar lançá -los como tal, recebo erros. Em geral, acho que poderia resolver a maioria dos meus problemas, permitindo que o Postgres aceite uma string vazia como um valor padrão para uma coluna -digamos 0 ou -1 para um tipo int -ao alterar uma coluna e alterar o tipo. Isso é possível?

Se eu criar a tabela antes de importar com as declarações de tipo geradas a partir da fonte de dados original, obtenho tipos melhores do que com shp2pgsql e posso iterar sobre as entradas de origem alimentando -as para o banco de dados, descartando qualquer inserções com falha. O problema fundamental é que, se eu tiver 1% de campos ruins, distribuídos uniformemente em 25 colunas, perderei 25% dos meus dados, pois uma determinada inserção falhará se algum campo for ruim. Eu adoraria poder fazer uma inserção de melhor esforço e resolver quaisquer problemas mais tarde, em vez de perder tantas linhas.

Qualquer entrada de pessoas que tenham lidado com problemas semelhantes é bem -vindo - eu não sou um cara do MySQL tentando agredir o PostGresql a cometer os mesmos erros que estou acostumado - apenas lidando com dados que não tenho controle total.

Foi útil?

Solução

Você poderia produzir um arquivo SQL a partir de shp2pgsql e fazer uma massagem dos dados antes de executá -los? Se os dados estiverem no formato de cópia, deve ser fácil analisar e alterar "" para " n" (insira como nulo) para colunas.

Outra possibilidade seria usar shp2pgsql para carregar os dados em uma tabela de estadiamento onde todos os campos são definidos como apenas tipo de 'texto' e depois usar uma instrução de inserção ... selecione para copiar os dados para o seu local final, com a possibilidade de massagear os dados na seleção para converter strings em branco para nulo etc.

Eu não acho que exista uma maneira de substituir o comportamento de como as strings são convertidas em INTs e assim por diante: possivelmente você pode criar seu próprio tipo ou domínio e definir um elenco implícito que era mais branda ... mas isso parece bastante desagradável , como os tipos são realmente apenas artefatos de como seus dados chegam ao sistema e não algo que você deseja manter depois disso.

Você perguntou sobre como consertá -lo ao alterar o tipo de coluna: Você também pode fazer isso, por exemplo:

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)

Que é quase equivalente à ideia da "tabela de estadiamento" que sugeri acima, exceto que agora a tabela de estadiamento é Sua tabela final. Alterar um tipo de coluna como esse requer reescrever a tabela inteira de qualquer maneira: então, é provável que, usando uma tabela de preparação e reformatando várias colunas de uma só vez, provavelmente será mais eficiente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top