পোস্টগ্র্রেএসকিউএলে উপস্থিত না থাকলে কীভাবে কলাম যুক্ত করবেন?


145

প্রশ্ন সহজ। xটেবিলের কলাম কীভাবে যুক্ত করবেন y, তবে কেবল যখন xকলামটি বিদ্যমান নেই? আমি শুধুমাত্র সমাধান পাওয়া এখানে কিভাবে যদি কলাম বিদ্যমান বার করো।

SELECT column_name 
FROM information_schema.columns 
WHERE table_name='x' and column_name='y';

উত্তর:


133

"ডিও" বিবৃতিটি ব্যবহার করে এখানে একটি স্বল্প-মিষ্টি সংস্করণ দেওয়া হয়েছে:

DO $$ 
    BEGIN
        BEGIN
            ALTER TABLE <table_name> ADD COLUMN <column_name> <column_type>;
        EXCEPTION
            WHEN duplicate_column THEN RAISE NOTICE 'column <column_name> already exists in <table_name>.';
        END;
    END;
$$

আপনি এগুলি প্যারামিটার হিসাবে পাস করতে পারবেন না, আপনাকে ক্লায়েন্টের পক্ষের স্ট্রিংয়ে পরিবর্তনশীল প্রতিস্থাপনের প্রয়োজন হবে, তবে এটি একটি স্ব-অন্তর্ভুক্ত ক্যোয়ারী যা কেবলমাত্র একটি বার্তা প্রকাশ করে যদি কলামটি ইতিমধ্যে উপস্থিত থাকে, যোগ না করে এবং অন্যান্য ত্রুটি (যেমন একটি অবৈধ ডেটা টাইপ) এ ব্যর্থ হতে থাকবে।

আমি যদি এই বাহ্যিক উত্স থেকে আসা এলোমেলো স্ট্রিংগুলি থাকে তবে এই পদ্ধতির কোনওটি করার পরামর্শ দিচ্ছি না। আপনি কোন পদ্ধতি ব্যবহার করেন না কেন (ক্লিন্ট সাইড বা সার্ভার-সাইড ডায়নামিক স্ট্রিংগুলি ক্যোয়ারী হিসাবে কার্যকর করা হয়), এটি বিপর্যয়ের একটি রেসিপি হবে কারণ এটি আপনাকে এসকিউএল ইঞ্জেকশন আক্রমণে খোলে।


4
DO $$ BEGIN BEGIN CREATE INDEX type_idx ON table1 USING btree (type); EXCEPTION WHEN duplicate_table THEN RAISE NOTICE 'Index exists.'; END; END;$$;একই পদ্ধতির মধ্যে CREATE INDEX;) আপনার উত্তরের জন্য ধন্যবাদ,
মারিওশ

কেন নিশ্চিত নয় যে কেবলমাত্র বেনামে কোড ব্লক DO $$ব্যর্থতা দিয়ে শুরু করবে । আমি DO $$;যা চেষ্টা করেছি তা খুব ব্যর্থ হয়েছে, যতক্ষণ না আমি ব্লকটি শুরু করেছি যতক্ষণ DO $$DECLARE r record;না দেব পোস্টগ্র্রেস ডক্সে একটি উদাহরণে দেওয়া হয়েছে ।
nemesisfixx

9
এর সাথে সমাপ্তি END; $$একটি সিনট্যাক্স ত্রুটি (পোস্টগ্রিস 9.3), এর END $$;পরিবর্তে আমাকে ব্যবহার করতে হয়েছিল
লাইটসিস্টেম

5
ভাল পন্থা, তবে কেন নেস্টেড বিগিন / এন্ড অবরুদ্ধ? এটি আমার জন্য একটি একক স্তর নিয়ে কাজ করে। এছাড়াও শেষে একটি সেমিকোলন যুক্ত করা ($$;) বিবৃতিটিকে পিএসএইচএল-এর পক্ষে দ্ব্যর্থহীন করে তোলে।
শেন

1
এই পদ্ধতির ( EXCEPTION) কিছুটা সাধারণ, এবং এমন কোনও কাজের জন্য নিযুক্ত করা যেতে পারে যার কোনও IF NOT EXISTSবাক্য গঠন নেই - উদাহরণস্বরূপ ALTER TABLE ... ADD CONSTRAINT
টমসজ গেন্ডার

389

সঙ্গে Postgres 9.6 এই অপশনটি ব্যবহার করা যেতে পারেif not exists

ALTER TABLE table_name ADD COLUMN IF NOT EXISTS column_name INTEGER;

4
মিষ্টি। দুর্ভাগ্যক্রমে, ADD CONSTRAINT IF NOT EXISTSএখনও কিছুই নেই।
টমাসজ গেন্ডার

4
এই উত্তরটি পৃষ্ঠার নীচে কেন, এটি অন্যান্য বিকল্পগুলির চেয়ে অনেক ভাল।
Etersters

কৌতূহলের বাইরে: এই কি টেবিলের অ্যাক্সেস লক সৃষ্টি করবে (এবং এইভাবে প্রোডাকশন ডাটাবেসে বিশাল টেবিলগুলিতে চালনার সময় একটি রক্ষণাবেক্ষণ উইন্ডোর প্রয়োজন হবে)?
হাসান বৈগ

4
স্ট্যাক-ওভারফ্লো সত্যই গ্রহণযোগ্য উত্তর পরিবর্তন সমর্থন করা উচিত।
হেনরিক সোমারল্যান্ড

@HenrikSommerland: যে হয় মঞ্জুরিপ্রাপ্ত - কিন্তু একমাত্র ব্যক্তি যিনি প্রশ্ন জিজ্ঞাসা করে।
a_horse_with_no_name

22
CREATE OR REPLACE function f_add_col(_tbl regclass, _col  text, _type regtype)
  RETURNS bool AS
$func$
BEGIN
   IF EXISTS (SELECT 1 FROM pg_attribute
              WHERE  attrelid = _tbl
              AND    attname = _col
              AND    NOT attisdropped) THEN
      RETURN FALSE;
   ELSE
      EXECUTE format('ALTER TABLE %s ADD COLUMN %I %s', _tbl, _col, _type);
      RETURN TRUE;
   END IF;
END
$func$  LANGUAGE plpgsql;

কল করুন:

SELECT f_add_col('public.kat', 'pfad1', 'int');

রিটার্নস TRUEসাফল্যের অন্য FALSE(কলাম ইতিমধ্যেই বিদ্যমান)।
অবৈধ সারণী বা নাম প্রকারের জন্য একটি ব্যতিক্রম উত্থাপন করে।

কেন অন্য সংস্করণ?

  • এটি একটি DOবিবৃতি দিয়ে করা যেতে পারে , তবে DOবিবৃতিগুলি কিছুই ফেরত দিতে পারে না। এবং যদি এটি বারবার ব্যবহারের জন্য হয় তবে আমি একটি ফাংশন তৈরি করব।

  • আমি অবজেক্ট আইডেন্টিফায়ার প্রকারগুলি ব্যবহার করি regclassএবং এর regtypeজন্য _tblএবং _typeক) এসকিউএল ইনজেকশন প্রতিরোধ করে এবং খ) অবিলম্বে উভয়ের বৈধতা পরীক্ষা করে (সম্ভাব্যতম উপায়)। কলামের নামের _colএখনো জন্য sanitized করা হয়েছে EXECUTEসঙ্গে quote_ident()। এই সম্পর্কিত উত্তরের আরও ব্যাখ্যা:

  • format()Postgres 9.1+ প্রয়োজন। পুরানো সংস্করণগুলির জন্য ম্যানুয়ালি কনটেনেট করুন:

    EXECUTE 'ALTER TABLE ' || _tbl || ' ADD COLUMN ' || quote_ident(_col) || ' ' || _type;
  • আপনি আপনার টেবিলের নাম স্কিমা-যোগ্যতা অর্জন করতে পারেন তবে আপনার দরকার নেই।
    আপনি উট-কেস এবং সংরক্ষিত শব্দগুলি সংরক্ষণ করার জন্য ফাংশন কলের শনাক্তকারীদের ডাবল-কোট করতে পারেন (তবে আপনার কোনওভাবেই এটি ব্যবহার করা উচিত নয়)।

  • আমি pg_catalogপরিবর্তে জিজ্ঞাসা information_schema। বিস্তারিত ব্যাখ্যা:

  • বর্তমানে গৃহীত উত্তরেরEXCEPTION মতো একটি ধারা রয়েছে এমন ব্লকগুলি যথেষ্ট ধীর। এটি সাধারণত সহজ এবং দ্রুত হয়। ডকুমেন্টেশন:

টিপ: একটি EXCEPTIONক্লজ সম্বলিত একটি ব্লক প্রবেশ ছাড়তে এবং প্রস্থান ছাড়াই উল্লেখযোগ্যভাবে বেশি ব্যয়বহুল একটি ছাড়াই। অতএব, EXCEPTIONপ্রয়োজন ছাড়া ব্যবহার করবেন না ।


আমি আমার চেয়ে ভাল আপনার সমাধান পছন্দ! এটি আরও ভাল, নিরাপদ এবং দ্রুত।
ডেভিড এস

পোস্টগ্র্রেসের যে সংস্করণটি নিয়ে আমার কাজ করতে হবে তার DOবিবৃতিটি নেই, গ্রহণ করার জন্য সামান্য পরিবর্তন DEFAULTএবং এটি পুরোপুরি কার্যকর হয়েছে!
পুনর্নির্মাণ

18

ফাংশন true/falseব্যবহার করে নিম্নলিখিত নির্বাচন করা প্রশ্নের সাথে ফিরে আসবে EXISTS()

বিদ্যমান () :
উপস্থিতি যুক্তি একটি স্বেচ্ছাসেবী নির্বাচন বিবৃতি, বা subquery হয়। এটি কোনও সারি ফেরত দেয় কিনা তা নির্ধারণের জন্য সাবকিউরিটি মূল্যায়ন করা হয়। যদি এটি কমপক্ষে একটি সারি ফেরত দেয় তবে উপস্থিতিগুলির ফলাফল "সত্য"; যদি সাবকিউরি কোনও সারি দেয় না, তবে উপস্থিতিগুলির ফলাফল "মিথ্যা"

SELECT EXISTS(SELECT  column_name 
                FROM  information_schema.columns 
               WHERE  table_schema = 'public' 
                 AND  table_name = 'x' 
                 AND  column_name = 'y'); 

এবং আপনার টেবিলটি পরিবর্তন করতে নিম্নলিখিত গতিশীল এসকিউএল বিবৃতি ব্যবহার করুন

DO
$$
BEGIN
IF NOT EXISTS (SELECT column_name 
                 FROM  information_schema.columns 
                WHERE  table_schema = 'public' 
                  AND  table_name = 'x' 
                  AND  column_name = 'y') THEN
ALTER TABLE x ADD COLUMN y int DEFAULT NULL;
ELSE
RAISE NOTICE 'Already exists';
END IF;
END
$$

2
সদৃশ সারণীর নাম এবং কলামের নাম একাধিক স্কিমে থাকতে পারে।
মাইক শেরিল 'ক্যাট রিকল'

1
ঠিক আছে, আপনি আপনার কোডটি স্কিমার জন্য অ্যাকাউন্টে পুনর্লিখন করতে চাইতে পারেন।
মাইক শেরিল 'ক্যাট রিক্যাল'

2

যারা পোস্টগ্রে 9.5+ ব্যবহার করেন (আমি আপনার বেশিরভাগের বিশ্বাস করি) তাদের পক্ষে একটি সহজ এবং পরিষ্কার সমাধান রয়েছে

ALTER TABLE if exists <tablename> add if not exists <columnname> <columntype>

1

নীচের ফাংশনটি যথাযথ বার্তা ফেরত উপস্থিত থাকলে কলামটি চেক করবে অন্যথায় এটি কলামটি টেবিলটিতে যুক্ত করবে।

create or replace function addcol(schemaname varchar, tablename varchar, colname varchar, coltype varchar)
returns varchar 
language 'plpgsql'
as 
$$
declare 
    col_name varchar ;
begin 
      execute 'select column_name from information_schema.columns  where  table_schema = ' ||
      quote_literal(schemaname)||' and table_name='|| quote_literal(tablename) || '   and    column_name= '|| quote_literal(colname)    
      into   col_name ;   

      raise info  ' the val : % ', col_name;
      if(col_name is null ) then 
          col_name := colname;
          execute 'alter table ' ||schemaname|| '.'|| tablename || ' add column '|| colname || '  ' || coltype; 
      else
           col_name := colname ||' Already exist';
      end if;
return col_name;
end;
$$

আমাকে খুব যুক্তিসঙ্গত উত্তর হিসাবে আঘাত করেছে, বিশেষ করে ডিও পোস্টগ্রাজের সাম্প্রতিক সংযোজন হিসাবে
জন পাওয়েল

1

এটি মূলত সোলা থেকে সমাধান, তবে কিছুটা পরিষ্কার করা হয়েছে। এটি যথেষ্ট আলাদা যে আমি তার সমাধানটি কেবল "উন্নত" করতে চাইনি (প্লাস, আমি এটিকে অসভ্য বলে মনে করি)।

মূল পার্থক্য হ'ল এটি এক্সেকিউট ফর্ম্যাটটি ব্যবহার করে। যা আমি কিছুটা পরিষ্কার বলে মনে করি তবে আমি বিশ্বাস করি এর অর্থ আপনার অবশ্যই পোস্টগ্র্যাস এসকিউএল ৯.১ বা আরও নতুন হওয়া উচিত।

এটি 9.1 এ পরীক্ষা করা হয়েছে এবং কাজ করে। দ্রষ্টব্য: স্কিমা / টেবিল_নাম / বা ডেটা টাইপ অবৈধ থাকলে এটি ত্রুটি বাড়িয়ে তুলবে। এটি "স্থির" হতে পারে তবে অনেক ক্ষেত্রে সঠিক আচরণ হতে পারে।

CREATE OR REPLACE FUNCTION add_column(schema_name TEXT, table_name TEXT, 
column_name TEXT, data_type TEXT)
RETURNS BOOLEAN
AS
$BODY$
DECLARE
  _tmp text;
BEGIN

  EXECUTE format('SELECT COLUMN_NAME FROM information_schema.columns WHERE 
    table_schema=%L
    AND table_name=%L
    AND column_name=%L', schema_name, table_name, column_name)
  INTO _tmp;

  IF _tmp IS NOT NULL THEN
    RAISE NOTICE 'Column % already exists in %.%', column_name, schema_name, table_name;
    RETURN FALSE;
  END IF;

  EXECUTE format('ALTER TABLE %I.%I ADD COLUMN %I %s;', schema_name, table_name, column_name, data_type);

  RAISE NOTICE 'Column % added to %.%', column_name, schema_name, table_name;

  RETURN TRUE;
END;
$BODY$
LANGUAGE 'plpgsql';

ব্যবহার:

select add_column('public', 'foo', 'bar', 'varchar(30)');

0

মাইগ্রেশন স্ক্রিপ্টগুলিতে যুক্ত করা যেতে পারে ফাংশন ডাকে এবং হয়ে গেলে ড্রপ হয়।

create or replace function patch_column() returns void as
$$
begin
    if exists (
        select * from information_schema.columns
            where table_name='my_table'
            and column_name='missing_col'
     )
    then
        raise notice 'missing_col already exists';
    else
        alter table my_table
            add column missing_col varchar;
    end if;
end;
$$ language plpgsql;

select patch_column();

drop function if exists patch_column();

0

আমার ক্ষেত্রে এটি কীভাবে তৈরি করা হয়েছিল তার জন্য আমাদের মাইগ্রেশন স্ক্রিপ্টগুলির জন্য বিভিন্ন স্কিমার কাটা কাটা কিছুটা কঠিন।

এটির কাজ করার জন্য আমরা একটি ব্যতিক্রম ব্যবহার করেছি যা কেবল ত্রুটিটিকে ধরা এবং উপেক্ষা করেছে। এটি দেখতে খুব সহজ হওয়ার দুর্দান্ত পার্শ্ব প্রতিক্রিয়াও ছিল।

তবে সাবধান থাকুন যে অন্যান্য সমাধানগুলির নিজস্ব সুবিধা রয়েছে যা সম্ভবত এই সমাধানটি ছাড়িয়ে যায়:

DO $$
BEGIN
  BEGIN
    ALTER TABLE IF EXISTS bobby_tables RENAME COLUMN "dckx" TO "xkcd";
  EXCEPTION
    WHEN undefined_column THEN RAISE NOTICE 'Column was already renamed';
  END;
END $$;

-1

আপনি অনুসরণ করে এটি করতে পারেন।

ALTER TABLE tableName drop column if exists columnName; 
ALTER TABLE tableName ADD COLUMN columnName character varying(8);

সুতরাং এটি কলামটি ইতিমধ্যে বিদ্যমান থাকলে ড্রপ করবে। এবং তারপরে নির্দিষ্ট সারণীতে কলামটি যুক্ত করুন।


17
কীভাবে তথ্য হারাবে?
আলিয়াক্সেই রামানাউ

48
আপনি সর্বদা আপনার ক্লায়েন্টদের কাছে ক্ষমা চাইতে পারেন
konzo

আমি সবেমাত্র কলামটি যুক্ত করেছি, তাই এটি আমার পক্ষে খুব সুবিধাজনক ছিল।
নুমেনন

-4

কেবল জিজ্ঞাসাটি একটি কলাম_নাম ফিরে এসেছে কিনা তা পরীক্ষা করে দেখুন।

যদি তা না হয় তবে এই জাতীয় কিছু কার্যকর করুন:

ALTER TABLE x ADD COLUMN y int;

যেখানে আপনি 'x' এবং 'y' এর জন্য দরকারী কিছু রেখেছেন এবং অবশ্যই একটি উপযুক্ত ডেটাটাইপ যেখানে আমি ইনট ব্যবহার করেছি।


আপনি কোন পরিবেশে আছেন? আপনার প্রস্তাবটিতে কোন স্ক্রিপ্টিং ভাষা আছে? অথবা আপনি PL / pgSQL ব্যবহার করছেন? আপনি কি পিএইচপি / জাভা / ইত্যাদি মত কিছু ভাষা থেকে সম্পাদন করছেন?
এরউইন মোলার

কোনও স্ক্রিপ্টিং ভাষা নেই। আমাকে কেবল এসকিউএল এর মধ্যে এটি করা দরকার । আমার জাভা অ্যাপ্লিকেশন রয়েছে যা ইনপুটটিতে এসকিউএল স্ক্রিপ্ট পায় এবং নির্বাচিত ডিবিতে সেই স্ক্রিপ্টটি চালায়।
মারিওশ

2
তারপরে আমি আপনাকে pl / pgsql: postgresql.org/docs/9.1/static/plpgsql.html সন্ধান করার পরামর্শ দিচ্ছি যাতে কলাম_নাম এবং টেবিলের নাম আর্গুমেন্ট হিসাবে নেওয়া হয়।
এরউইন মোলার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.