एक खाली टेबल काम नहीं करेगी। आपको ऐसी तालिका चाहिए जो इनपुट डेटा की संरचना से मेल खाती हो। कुछ इस तरह:
CREATE TABLE raw_data (
col1 int
, col2 int
...
);
आपको टैब
declare घोषित करने की आवश्यकता नहीं है DELIMITER
. के रूप में चूंकि यह डिफ़ॉल्ट है:
COPY raw_data FROM '/home/Projects/TestData/raw_data.txt';
800 कॉलम आप कहते हैं? कई कॉलम आमतौर पर आपके डिज़ाइन में समस्या का संकेत देते हैं। वैसे भी, तालिका बनाएं
. को आधा स्वचालित करने के तरीके हैं स्क्रिप्ट।
स्वचालन
सरलीकृत अपरिष्कृत डेटा मानते हुए
1 2 3 4 -- first row contains "column names"
1 1 0 1 -- tab separated
1 0 0 1
1 0 1 1
कोई भिन्न DELIMITER
परिभाषित करें (एक जो आयात डेटा में बिल्कुल भी नहीं होता है), और एक अस्थायी स्टेजिंग तालिका में एक पाठ
के साथ आयात करें कॉलम:
CREATE TEMP TABLE tmp_data (raw text);
COPY tmp_data FROM '/home/Projects/TestData/raw_data.txt' WITH (DELIMITER '§');
यह क्वेरी तालिका बनाएं
बनाता है स्क्रिप्ट:
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 यहां
पुरानी SQL Fiddle