استخدام ALTER لإسقاط عمود إذا كان موجودًا في MySQL

StackOverflow https://stackoverflow.com/questions/173814

  •  05-07-2019
  •  | 
  •  

سؤال

كيف يمكن استخدام ALTER لإسقاط عمود في جدول MySQL إذا كان هذا العمود موجودًا؟

أعلم أنه يمكنني استخدامها ALTER TABLE my_table DROP COLUMN my_column, ، ولكن هذا سوف يلقي خطأ إذا my_column غير موجود.هل هناك بناء جملة بديل لإسقاط العمود بشكل مشروط؟

أنا أستخدم MySQL الإصدار 4.0.18.

هل كانت مفيدة؟

المحلول

بالنسبة لـ MySQL، لا يوجد شيء: طلب ميزة MySQL.

يمكن القول إن السماح بذلك هو فكرة سيئة حقًا، على أي حال: IF EXISTS يشير إلى أنك تقوم بتشغيل عمليات مدمرة على قاعدة بيانات ذات بنية غير معروفة (لك).قد تكون هناك مواقف يكون فيها ذلك مقبولاً للعمل المحلي السريع والقذر، ولكن إذا كنت تميل إلى تشغيل مثل هذا البيان مقابل بيانات الإنتاج (في الترحيل وما إلى ذلك)، فأنت تلعب بالنار.

ولكن إذا أصررت، فليس من الصعب التحقق من وجوده أولاً في العميل، أو اكتشاف الخطأ.

يدعم MariaDB أيضًا ما يلي بدءًا من الإصدار 10.0.2:

قم بإسقاط [العمود] [إذا كان موجودًا] col_name

أنا.ه.

ALTER TABLE my_table DROP إذا كان موجودًا my_column؛

ولكن يمكن القول إنها فكرة سيئة الاعتماد على ميزة غير قياسية يدعمها واحد فقط من عدة تشعبات في MySQL.

نصائح أخرى

لا يوجد أي دعم مستوى لغة هذا في الخلية. هنا هو عمل حول إشراك الخلية information_schema البيانات الفوقية في 5.0+، لكنها لن تعالج المشكلة في 4.0.18.

drop procedure if exists schema_change;

delimiter ';;'
create procedure schema_change() begin

    /* delete columns if they exist */
    if exists (select * from information_schema.columns where table_schema = schema() and table_name = 'table1' and column_name = 'column1') then
        alter table table1 drop column `column1`;
    end if;
    if exists (select * from information_schema.columns where table_schema = schema() and table_name = 'table1' and column_name = 'column2') then
        alter table table1 drop column `column2`;
    end if;

    /* add columns */
    alter table table1 add column `column1` varchar(255) NULL;
    alter table table1 add column `column2` varchar(255) NULL;

end;;

delimiter ';'
call schema_change();

drop procedure if exists schema_change;

وكتبت بعض المعلومات أكثر تفصيلا في href="http://bitkickers.blogspot.com/2010/01/mysql-drop-column-if-exists.html" بلوق وظيفة .

وأنا أعلم أن هذا هو موضوع قديم، ولكن هناك وسيلة بسيطة للتعامل مع هذا المطلب دون استخدام الإجراءات المخزنة. هذا قد يساعد شخص ما.

set @exist_Check := (
    select count(*) from information_schema.columns 
    where TABLE_NAME='YOUR_TABLE' 
    and COLUMN_NAME='YOUR_COLUMN' 
    and TABLE_SCHEMA=database()
) ;
set @sqlstmt := if(@exist_Check>0,'alter table YOUR_TABLE drop column YOUR_COLUMN', 'select ''''') ;
prepare stmt from @sqlstmt ;
execute stmt ;

وآمل أن يساعد هذا شخص ما، كما فعلت لي (بعد الكثير من التجربة والخطأ).

ولقد بنيت إجراء قابلة لإعادة الاستخدام التي يمكن أن تساعد جعل DROP COLUMN idempotent:

-- column_exists:

DROP FUNCTION IF EXISTS column_exists;

DELIMITER $$
CREATE FUNCTION column_exists(
  tname VARCHAR(64),
  cname VARCHAR(64)
)
  RETURNS BOOLEAN
  READS SQL DATA
  BEGIN
    RETURN 0 < (SELECT COUNT(*)
                FROM `INFORMATION_SCHEMA`.`COLUMNS`
                WHERE `TABLE_SCHEMA` = SCHEMA()
                      AND `TABLE_NAME` = tname
                      AND `COLUMN_NAME` = cname);
  END $$
DELIMITER ;

-- drop_column_if_exists:

DROP PROCEDURE IF EXISTS drop_column_if_exists;

DELIMITER $$
CREATE PROCEDURE drop_column_if_exists(
  tname VARCHAR(64),
  cname VARCHAR(64)
)
  BEGIN
    IF column_exists(tname, cname)
    THEN
      SET @drop_column_if_exists = CONCAT('ALTER TABLE `', tname, '` DROP COLUMN `', cname, '`');
      PREPARE drop_query FROM @drop_column_if_exists;
      EXECUTE drop_query;
    END IF;
  END $$
DELIMITER ;

والاستعمال:

CALL drop_column_if_exists('my_table', 'my_column');

مثال:

SELECT column_exists('my_table', 'my_column');       -- 1
CALL drop_column_if_exists('my_table', 'my_column'); -- success
SELECT column_exists('my_table', 'my_column');       -- 0
CALL drop_column_if_exists('my_table', 'my_column'); -- success
SELECT column_exists('my_table', 'my_column');       -- 0
و

وتشيس سيبرت أعمال الجواب، ولكن أود أن أضيف أن إذا كان لديك العديد من المخطط الذي تريد تغيير SELECT على النحو التالي:

select * from information_schema.columns where table_schema in (select schema()) and table_name=...

أدرك أن هذا الموضوع قديم جدًا الآن، لكني كنت أواجه نفس المشكلة.كان هذا هو الحل الأساسي الذي أستخدمه في MySQL Workbench، ولكنه كان يعمل بشكل جيد...

  1. احصل على محرر SQL جديد وقم بتنفيذ SHOW TABLES للحصول على قائمة بالجداول الخاصة بك
  2. حدد كافة الصفوف، واختر نسخ إلى الحافظة (غير مقتبسة) من قائمة السياق
  3. الصق قائمة الأسماء في علامة تبويب محرر أخرى
  4. اكتب استفسارك، على سبيل المثال ALTER TABLE x يسقط a;
  5. قم ببعض النسخ واللصق، بحيث ينتهي بك الأمر إلى استعلام منفصل لكل جدول
  6. تبديل ما إذا كان يجب أن يتوقف طاولة العمل عند حدوث خطأ
  7. اضغط على "تنفيذ" وابحث في سجل الإخراج

أي جداول لديها الجدول الآن ليس لها أي جداول لم تكن قد أظهرت خطأ في السجلات

ثم يمكنك العثور على/استبدال "drop aقم بتغييره إلى "إضافة عمود". b INT NULL' إلخ وقم بتشغيل الأمر برمته مرة أخرى ....

قديم بعض الشيء، ولكن في النهاية تحصل على النتيجة النهائية ويمكنك التحكم/مراقبة العملية برمتها وتذكر حفظ نصوص SQL الخاصة بك في حالة احتياجك إليها مرة أخرى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top