0

これは、いくつかの状況で出てきた一種の一般的な質問です。以下の例は代表的なものですが、網羅的なものではありません。私は、不完全な(しかし十分に近い)データソースでPostgresを使用する方法を学ぶことに興味があります。

特定のケース-シェープファイルとxmlで公開された政府データを処理するためにPostGISでPostgresを使用しています。PostGISで配布されているshp2pgsqlモジュールを使用すると(たとえば、このデータセットで)、次のようなスキーマを取得することがよくあります。

   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              |

これらのvarcharのうち少なくとも10個(fips、標高、人口など)はintである必要があることを私は知っています。しかし、それらをそのようにキャストしようとすると、エラーが発生します。一般に、列を変更して型を変更するときに、Postgresが列のデフォルト値(たとえば、int型の場合は0または-1)として空の文字列を受け入れるようにすることで、ほとんどの問題を解決できると思います。これは可能ですか?

元のデータソースから生成された型宣言を使用してインポートする前にテーブルを作成すると、shp2pgsqlを使用するよりも優れた型が得られ、データベースにフィードするソースエントリを反復処理して、失敗した挿入を破棄できます。基本的な問題は、1%の不良フィールドがあり、25列に均等に分散されている場合、いずれかのフィールドが不良であると特定の挿入が失敗するため、データの25%が失われることです。それほど多くの行を失うのではなく、ベストエフォートの挿入を作成して、後で問題を修正できるようにしたいと思います。

同様の問題を扱ったことのある人からの意見は大歓迎です。私は、PostgreSQLを打ち負かして、慣れているのと同じ間違いを犯そうとしているMySQLの男ではありません。完全に制御できないデータを扱っているだけです。

4

1 に答える 1

3

shp2pgsql から SQL ファイルを生成し、それを実行する前にデータのいくつかのマッサージを行っていただけますか? データが COPY 形式の場合、列の "" を "\N" (null として挿入) に簡単に解析および変更できるはずです。

もう 1 つの可能性は、shp2pgsql を使用して、すべてのフィールドが単なる「テキスト」タイプとして定義されているステージング テーブルにデータをロードし、次に INSERT...SELECT ステートメントを使用してデータを最終的な場所にコピーすることです。 SELECT でデータを処理して空白文字列を null に変換するなど。

文字列が int に変換される方法などの動作をオーバーライドする方法はないと思います。おそらく、独自の型またはドメインを作成し、より寛大な暗黙のキャストを定義できます...しかし、これはかなり厄介に聞こえます、型は実際にはデータがシステムに到着する方法の単なる成果物であり、その後保持したいものではないためです.

列のタイプを変更するときにそれを修正することについて尋ねました: あなたもそれを行うことができます, 例えば:

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)

これは、上で提案した「ステージング テーブル」のアイデアとほとんど同じですが、ステージング テーブル最終的なテーブルになる点が異なります。このように列の型を変更するには、とにかくテーブル全体を書き直す必要があります。したがって、実際には、ステージング テーブルを使用して複数の列を一度に再フォーマットする方が効率的である可能性があります。

于 2009-06-08T23:55:23.437 に答える