[mysql] ALTER를 사용하여 MySQL에있는 경우 열 삭제

해당 열이있는 경우 ALTER를 사용하여 MySQL 테이블의 열을 삭제하는 방법은 무엇입니까?

나는 사용할 수 있다는 것을 알고 ALTER TABLE my_table DROP COLUMN my_column있지만 my_column존재하지 않으면 오류가 발생 합니다. 조건부로 열을 삭제하는 대체 구문이 있습니까?

MySQL 버전 4.0.18을 사용하고 있습니다.



답변

MySQL의 경우 MySQL 기능 요청 이 없습니다 .

어쨌든 이것을 허용하는 것은 정말 나쁜 생각입니다. IF EXISTS알 수없는 구조를 가진 데이터베이스에서 파괴적인 작업을 실행하고 있음을 나타냅니다. 빠르고 더러운 로컬 작업에 이것이 허용되는 상황이있을 수 있지만 프로덕션 데이터 (이전 등)에 대해 그러한 명령문을 실행하려는 유혹이 있다면 불장난입니다.

그러나 주장한다면 클라이언트에서 먼저 존재를 확인하거나 오류를 포착하는 것은 어렵지 않습니다.

MariaDB는 10.0.2부터 다음을 지원합니다.

DROP [COLUMN] [IF EXISTS] col_name

ALTER TABLE my_table DROP IF EXISTS my_column;

그러나 MySQL의 여러 포크 중 하나만 지원하는 비표준 기능에 의존하는 것은 틀림없이 나쁜 생각입니다.


답변

MySQL에서는 이에 대한 언어 수준 지원이 없습니다. 다음은 5.0+의 MySQL information_schema 메타 데이터와 관련된 해결 방법이지만 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;

나는 블로그 포스트 에 좀 더 자세한 정보를 썼다 .


답변

이것이 오래된 스레드라는 것을 알고 있지만 저장 프로 시저를 사용하지 않고이 요구 사항을 처리하는 간단한 방법이 있습니다. 이것은 누군가를 도울 수 있습니다.

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멱 등성을 만드는 데 도움이되는 재사용 가능한 절차를 만들었습니다 .

-- 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


답변

Chase Seibert의 대답은 작동하지만 여러 스키마가 있으면 SELECT를 변경하려는 경우 다음과 같이 추가합니다.

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


답변

이 문제를 해결하는 가장 간단한 방법은 다음과 같습니다.

  • CREATE new_table AS SELECT id, col1, col2, … (최종 테이블에서 실제로 원하는 열만) FROM my_table;

  • my_table을 old_table로, new_table을 my_table로 이름을 변경합니다.

  • DROP old_table;

또는 필요한 경우 롤백을 위해 old_table을 유지하십시오.

이것은 작동하지만 외래 키는 이동되지 않습니다. 나중에 my_table에 다시 추가해야합니다. my_table을 참조하는 다른 테이블의 외래 키도 수정해야합니다 (새 my_table을 가리킴).

행운을 빕니다…


답변

이 스크립트를 사용하고 열, 스키마 및 테이블 이름을 사용할 수 있습니다.

 IF EXISTS (SELECT *
                         FROM INFORMATION_SCHEMA.COLUMNS
                         WHERE TABLE_NAME = 'TableName' AND COLUMN_NAME = 'ColumnName'
                                             AND TABLE_SCHEMA = SchemaName)
    BEGIN
       ALTER TABLE TableName DROP COLUMN ColumnName;
    END;