উত্তর:
"ডিও" বিবৃতিটি ব্যবহার করে এখানে একটি স্বল্প-মিষ্টি সংস্করণ দেওয়া হয়েছে:
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;
$$
আপনি এগুলি প্যারামিটার হিসাবে পাস করতে পারবেন না, আপনাকে ক্লায়েন্টের পক্ষের স্ট্রিংয়ে পরিবর্তনশীল প্রতিস্থাপনের প্রয়োজন হবে, তবে এটি একটি স্ব-অন্তর্ভুক্ত ক্যোয়ারী যা কেবলমাত্র একটি বার্তা প্রকাশ করে যদি কলামটি ইতিমধ্যে উপস্থিত থাকে, যোগ না করে এবং অন্যান্য ত্রুটি (যেমন একটি অবৈধ ডেটা টাইপ) এ ব্যর্থ হতে থাকবে।
আমি যদি এই বাহ্যিক উত্স থেকে আসা এলোমেলো স্ট্রিংগুলি থাকে তবে এই পদ্ধতির কোনওটি করার পরামর্শ দিচ্ছি না। আপনি কোন পদ্ধতি ব্যবহার করেন না কেন (ক্লিন্ট সাইড বা সার্ভার-সাইড ডায়নামিক স্ট্রিংগুলি ক্যোয়ারী হিসাবে কার্যকর করা হয়), এটি বিপর্যয়ের একটি রেসিপি হবে কারণ এটি আপনাকে এসকিউএল ইঞ্জেকশন আক্রমণে খোলে।
DO $$
ব্যর্থতা দিয়ে শুরু করবে । আমি DO $$;
যা চেষ্টা করেছি তা খুব ব্যর্থ হয়েছে, যতক্ষণ না আমি ব্লকটি শুরু করেছি যতক্ষণ DO $$DECLARE r record;
না দেব পোস্টগ্র্রেস ডক্সে একটি উদাহরণে দেওয়া হয়েছে ।
END; $$
একটি সিনট্যাক্স ত্রুটি (পোস্টগ্রিস 9.3), এর END $$;
পরিবর্তে আমাকে ব্যবহার করতে হয়েছিল
EXCEPTION
) কিছুটা সাধারণ, এবং এমন কোনও কাজের জন্য নিযুক্ত করা যেতে পারে যার কোনও IF NOT EXISTS
বাক্য গঠন নেই - উদাহরণস্বরূপ ALTER TABLE ... ADD CONSTRAINT
।
সঙ্গে Postgres 9.6 এই অপশনটি ব্যবহার করা যেতে পারেif not exists
ALTER TABLE table_name ADD COLUMN IF NOT EXISTS column_name INTEGER;
ADD CONSTRAINT IF NOT EXISTS
এখনও কিছুই নেই।
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
এবং এটি পুরোপুরি কার্যকর হয়েছে!
ফাংশন 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
$$
নীচের ফাংশনটি যথাযথ বার্তা ফেরত উপস্থিত থাকলে কলামটি চেক করবে অন্যথায় এটি কলামটি টেবিলটিতে যুক্ত করবে।
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;
$$
এটি মূলত সোলা থেকে সমাধান, তবে কিছুটা পরিষ্কার করা হয়েছে। এটি যথেষ্ট আলাদা যে আমি তার সমাধানটি কেবল "উন্নত" করতে চাইনি (প্লাস, আমি এটিকে অসভ্য বলে মনে করি)।
মূল পার্থক্য হ'ল এটি এক্সেকিউট ফর্ম্যাটটি ব্যবহার করে। যা আমি কিছুটা পরিষ্কার বলে মনে করি তবে আমি বিশ্বাস করি এর অর্থ আপনার অবশ্যই পোস্টগ্র্যাস এসকিউএল ৯.১ বা আরও নতুন হওয়া উচিত।
এটি 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)');
মাইগ্রেশন স্ক্রিপ্টগুলিতে যুক্ত করা যেতে পারে ফাংশন ডাকে এবং হয়ে গেলে ড্রপ হয়।
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();
আমার ক্ষেত্রে এটি কীভাবে তৈরি করা হয়েছিল তার জন্য আমাদের মাইগ্রেশন স্ক্রিপ্টগুলির জন্য বিভিন্ন স্কিমার কাটা কাটা কিছুটা কঠিন।
এটির কাজ করার জন্য আমরা একটি ব্যতিক্রম ব্যবহার করেছি যা কেবল ত্রুটিটিকে ধরা এবং উপেক্ষা করেছে। এটি দেখতে খুব সহজ হওয়ার দুর্দান্ত পার্শ্ব প্রতিক্রিয়াও ছিল।
তবে সাবধান থাকুন যে অন্যান্য সমাধানগুলির নিজস্ব সুবিধা রয়েছে যা সম্ভবত এই সমাধানটি ছাড়িয়ে যায়:
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 $$;
আপনি অনুসরণ করে এটি করতে পারেন।
ALTER TABLE tableName drop column if exists columnName;
ALTER TABLE tableName ADD COLUMN columnName character varying(8);
সুতরাং এটি কলামটি ইতিমধ্যে বিদ্যমান থাকলে ড্রপ করবে। এবং তারপরে নির্দিষ্ট সারণীতে কলামটি যুক্ত করুন।
কেবল জিজ্ঞাসাটি একটি কলাম_নাম ফিরে এসেছে কিনা তা পরীক্ষা করে দেখুন।
যদি তা না হয় তবে এই জাতীয় কিছু কার্যকর করুন:
ALTER TABLE x ADD COLUMN y int;
যেখানে আপনি 'x' এবং 'y' এর জন্য দরকারী কিছু রেখেছেন এবং অবশ্যই একটি উপযুক্ত ডেটাটাইপ যেখানে আমি ইনট ব্যবহার করেছি।
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
;) আপনার উত্তরের জন্য ধন্যবাদ,