Pregunta

Esto es una especie de pregunta general que ha surgido en varios contextos, el siguiente ejemplo es representativa pero no exhaustiva. Estoy interesado en cualesquiera formas de aprender a trabajar con Postgres en fuentes de datos imperfectos (pero lo suficientemente cerca).

El caso específico - Estoy usando PostgreSQL con PostGIS para trabajar con datos gubernamentales publicados en archivos de formas y XML. Con el módulo de shp2pgsql distribuido con PostGIS (por ejemplo en este conjunto de datos) A menudo recibo esquema siguiente:

   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              |

Sé que al menos 10 de esos varchars - el FIPS, elevación, población, etc., deben ser enteros; pero cuando se trata de echarlos como tal recibo errores. En general, creo que podría resolver la mayoría de mis problemas permitiendo Postgres para aceptar una cadena vacía como un valor por defecto para una columna - por ejemplo 0 ó -1 para un tipo int - cuando se altera una columna y cambiar el tipo. ¿Es esto posible?

Si creo la tabla antes de importar las declaraciones de tipo generados a partir de la fuente de datos original, consigo mejores tipos que con shp2pgsql, y puede iterar sobre las entradas con las fuentes de alimentación a la base de datos, descartando cualquier insertos fallidos. El problema fundamental es que si tengo 1% de campos malos, distribuidos uniformemente sobre 25 columnas, voy a perder el 25% de mis datos desde una inserción dada fallará si cualquier campo es malo. Me gustaría ser capaz de hacer un inserto de mejor esfuerzo y solucione los problemas más adelante, en lugar de perder que muchas filas.

Cualquier entrada de la gente de haber tratado con problemas similares es bienvenido - No soy un chico tratando de MySQL PostgreSQL bateador en la fabricación de los mismos errores que estoy acostumbrado - sólo se trata de datos que no tengo control total sobre .

¿Fue útil?

Solución

Podría producir un archivo de SQL desde shp2pgsql y hacer un poco de masaje de los datos antes de ejecutarlo? Si los datos están en formato papel, debe ser fácil de analizar y el cambio "" a "\ n" (insertar como nulo) para las columnas.

Otra posibilidad sería utilizar shp2pgsql para cargar los datos en una tabla de ensayo en el que todos los campos se definen como acaba de tipo 'texto', y luego usar un INSERT ... SELECT para copiar los datos a su ubicación final, con la posibilidad de dar masajes a los datos en el SELECT para convertir cadenas en blanco para anular etc.

No creo que haya una manera de reemplazar el comportamiento de cómo se convierten las cadenas enteros y así sucesivamente: posiblemente se podrían crear su propio tipo o dominio, y definir una conversión implícita de que era más indulgente, pero esto ... suena bastante desagradable, ya que los tipos son en realidad los artefactos de cómo su datos llegan en el sistema y no es algo que desea mantener alrededor después de eso.

Usted preguntó por repararlo cuando se cambia el tipo de columna: se puede hacer eso también, por ejemplo:

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)

Lo que es casi equivalente a la idea de "tabla de ensayo" he sugerido más arriba, excepto que ahora la tabla de ensayo es su mesa final. La alteración de un tipo de columna como esta requiere volver a escribir toda la mesa de todos modos:. Lo que en realidad, el uso de una tabla de etapas múltiples y formatear columnas a la vez es probable que sea más eficiente

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top