বিদ্যমান ENUM প্রকারে একটি নতুন মান যুক্ত করা হচ্ছে


208

আমার কাছে একটি টেবিল কলাম রয়েছে যা একটি enumপ্রকার ব্যবহার করে । enumঅতিরিক্ত সম্ভাব্য মান পেতে আমি এই ধরণের আপডেট করতে চাই । আমি কোনও বিদ্যমান মান মুছতে চাই না, কেবল নতুন মান যুক্ত করুন। এটি করার সহজ উপায় কী?

উত্তর:


153

আপনি পোস্টগ্রিএসকিউএল ৯.১ বা তার পরে ব্যবহার করছেন এবং আপনি যদি কোনও লেনদেনের বাইরে পরিবর্তন করতে ঠিক থাকেন তবে দ্রষ্টব্য , সরল পদ্ধতির জন্য এই উত্তরটি দেখুন ।


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

আপনি যদি পরিবর্তন করতে চান এমন এনাম টাইপ ব্যবহার করে তবে কেবল একটি বা দুটি কলাম রয়েছে, আপনি এটি চেষ্টা করতে পারেন। এছাড়াও আপনি নতুন ধরণের মানগুলির ক্রম পরিবর্তন করতে পারেন।

-- 1. rename the enum type you want to change
alter type some_enum_type rename to _some_enum_type;
-- 2. create new type
create type some_enum_type as enum ('old', 'values', 'and', 'new', 'ones');
-- 3. rename column(s) which uses our enum type
alter table some_table rename column some_column to _some_column;
-- 4. add new column of new type
alter table some_table add some_column some_enum_type not null default 'new';
-- 5. copy values to the new column
update some_table set some_column = _some_column::text::some_enum_type;
-- 6. remove old column and type
alter table some_table drop column _some_column;
drop type _some_enum_type;

1 টির বেশি কলাম থাকলে 3-6 পুনরাবৃত্তি করা উচিত।


9
এটি উল্লেখ করার মতো যে এগুলি সবই একটি একক লেনদেনে করা যায়, তাই এটি প্রোডাকশন ডাটাবেসে এটি করা বেশিরভাগ ক্ষেত্রে নিরাপদ।
ডেভিড লেপপিক

52
এটি কখনই ভাল ধারণা ছিল না। 9.1 থেকে আপনি এটি দিয়ে সব করতে পারেন ALTER TYPE। তবে এর আগেও ALTER TABLE foo ALTER COLUMN bar TYPE new_type USING bar::text::new_type;ছিল অনেক উন্নত।
এরউইন ব্র্যান্ডসটেটার

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

13
আপনি 3, 4, 5 এবং 6 পদক্ষেপগুলি একসাথে একক বিবৃতিতে ভেঙে ফেলতে পারেন:ALTER TABLE some_table ALTER COLUMN some_column TYPE some_enum_type USING some_column::text::some_enum_type;
glyphobet

3
যদি কোনও লাইভ টেবিলটিতে এটি করা থাকে, প্রক্রিয়া চলাকালীন টেবিলটি লক করুন। পোস্টগ্রাএসকিএল-তে ডিফল্ট লেনদেনের বিচ্ছিন্নতা স্তর এই লেনদেনের সময় অন্যান্য লেনদেনের মাধ্যমে নতুন সারিগুলি beingোকানো আটকাবে না, তাই আপনাকে ভুলভাবে জনবহুল সারি রেখে দেওয়া যেতে পারে।
সেরজিও কারভালহো

421

পোস্টগ্রি 9.1 প্রবর্তন করার ক্ষমতা ALTER Enum প্রকারসমূহ:

ALTER TYPE enum_type ADD VALUE 'new_value'; -- appends to list
ALTER TYPE enum_type ADD VALUE 'new_value' BEFORE 'old_value';
ALTER TYPE enum_type ADD VALUE 'new_value' AFTER 'old_value';

1
"এনাম_ টাইপ" কী? মাঠের নাম, টেবিল_ফিল্ডের নাম? অথবা অন্য কিছু? আমি কিভাবে এটি আঘাত করা উচিত? আমার টেবিল "গ্রেড" আছে এবং আমার কাছে কলাম "টাইপ" আছে এবং ডিবি ডাম্পে আমি এটি পেয়েছি: গ্রেড গ্রেড_ টাইপ_চেক করুন চেক ((টাইপ) :: পাঠ্য = কোনও ((আরআরএ ['পরীক্ষা' :: চরিত্রের ভিন্নতা, 'পরীক্ষা': : চরিত্রের ভিন্নতা, 'অতিরিক্ত' :: চরিত্রের ভিন্নতা, 'মধ্যম' :: চরিত্রটি পৃথক, 'চূড়ান্ত' :: চরিত্রটি পৃথক]] :: পাঠ্য [])))

1
enum_type আপনার নিজের এনাম টাইপের নাম @marotanenbaum। যদি আপনি আপনার এনামটি "টাইপ" হন তবে আপনার এটি ব্যবহার করা উচিত।
দরিউজ

26
এটি একটি অপসারণ করা সম্ভব?
সিড

8
@ ড্রউনোকেসের মন্তব্যে যোগ করা, আপনি যদি ডিবি-মাইগ্রেট ব্যবহার করেন (যা লেনদেনের ক্ষেত্রে চলে) তবে আপনি একটি ত্রুটি পেতে পারেন: ত্রুটি: বিকল্প টাইপ ... এডিডি কোনও লেনদেনের ব্লকের ভিতরে চলতে পারে না সমাধানটি এখানে উল্লেখ করা হয়েছে (হুবিটাস দ্বারা) ): স্ট্যাকওভারফ্লো.com
মহেশ

1
আপনি এটি অপসারণ করতে পারবেন না তাই এটি ডাউ মাইগ্রেশনকে অসম্ভব করে তোলে তাই অন্য পদ্ধতি অবলম্বন করতে হবে
মুহাম্মদ উমর

65

একটি সম্ভাব্য সমাধান নিম্নলিখিত; পূর্বশর্তটি হ'ল ব্যবহৃত এনুম মানগুলিতে দ্বন্দ্ব নেই। (উদাহরণস্বরূপ, এনাম মান অপসারণ করার সময়, নিশ্চিত হয়ে নিন যে এই মানটি আর ব্যবহার হয় না))

-- rename the old enum
alter type my_enum rename to my_enum__;
-- create the new enum
create type my_enum as enum ('value1', 'value2', 'value3');

-- alter all you enum columns
alter table my_table
  alter column my_column type my_enum using my_column::text::my_enum;

-- drop the old enum
drop type my_enum__;

এছাড়াও এইভাবে কলাম ক্রম পরিবর্তন করা হবে না।


1
+1 এটি পূর্ব -9.1-এ যাওয়ার উপায় এবং এখনও উপাদানগুলি মুছতে বা সংশোধন করার উপায়।

এটি আমার সমাধানের জন্য এখন পর্যন্ত সেরা উত্তর, যা বিদ্যমান এনাম প্রকারে নতুন এনাম যুক্ত করে, যেখানে আমরা সমস্ত পুরানো এনামগুলিকে রাখছি এবং নতুন যুক্ত করছি। অতিরিক্ত হিসাবে আমাদের আপডেট স্ক্রিপ্ট লেনদেন হয়। দুর্দান্ত পোস্ট!
ডারিন পিটারসন

1
জমকালো উত্তর! চারপাশে থাকা হ্যাকগুলি এড়ায় pg_enumযা আসলে জিনিসগুলি ভেঙে দিতে পারে এবং লেনদেনের বিপরীতে ALTER TYPE ... ADD
নাথানএলডেনএসআর

4
ক্ষেত্রে আপনার কলামটি একটি ডিফল্ট মান আপনি নিম্নলিখিত ত্রুটির পাবেন রয়েছে: default for column "my_column" cannot be cast automatically to type "my_enum"। আপনাকে নিম্নলিখিতগুলি করতে হবে: ALTER TABLE "my_table" ALTER COLUMN "my_column" DROP DEFAULT, ALTER COLUMN "my_column" TYPE "my_type" USING ("my_column"::text::"my_type"), ALTER COLUMN "my_column" SET DEFAULT 'my_default_value';
n1ru4l

30

আপনি যদি enumলেনদেনের ক্ষেত্রে মূল্য যুক্ত করতে চান এমন পরিস্থিতিতে পড়েন, তবে ALTER TYPEবিবৃতিতে ফ্লাইওয়ে মাইগ্রেশনে এটি কার্যকর করুন আপনি ত্রুটি পেয়ে যাবেন ERROR: ALTER TYPE ... ADD cannot run inside a transaction block( ফ্লাইওয়ে ইস্যু দেখুন # 350 ) আপনি এই জাতীয় মানগুলি pg_enumসরাসরি ওয়ার্কআরউন্ড ( type_egais_unitsটার্গেটের নাম enum) হিসাবে যুক্ত করতে পারেন :

INSERT INTO pg_enum (enumtypid, enumlabel, enumsortorder)
    SELECT 'type_egais_units'::regtype::oid, 'NEW_ENUM_VALUE', ( SELECT MAX(enumsortorder) + 1 FROM pg_enum WHERE enumtypid = 'type_egais_units'::regtype )

9
তবে এটির জন্য প্রশাসকের অনুমতি প্রদানের প্রয়োজন হবে, কারণ এটি সিস্টেম সারণী পরিবর্তন করে।
অ্যাসেলজিন

22

@ দারিউজ 1 এর পরিপূরক

4.2.1 রেলগুলির জন্য, এই নথির বিভাগটি রয়েছে:

== লেনদেনের স্থানান্তর

ডাটাবেস অ্যাডাপ্টার যদি ডিডিএল লেনদেনকে সমর্থন করে তবে সমস্ত মাইগ্রেশন স্বয়ংক্রিয়ভাবে কোনও লেনদেনের মধ্যে আবৃত হবে। এমন কোনও কোয়েরি রয়েছে যা আপনি কোনও লেনদেনের মধ্যেই কার্যকর করতে পারবেন না এবং এই পরিস্থিতিতে আপনি স্বয়ংক্রিয় লেনদেন বন্ধ করতে পারেন।

class ChangeEnum < ActiveRecord::Migration
  disable_ddl_transaction!

  def up
    execute "ALTER TYPE model_size ADD VALUE 'new_value'"
  end
end

3
এই! আপনি যদি আধুনিক রেলগুলিতে এনামগুলির সাথে খেলছেন তবে এটি ঠিক আপনি যা খুঁজছেন তা।
এলি আলবার্ট

1
দুর্দান্ত, আমাকে অনেক সাহায্য করেছে!
Dmytro Uhnichenko

10

পোস্টগ্রিস 9.1 ডকুমেন্টেশন থেকে :

ALTER TYPE name ADD VALUE new_enum_value [ { BEFORE | AFTER } existing_enum_value ]

উদাহরণ:

ALTER TYPE user_status ADD VALUE 'PROVISIONAL' AFTER 'NORMAL'

3
ডকুমেন্টেশন থেকেও: এনাম টাইপের মূল সদস্যদের সাথে তুলনামূলক তুলনায় কিছুটা ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ক্ষতি হয়। [.... স্ট্যাকওভারফ্লো মন্তব্যের জন্য বিশদভাবে স্নিপড ... বিস্তারিত মন্দা সাধারণত তুচ্ছ হয় না; তবে এটি যদি গুরুত্বপূর্ণ হয় তবে এনামের ধরণটি ফেলে এবং পুনরায় তৈরি করার মাধ্যমে বা ডেটাবেস ডাম্পিং করে এবং পুনরায় লোড করে অনুকূল কর্মক্ষমতা ফিরে পাওয়া যেতে পারে।
অ্যারন জিনম্যান

8

দাবি অস্বীকার: আমি এই সমাধানটি চেষ্টা করে দেখিনি, সুতরাং এটি কার্যকর নাও হতে পারে ;-)

আপনার দিকে তাকানো উচিত pg_enum। আপনি যদি কেবল বিদ্যমান ENUM এর লেবেলটি পরিবর্তন করতে চান তবে একটি সাধারণ আপডেট it

একটি নতুন ENUM মান যুক্ত করতে:

  • প্রথমে নতুন মানটি .োকান pg_enum। নতুন মানটি যদি সর্বশেষ হতে হয় তবে আপনি শেষ করেছেন।
  • যদি না হয় (আপনার বিদ্যমান বিদ্যমানগুলির মধ্যে একটি নতুন ENUM মান প্রয়োজন), আপনাকে উপরের থেকে নীচে যেতে আপনার টেবিলের প্রতিটি স্বতন্ত্র মান আপডেট করতে হবে ...
  • তারপরে আপনাকে তাদের pg_enumবিপরীত ক্রমে পুনরায় নামকরণ করতে হবে ।

চিত্রণ
আপনার নীচে লেবেলের সেট রয়েছে:

ENUM ('enum1', 'enum2', 'enum3')

এবং আপনি পেতে চান:

ENUM ('enum1', 'enum1b', 'enum2', 'enum3')

তারপর:

INSERT INTO pg_enum (OID, 'newenum3');
UPDATE TABLE SET enumvalue TO 'newenum3' WHERE enumvalue='enum3';
UPDATE TABLE SET enumvalue TO 'enum3' WHERE enumvalue='enum2';

তারপর:

UPDATE TABLE pg_enum SET name='enum1b' WHERE name='enum2' AND enumtypid=OID;

এবং আরও ...



5

আমি কোনও মন্তব্য পোস্ট করার মতো মনে হচ্ছে না, তাই আমি কেবলই বলব যে pg_enum আপডেট করা পোস্টগ্রিস 8.4 এ কাজ করে। আমাদের এনামগুলিকে যেভাবে সেট আপ করা হয়, তার জন্য আমি বিদ্যমান এনাম ধরণের সাথে নতুন মান যুক্ত করেছি:

INSERT INTO pg_enum (enumtypid, enumlabel)
  SELECT typelem, 'NEWENUM' FROM pg_type WHERE
    typname = '_ENUMNAME_WITH_LEADING_UNDERSCORE';

এটি কিছুটা ভীতিজনক, তবে পোস্টগ্র্রেস আসলে কীভাবে তার ডেটা সঞ্চয় করে, তা বোঝা যায়।


1
দুর্দান্ত উত্তর! কেবলমাত্র একটি নতুন এনাম সংযুক্ত করার জন্য সহায়তা করে, তবে আপনাকে যেখানে পুনরায় অর্ডার দিতে হবে তা অবশ্যই সমাধান করবে না doesn't
মাহমুদ আবদেলকাদের


টাইপনেমের শীর্ষস্থানীয় আন্ডারস্কোরের পাশাপাশি এগুলি কেস সংবেদনশীলও। Pg_type টেবিল থেকে টাইপনেম দ্বারা নির্বাচন করার চেষ্টা করে আমার মন প্রায় হারিয়ে গেল।
মহেশ

5

Pg_enum আপডেট করা কাজ করে, মধ্যস্থ কলাম কৌতুকটি উপরে হাইলাইট করে। কলামের ধরণটি সরাসরি পরিবর্তন করতে কেউ যাদু ব্যবহার করতে পারেন:

CREATE TYPE test AS enum('a', 'b');
CREATE TABLE foo (bar test);
INSERT INTO foo VALUES ('a'), ('b');

ALTER TABLE foo ALTER COLUMN bar TYPE varchar;

DROP TYPE test;
CREATE TYPE test as enum('a', 'b', 'c');

ALTER TABLE foo ALTER COLUMN bar TYPE test
USING CASE
WHEN bar = ANY (enum_range(null::test)::varchar[])
THEN bar::test
WHEN bar = ANY ('{convert, these, values}'::varchar[])
THEN 'c'::test
ELSE NULL
END;

যতক্ষণ না আপনার কোনও ক্রিয়াকলাপের স্পষ্টভাবে প্রয়োজন হয় বা সেই এনামকে ফেরত দেয় আপনি ভাল good (pgsql আপনি টাইপটি রেখে দিলে অভিযোগ করবে।)

এছাড়াও, দ্রষ্টব্য যে PG9.1 একটি ALL TYPE বিবৃতি পেশ করছে, যা এনামগুলিতে কাজ করবে:

http://developer.postgresql.org/pgdocs/postgres/release-9-1-alpha.html


পোস্টগ্রেএসকিউএল 9.1 এর জন্য প্রাসঙ্গিক ডকুমেন্টেশন এখন postgresql.org/docs/9.1/static/sql-altertype.html
উইচার্ট আক্কারম্যান

1
ALTER TABLE foo ALTER COLUMN bar TYPE test USING bar::text::new_type;তবে এখন মূলত অপ্রাসঙ্গিক ...
এরউইন ব্র্যান্ডসেটেটার

একইভাবে ইরভিন যা বলেছিলেন, ... USING bar::typeআমার পক্ষে কাজ করেছেন। এমনকি আমি নির্দিষ্ট করতে হবে না ::text
ড্যানিয়েল ওয়ার্নার

3

সরলতম: এনামগুলি থেকে মুক্তি পান। এগুলি সহজেই সংশোধনযোগ্য নয় এবং এভাবে খুব কমই ব্যবহার করা উচিত ।


2
একটি সাধারণ চেক বাধা সম্ভবত করতে হবে?

1
এবং স্ট্রিং হিসাবে মান সংরক্ষণ করার সমস্যাটি ঠিক কী?

5
@ গ্রেজার: 9.1-এ আপনি এনামগুলিতে মান যোগ করতে পারেন ( depesz.com/index.php/2010/10/27/… ) - তবে আপনি এখনও পুরানোগুলি সরাতে পারবেন না।

3
@ উইলশেপার্ড - আমি মনে করি যে এটি মূলত কখনই নয়। আমি মনে করি যে চেক সীমাবদ্ধতার সাথে পাঠ্যের উপর ভিত্তি করে কাস্টম প্রকারগুলি যে কোনও ক্ষেত্রে আরও বেশি ভাল।

3
@ জ্যাকডুগ্লাস - নিশ্চিত আমি যে কোনও দিন এনাম চেক করে ডোমেন নেব।

3

উপযুক্ত জায়গায় একটি মন্তব্য যোগ করতে পারেন না, কিন্তু ALTER TABLE foo ALTER COLUMN bar TYPE new_enum_type USING bar::text::new_enum_typeকলামে একটি ডিফল্ট ব্যর্থ। আমি বাধ্য ছিলাম:

ALTER table ALTER COLUMN bar DROP DEFAULT;

এবং তারপর এটি কাজ করে।


2

সেক্ষেত্রে, আপনি যদি রেলগুলি ব্যবহার করছেন এবং আপনার বেশ কয়েকটি বিবৃতি রয়েছে তবে আপনার একের পর এক মৃত্যুর প্রয়োজন হবে যেমন:

execute "ALTER TYPE XXX ADD VALUE IF NOT EXISTS 'YYY';"
execute "ALTER TYPE XXX ADD VALUE IF NOT EXISTS 'ZZZ';"

1

এখানে একটি আরও সাধারণ তবে একটি দ্রুত-কার্যক্ষম সমাধান রয়েছে যা ধরণের পরিবর্তনের পরিবর্তে এটি ব্যবহার করে ডাটাবেসের সমস্ত কলাম আপডেট করে। এমনকি ENUM- র একটি নতুন সংস্করণ একাধিক লেবেল দ্বারা আলাদা বা মূল কিছুটি বাদ দিলেও পদ্ধতিটি প্রয়োগ করা যেতে পারে। নীচের কোডটি এর my_schema.my_type AS ENUM ('a', 'b', 'c')সাথে প্রতিস্থাপন করে ENUM ('a', 'b', 'd', 'e'):

CREATE OR REPLACE FUNCTION tmp() RETURNS BOOLEAN AS
$BODY$

DECLARE
    item RECORD;

BEGIN

    -- 1. create new type in replacement to my_type
    CREATE TYPE my_schema.my_type_NEW
        AS ENUM ('a', 'b', 'd', 'e');

    -- 2. select all columns in the db that have type my_type
    FOR item IN
        SELECT table_schema, table_name, column_name, udt_schema, udt_name
            FROM information_schema.columns
            WHERE
                udt_schema   = 'my_schema'
            AND udt_name     = 'my_type'
    LOOP
        -- 3. Change the type of every column using my_type to my_type_NEW
        EXECUTE
            ' ALTER TABLE ' || item.table_schema || '.' || item.table_name
         || ' ALTER COLUMN ' || item.column_name
         || ' TYPE my_schema.my_type_NEW'
         || ' USING ' || item.column_name || '::text::my_schema.my_type_NEW;';
    END LOOP;

    -- 4. Delete an old version of the type
    DROP TYPE my_schema.my_type;

    -- 5. Remove _NEW suffix from the new type
    ALTER TYPE my_schema.my_type_NEW
        RENAME TO my_type;

    RETURN true;

END
$BODY$
LANGUAGE 'plpgsql';

SELECT * FROM tmp();
DROP FUNCTION tmp();

পুরো প্রক্রিয়াটি মোটামুটি দ্রুত চলবে, কারণ যদি লেবেলের ক্রমটি অব্যাহত থাকে তবে তথ্যের কোনও প্রকৃত পরিবর্তন ঘটবে না। আমি 5 টি টেবিল ব্যবহার করে my_typeপ্রতিটিটিতে 50,000-70,000 সারি ব্যবহার করে পদ্ধতিটি প্রয়োগ করেছি এবং পুরো প্রক্রিয়াটি কেবল 10 সেকেন্ডে নিয়েছিল।

অবশ্যই, ENUM- র নতুন সংস্করণে অনুপস্থিত লেবেলগুলি ডেটাতে কোথাও ব্যবহার করা থাকলে ফাংশনটি একটি ব্যতিক্রম প্রত্যাবর্তন করবে তবে এ জাতীয় পরিস্থিতিতে যেকোনোভাবে আগেই করা উচিত।


এটি সত্যই মূল্যবান। সমস্যাটি যদিও পুরানো ENUM ব্যবহার করে দেখা হয়েছে। এগুলি বাদ দিতে হবে এবং পুনরায় তৈরি করতে হবে, যা বাদ পড়ে যাওয়াগুলির উপর নির্ভর করে অন্যান্য মতামত বিবেচনা করে আরও জটিল। যৌগিক প্রকারের বিষয়ে কথা বলছি না ...
ওন্ডেজ বৌদা

1

যারা কোনও লেনদেনের সমাধান খুঁজছেন তাদের জন্য নিম্নলিখিতটি কাজ করছে বলে মনে হচ্ছে।

এর পরিবর্তে ENUM, একটি DOMAINটাইপ TEXTকরে একটি সীমাবদ্ধতার সাথে ব্যবহার করা হবে যাচাই করে দেখা হচ্ছে যে মানটি অনুমোদিত মানগুলির নির্দিষ্ট তালিকার মধ্যে রয়েছে (কিছু মন্তব্য দ্বারা প্রস্তাবিত)। একমাত্র সমস্যাটি হ'ল কোনও ডোমেইনে কোনও বাধা যুক্ত করা যায় না (এবং এভাবে কোনও সংশোধনও করা যায় না) যদি এটি কোনও যৌগিক ধরণের দ্বারা ব্যবহৃত হয় (ডক্স কেবল এই "অবশেষে উন্নত করা উচিত" বলে থাকে)। এই জাতীয় বিধিনিষেধের আশেপাশে কাজ করা যেতে পারে, তবে, কোনও ফাংশন ডাকার সীমাবদ্ধতা ব্যবহার করে, নীচে as

START TRANSACTION;

CREATE FUNCTION test_is_allowed_label(lbl TEXT) RETURNS BOOL AS $function$
    SELECT lbl IN ('one', 'two', 'three');
$function$ LANGUAGE SQL IMMUTABLE;

CREATE DOMAIN test_domain AS TEXT CONSTRAINT val_check CHECK (test_is_allowed_label(value));

CREATE TYPE test_composite AS (num INT, word test_domain);

CREATE TABLE test_table (val test_composite);
INSERT INTO test_table (val) VALUES ((1, 'one')::test_composite), ((3, 'three')::test_composite);
-- INSERT INTO test_table (val) VALUES ((4, 'four')::test_composite); -- restricted by the CHECK constraint

CREATE VIEW test_view AS SELECT * FROM test_table; -- just to show that the views using the type work as expected

CREATE OR REPLACE FUNCTION test_is_allowed_label(lbl TEXT) RETURNS BOOL AS $function$
    SELECT lbl IN ('one', 'two', 'three', 'four');
$function$ LANGUAGE SQL IMMUTABLE;

INSERT INTO test_table (val) VALUES ((4, 'four')::test_composite); -- allowed by the new effective definition of the constraint

SELECT * FROM test_view;

CREATE OR REPLACE FUNCTION test_is_allowed_label(lbl TEXT) RETURNS BOOL AS $function$
    SELECT lbl IN ('one', 'two', 'three');
$function$ LANGUAGE SQL IMMUTABLE;

-- INSERT INTO test_table (val) VALUES ((4, 'four')::test_composite); -- restricted by the CHECK constraint, again

SELECT * FROM test_view; -- note the view lists the restricted value 'four' as no checks are made on existing data

DROP VIEW test_view;
DROP TABLE test_table;
DROP TYPE test_composite;
DROP DOMAIN test_domain;
DROP FUNCTION test_is_allowed_label(TEXT);

COMMIT;

পূর্বে, আমি গৃহীত উত্তরের অনুরূপ একটি সমাধান ব্যবহার করেছি, তবে একবারে দেখা বা ফাংশন বা সংমিশ্রিত ধরণের (এবং বিশেষত পরিবর্তিত ENUMs ব্যবহার করে অন্যান্য মতামত ব্যবহার করে দেখা হচ্ছে ...) বিবেচনা করা গেলে এটি ভাল হওয়া অনেক দূরে। এই উত্তরে প্রস্তাবিত সমাধানটি কোনও শর্তে কাজ করছে বলে মনে হচ্ছে।

একমাত্র অসুবিধা হ'ল কিছু অনুমোদিত মানগুলি সরানো হলে (যা বিশেষত এই প্রশ্নের জন্য গ্রহণযোগ্য হতে পারে) যখন বিদ্যমান ডেটাগুলিতে কোনও চেক করা হয় না। ( ALTER DOMAIN test_domain VALIDATE CONSTRAINT val_checkদুর্ভাগ্যক্রমে, যৌগিক ধরণের দ্বারা ব্যবহৃত ডোমেনে নতুন বাধা যুক্ত করার মতো একই ত্রুটি দিয়ে শেষের কল ))

মনে রাখবেন যে সামান্য পরিবর্তন যেমন CHECK (value = ANY(get_allowed_values())), যেখানে get_allowed_values()ফাংশন অনুমোদিত মানগুলির তালিকা ফিরিয়ে দেয়, কাজ করবে না - যা বেশ বিস্ময়কর, তাই আমি আশা করি উপরে প্রস্তাবিত সমাধান নির্ভরযোগ্যভাবে কাজ করে (এটি আমার পক্ষে এখনও অবধি ...)। (এটি কাজ করে, আসলে - এটি আমার ত্রুটি ছিল)


0

উপরে আলোচিত হিসাবে, ALTERকমান্ড কোনও লেনদেনের ভিতরে লেখা যায় না। প্রস্তাবিত উপায়টি হল pg_enum টেবিলটিতে সরাসরি, দ্বারা retrieving the typelem from pg_type tableএবং and োকানো calculating the next enumsortorder number;

নিম্নলিখিতটি আমি ব্যবহার করি এমন কোড। (সন্নিবেশ করার আগে সদৃশ মান বিদ্যমান কিনা তা পরীক্ষা করে (এনামাইটপিড এবং এনামেলাবেলের নামের মধ্যে সীমাবদ্ধতা)

INSERT INTO pg_enum (enumtypid, enumlabel, enumsortorder)
    SELECT typelem,
    'NEW_ENUM_VALUE',
    (SELECT MAX(enumsortorder) + 1 
        FROM pg_enum e
        JOIN pg_type p
        ON p.typelem = e.enumtypid
        WHERE p.typname = '_mytypename'
    )
    FROM pg_type p
    WHERE p.typname = '_mytypename'
    AND NOT EXISTS (
        SELECT * FROM 
        pg_enum e
        JOIN pg_type p
        ON p.typelem = e.enumtypid
        WHERE e.enumlabel = 'NEW_ENUM_VALUE'
        AND p.typname = '_mytypename'
    )

মনে রাখবেন যে আপনার টাইপের নামটি পিজি_ টাইপ সারণীতে একটি আন্ডারস্কোর দিয়ে প্রম্পেন্ড করা হয়েছে। এছাড়াও, টাইপনামটি যেখানে ক্লজটিতে সমস্ত ছোট হাতের অক্ষর থাকা দরকার।

এখন এটি আপনার ডিবি মাইগ্রেশন স্ক্রিপ্টে নিরাপদে লেখা যেতে পারে।


-1

আমি জানি না অন্য বিকল্প আছে কিনা তবে আমরা ব্যবহার করে মানটি ফেলে দিতে পারি:

select oid from pg_type where typname = 'fase';'
select * from pg_enum where enumtypid = 24773;'
select * from pg_enum where enumtypid = 24773 and enumsortorder = 6;
delete from pg_enum where enumtypid = 24773 and enumsortorder = 6;

-2

নাভিচ্যাট ব্যবহার করার সময় আপনি টাইপগুলিতে যেতে পারেন (দর্শন অধীনে -> অন্যান্য -> প্রকারের জন্য) - ধরণের নকশার দর্শন পেতে পারেন - এবং "লেবেল যুক্ত করুন" বোতামটি ক্লিক করতে পারেন।


1
সুন্দর হলেও বাস্তব জীবনে এটি কার্যকর নয়:ERROR: cannot drop type foo because other objects depend on it HINT: Use DROP ... CASCADE to drop the dependent objects too.
অর্টউইন জেন্টজ

অদ্ভুত, এটি আমার পক্ষে কাজ করেছিল। (টিএস যখন
এনাম

1
আমি বিশেষ করে একটি ডিআআরপি করিনি তবে আপনার পদ্ধতির পরে ঠিক চলে গেলাম। আমি ধরে নিলাম নাভিচ্যাট দৃশ্যের পিছনে DROP করে এবং ব্যর্থ হয়। আমি নাভিচ্যাট 9.1.5 লাইট ব্যবহার করছি।
অর্টউইন জেন্টজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.