PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

त्रुटि:PostgreSQL COPY का उपयोग करते समय अंतिम अपेक्षित कॉलम के बाद अतिरिक्त डेटा

एक खाली टेबल काम नहीं करेगी। आपको ऐसी तालिका चाहिए जो इनपुट डेटा की संरचना से मेल खाती हो। कुछ इस तरह:

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. एक पोस्टग्रेज सुपरयुसर क्या है

  2. PostgreSQL में एन्क्रिप्टेड पासवर्ड के साथ उपयोगकर्ता बनाना

  3. क्या एक प्रश्न में प्रत्येक पंक्ति के लिए अलग-अलग स्थितियां संभव हैं?

  4. एक पैरामीटर पूछें (postgresql.conf सेटिंग) जैसे max_connections

  5. अजवाइन और लेनदेन.परमाणु