यदि मौजूद नहीं है तो PostgreSQL तालिका बनाएँ


174

MySQL स्क्रिप्ट में आप लिख सकते हैं:

CREATE TABLE IF NOT EXISTS foo ...;

... अन्य सामान ...

और फिर आप टेबल को दोबारा बनाए बिना स्क्रिप्ट को कई बार चला सकते हैं।

आप PostgreSQL में यह कैसे करते हैं?

जवाबों:


278

यह सुविधा Postgres 9.1 में लागू की गई है :

CREATE TABLE IF NOT EXISTS myschema.mytable (i integer);



के लिए पुराने संस्करणों , यहाँ इसके आसपास काम करने के लिए एक समारोह है:

CREATE OR REPLACE FUNCTION create_mytable ()
  RETURNS void AS
$func$
BEGIN
   IF EXISTS (SELECT FROM pg_catalog.pg_tables 
              WHERE  schemaname = 'myschema'
              AND    tablename  = 'mytable') THEN
      RAISE NOTICE 'Table myschema.mytable already exists.';
   ELSE
      CREATE TABLE myschema.mytable (i integer);
   END IF;
END
$func$ LANGUAGE plpgsql;

कॉल करें:

SELECT create_mytable();        -- call as many times as you want. 

टिप्पणियाँ:

  • कॉलम schemanameऔर tablenameमें pg_tablesकेस-संवेदी होते। यदि आप CREATE TABLEस्टेटमेंट में डबल-कोट आइडेंटिफ़ायर करते हैं, तो आपको उसी स्पेलिंग का उपयोग करने की आवश्यकता है। यदि आप नहीं करते हैं, तो आपको लोअर-केस स्ट्रिंग्स का उपयोग करने की आवश्यकता है। देख:

  • pg_tablesकेवल वास्तविक तालिकाएँ हैं । पहचानकर्ता संबंधित वस्तुओं पर अभी भी कब्जा कर सकता है। देख:

  • यदि इस फ़ंक्शन को निष्पादित करने वाली भूमिका में तालिका बनाने के लिए आवश्यक विशेषाधिकार नहीं हैं, तो आप SECURITY DEFINERफ़ंक्शन के लिए उपयोग करना चाहते हैं और आवश्यक विशेषाधिकारों के साथ किसी अन्य भूमिका के स्वामित्व में कर सकते हैं । यह संस्करण पर्याप्त सुरक्षित है।


मुझे मौजूदा पोस्टग्रेज 8.4 डेटाबेस का उपयोग करने के लिए मजबूर किया जा रहा है। यह हैक करता है चाल, धन्यवाद!
असीम

1
@Boundless: मैंने देखा कि आपका संपादन "बहुत मामूली" के रूप में अस्वीकार कर दिया गया था। मैंने इसे लागू किया, क्योंकि यह चोट नहीं पहुंचाएगा। हालाँकि, आपको CREATE FUNCTIONकेवल एक बार निष्पादित करना चाहिए । यह है SELECT create_mytable();कि आप कई बार कॉल करना चाह सकते हैं।
एरविन ब्रान्डेसटेटर

1
ब्रांडस्टेटर: मैं आपसे सहमत हूं। समस्या यह है कि मैं भाग गया था कि मुझे पता नहीं था कि फ़ंक्शन बनाया गया था या नहीं (जैसे तालिका मौजूद हो सकती है या नहीं भी हो सकती है)। इसलिए मैं यह सुनिश्चित करना चाहता हूं कि फोन करने से पहले फ़ंक्शन बनाया जाए।
असीम

82

इसे इस्तेमाल करे:

CREATE TABLE IF NOT EXISTS app_user (
  username varchar(45) NOT NULL,
  password varchar(450) NOT NULL,
  enabled integer NOT NULL DEFAULT '1',
  PRIMARY KEY (username)
)

यह वास्तव में क्लीनर समाधान है। उखाड़ा जाना चाहिए।
SDReyes

4
वास्तव में, मैं 'समाधान' से जुड़े कितने समाधानों से घबरा गया हूं।
SDReyes

8
@SDReyes पोस्टग्रेज 9.1 से पहले उन अन्य समाधानों को पोस्ट किया गया था जिसमें IF NOT EXISTSविकल्प शामिल था ।
क्रिस

2
यह निश्चित नहीं है कि @ erwin-brandstetter उत्तर के रूप में यह उत्तर कैसे योगदान देता है, अपने आप में पूर्ण था।
कॉमिवेंटर

@comiventor सही, यह कभी भी दिखाता है कि पैरामीटर उपयोग कैसे होता है। प्रमुख उत्तर मुझे यह नहीं मिला कि जब तक मैंने इसे नहीं देखा। यह थोड़ा मदद करता है।
गुस्सा 84

7

मैंने मौजूदा उत्तरों में से एक सामान्य समाधान तैयार किया है जिसे किसी भी तालिका के लिए पुन: उपयोग किया जा सकता है:

CREATE OR REPLACE FUNCTION create_if_not_exists (table_name text, create_stmt text)
RETURNS text AS
$_$
BEGIN

IF EXISTS (
    SELECT *
    FROM   pg_catalog.pg_tables 
    WHERE    tablename  = table_name
    ) THEN
   RETURN 'TABLE ' || '''' || table_name || '''' || ' ALREADY EXISTS';
ELSE
   EXECUTE create_stmt;
   RETURN 'CREATED';
END IF;

END;
$_$ LANGUAGE plpgsql;

उपयोग:

select create_if_not_exists('my_table', 'CREATE TABLE my_table (id integer NOT NULL);');

यह सिर्फ एक पैरामीटर लेने के लिए आगे सरलीकृत किया जा सकता है अगर कोई क्वेरी पैरामीटर से तालिका का नाम निकालेगा। इसके अलावा मैंने स्कीमा छोड़ दिया।


2

यह समाधान कुछ हद तक Erwin Brandstetter के उत्तर के समान है, लेकिन केवल sql भाषा का उपयोग करता है।

सभी PostgreSQL स्थापनाओं में डिफ़ॉल्ट रूप से plpqsql भाषा नहीं है, इसका मतलब है कि आपको CREATE LANGUAGE plpgsqlफ़ंक्शन बनाने से पहले कॉल करना पड़ सकता है , और बाद में फिर से भाषा को हटाना होगा, डेटाबेस को उसी स्थिति में छोड़ना होगा जैसा पहले था (लेकिन केवल डेटाबेस के साथ शुरू करने के लिए plpgsql भाषा नहीं थी)। देखें कि जटिलता कैसे बढ़ती है?

यदि आप अपनी स्क्रिप्ट को स्थानीय स्तर पर चला रहे हैं, तो plpgsql को जोड़ना समस्या नहीं हो सकता है, हालाँकि, यदि स्क्रिप्ट का उपयोग किसी ग्राहक के लिए स्कीमा सेट करने के लिए किया जाता है, तो ग्राहक डेटाबेस में इस तरह से परिवर्तन छोड़ना वांछनीय नहीं हो सकता है।

यह समाधान एंड्रियास शेरबाम की एक पोस्ट से प्रेरित है ।

-- Function which creates table
CREATE OR REPLACE FUNCTION create_table () RETURNS TEXT AS $$
    CREATE TABLE table_name (
       i int
    );
    SELECT 'extended_recycle_bin created'::TEXT;
    $$
LANGUAGE 'sql';

-- Test if table exists, and if not create it
SELECT CASE WHEN (SELECT true::BOOLEAN
    FROM   pg_catalog.pg_tables 
    WHERE  schemaname = 'public'
    AND    tablename  = 'table_name'
  ) THEN (SELECT 'success'::TEXT)
  ELSE (SELECT create_table())
END;

-- Drop function
DROP FUNCTION create_table();

Plpgsql उपलब्ध होने पर भी आपका समाधान बहुत अच्छा है। समय पर विद्यमान वस्तुओं पर विचारों और कार्यों के निर्माण के लिए यह आसान विस्तार योग्य है। विदेशी सर्वर से तालिकाओं पर उदाहरण। आपने मेरा दिन बचाया! धन्यवाद!
एलेक्स यू

2

कोई सृजन नहीं है, अगर नहीं है तो ... लेकिन आप इसके लिए एक सरल प्रक्रिया लिख ​​सकते हैं, जैसे कुछ:

CREATE OR REPLACE FUNCTION prc_create_sch_foo_table() RETURNS VOID AS $$
BEGIN

EXECUTE 'CREATE TABLE /* IF NOT EXISTS add for PostgreSQL 9.1+ */ sch.foo (
                    id serial NOT NULL, 
                    demo_column varchar NOT NULL, 
                    demo_column2 varchar NOT NULL,
                    CONSTRAINT pk_sch_foo PRIMARY KEY (id));
                   CREATE INDEX /* IF NOT EXISTS add for PostgreSQL 9.5+ */ idx_sch_foo_demo_column ON sch.foo(demo_column);
                   CREATE INDEX /* IF NOT EXISTS add for PostgreSQL 9.5+ */ idx_sch_foo_demo_column2 ON sch.foo(demo_column2);'
               WHERE NOT EXISTS(SELECT * FROM information_schema.tables 
                        WHERE table_schema = 'sch' 
                            AND table_name = 'foo');

         EXCEPTION WHEN null_value_not_allowed THEN
           WHEN duplicate_table THEN
           WHEN others THEN RAISE EXCEPTION '% %', SQLSTATE, SQLERRM;

END; $$ LANGUAGE plpgsql;

2

कोई सृजन नहीं है, अगर नहीं है तो ... लेकिन आप इसके लिए एक सरल प्रक्रिया लिख ​​सकते हैं, जैसे कुछ:

CREATE OR REPLACE FUNCTION execute(TEXT) RETURNS VOID AS $$
BEGIN
  EXECUTE $1;
END; $$ LANGUAGE plpgsql;


SELECT 
  execute($$
      CREATE TABLE sch.foo 
      (
        i integer
      )
  $$) 
WHERE 
  NOT exists 
  (
    SELECT * 
    FROM information_schema.tables 
    WHERE table_name = 'foo'
      AND table_schema = 'sch'
  );

अंदर एक ट्रिगर हमेशा काम नहीं करता है: gist.github.com/igilfanov/4df5e90d8a88d653132746a223639f45 ERROR: रिश्ता "फू" पहले से ही मौजूद है
IGfefovov
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.