空のテーブルは機能しません。入力データの構造に一致するテーブルが必要です。次のようなもの:
CREATE TABLE raw_data (
col1 int
, col2 int
...
);
tab
を宣言する必要はありません DELIMITER
として これがデフォルトなので:
COPY raw_data FROM '/home/Projects/TestData/raw_data.txt';
あなたが言う800列?その数の列は通常、設計に問題があることを示します。とにかく、 CREATE TABLE
を半自動化する方法があります スクリプト。
自動化
単純化された生データを想定する
1 2 3 4 -- first row contains "column names"
1 1 0 1 -- tab separated
1 0 0 1
1 0 1 1
別のDELIMITER
を定義します (インポートデータではまったく発生しないもの)、単一の text
を使用して一時ステージングテーブルにインポートします。 列:
CREATE TEMP TABLE tmp_data (raw text);
COPY tmp_data FROM '/home/Projects/TestData/raw_data.txt' WITH (DELIMITER '§');
このクエリは、 CREATE TABLE
を作成します スクリプト:
SELECT 'CREATE TABLE tbl (col' || replace (raw, E'\t', ' bool, col') || ' bool)'
FROM (SELECT raw FROM tmp_data LIMIT 1) t;
より一般的で安全なクエリ:
SELECT 'CREATE TABLE tbl('
|| string_agg(quote_ident('col' || col), ' bool, ' ORDER BY ord)
|| ' bool);'
FROM (SELECT raw FROM tmp_data LIMIT 1) t
, unnest(string_to_array(t.raw, E'\t')) WITH ORDINALITY c(col, ord);
返品:
CREATE TABLE tbl (col1 bool, col2 bool, col3 bool, col4 bool);
有効性を確認してから実行するか、結果が信頼できる場合は動的に実行します。
DO
$$BEGIN
EXECUTE (
SELECT 'CREATE TABLE tbl (col' || replace(raw, ' ', ' bool, col') || ' bool)'
FROM (SELECT raw FROM tmp_data LIMIT 1) t
);
END$$;
次に、 INSERT
このクエリのデータ:
INSERT INTO tbl
SELECT (('(' || replace(replace(replace(
raw
, '1', 't')
, '0', 'f')
, E'\t', ',')
|| ')')::tbl).*
FROM (SELECT raw FROM tmp_data OFFSET 1) t;
または、 translate()コード>
:
INSERT INTO tbl
SELECT (('(' || translate(raw, E'10\t', 'tf,') || ')')::tbl).*
FROM (SELECT raw FROM tmp_data OFFSET 1) t;
文字列は行リテラルに変換され、新しく作成されたテーブル行タイプにキャストされ、(row)。*
で分解されます。 。
すべて完了しました。
これらすべてをplpgsql関数に入れることもできますが、SQLインジェクションから保護する必要があります。 (SOには関連するソリューションがいくつかあります。検索してみてください。
db <> fiddle こちら
Old SQL Fiddle