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


93

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

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

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


6
이 질문은 Meta 에서 언급되었습니다 .
그냥 학생

답변:


72

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

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

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

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

DROP [COLUMN] [IF EXISTS] col_name 

ALTER TABLE my_table DROP IF EXISTS my_column;

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


8
순수한 SQL로 수행하는 방법이 있습니까?

16
와. 2005 년-9 년 전 언급 됨. 나는이 같은데요 ... 우선 순위 목록을 아래로입니다
crmpicco

4
MariaDB는이를 지원합니다. 10.0.2
Dfr

20
"이것을 허용하는 것은 틀림없이 정말 나쁜 생각입니다."— 동의하지 않습니다. somone이 사용자 사용 사례에 대해 가정해야하는 이유는 무엇입니까? 많은 데이터베이스가 있으며 동기화해야합니다. 정말 ... 소프트웨어가 인간보다 똑똑되고 싶어 할 때 annoyoing 것
Onkeltem

5
14 년이 지났지 만 아직 거기에 있지 않습니다. 나는 이것이 결코 끝날 것이라고 생각하지 않습니다.
Steve Horvath

45

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;

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


3
DrHyde의 공헌을 코멘트로 요약하는 것이 중요하다고 생각했습니다. 왜냐하면 그것이 자신의 답변에있을 때는 분명하지 않기 때문입니다. 다른 데이터베이스를 수정하지 않았는지 확인하십시오. SELECT * from information_schema.columns WHERE table_name = "country"AND column_name = "updated_at"AND table_schema = DATABASE () \ G
Homer6

"schema_change가있는 경우 프로 시저 삭제"에서 경고를받지 않으려면 "set sql_notes = 0;"추가 첫 번째 줄 앞에 "set sql_notes = 1;"을 추가합니다. 마지막 줄 이후. 세부 -> stackoverflow.com/questions/27616564/suppress-mysql-warnings
csonuryilmaz

"구분자"는 ''없이 있어야합니다 (예 :-> 구분자 ;;)
Illidan

17

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

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 ;

이것이 나처럼 (많은 시행 착오 후에) 누군가에게 도움이되기를 바랍니다.


확실히했다. 감사 @Pradeep
수밋 Deshmukh

14

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

5

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

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

1

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

  • 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을 가리킴).

행운을 빕니다...



-3

이 스레드가 지금 꽤 오래되었다는 것을 알고 있지만 동일한 문제가 발생했습니다. 이것은 MySQL Workbench를 사용하는 매우 기본적인 솔루션 이었지만 제대로 작동했습니다.

  1. 새 SQL 편집기를 얻고 SHOW TABLES를 실행하여 테이블 목록을 가져옵니다.
  2. 모든 행을 선택하고 컨텍스트 메뉴에서 클립 보드에 복사 (인용되지 않음)를 선택하십시오.
  3. 이름 목록을 다른 편집기 탭에 붙여 넣습니다.
  4. 쿼리를 작성하십시오. 즉, ALTER TABLE xDROP a;
  5. 일부 복사 및 붙여 넣기를 수행하면 각 테이블에 대해 별도의 쿼리가 생성됩니다.
  6. 오류 발생시 워크 벤치 중지 여부 전환
  7. 실행을 누르고 출력 로그를 살펴보십시오.

테이블이있는 테이블에는 이제 로그에 오류가 표시되지 않은 테이블이 없습니다.

그런 다음 'drop a'을 'ADD COLUMN bINT NULL'등으로 변경하고 전체를 다시 실행할 수 있습니다 ....

약간 투박하지만 마침내 최종 결과를 얻고 전체 프로세스를 제어 / 모니터링 할 수 있으며 다시 필요할 경우 SQL 스크립트를 저장하는 것을 잊지 마십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.