MySQL, SQL이있는 테이블에 열이 있는지 확인하십시오.


130

MySQL의 특정 테이블에 특정 열이 있는지 확인하고 그렇지 않은 경우 확인하는 쿼리를 작성하려고합니다. 그렇지 않으면 아무것도하지 마십시오. 이것은 모든 엔터프라이즈 급 데이터베이스에서 실제로 쉬운 절차이지만 MySQL은 예외 인 것 같습니다.

나는 같은 것을 생각했다

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
           WHERE TABLE_NAME='prefix_topic' AND column_name='topic_last_update') 
BEGIN 
ALTER TABLE `prefix_topic` ADD `topic_last_update` DATETIME NOT NULL;
UPDATE `prefix_topic` SET `topic_last_update` = `topic_date_add`;
END;

작동하지만 잘못 실패합니다. 방법이 있습니까?



왜 만들지 않습니까? 존재하면 작성에 실패하지만 신경 쓰지 않아도됩니다.
Brian Hooper

생성은 트랜잭션 내부에서 이루어지고 실패는 슬프지만 사실 인 전체 트랜잭션을 종료합니다.
Clops

@haim - headups에 대한 thans하지만 링크에서 제안 쿼리 :( 만 절차 내에서 작동이
clops

2
DDL 문은 현재 트랜잭션에서 암시 적 커밋을 유발합니다. dev.mysql.com/doc/refman/5.0/en/implicit-commit.html
Mchl

답변:


259

이것은 나를 위해 잘 작동합니다.

SHOW COLUMNS FROM `table` LIKE 'fieldname';

PHP를 사용하면 다음과 같습니다.

$result = mysql_query("SHOW COLUMNS FROM `table` LIKE 'fieldname'");
$exists = (mysql_num_rows($result))?TRUE:FALSE;

8
문제는 php + sql 또는 java + sql을 사용하여 수행하는 방법이 아니라 순수한 sql / mysql을 사용하여 수행하는 방법입니다. 따라서 downvote
Yuriy Nakonechnyy

61
질문에 대답 + 일부 정보는 저와 다른 사람들에게 도움이되었을 것입니다, +1
Francisco Presencia

@Mfoo 감사합니다 Mfoo, 당신은 내 하루를 구했습니다! 매력처럼 작동합니다. 이 작업에 대한 절차를 만드는 것 외에 최고의 솔루션 중 하나입니다.
webblover

8
Yura : 순수한 SQL / MySQL 응답은 "SHOW COLUMNS FROM table LIKE 'fieldname'"을 사용하는 첫 번째 부분입니다. PHP 코드를 무시해도 괜찮습니다. PHP를 사용하는 경우 결과를 검색하고 해석하는 한 가지 방법 일뿐입니다.
orrd

1
@codenamezero MSSQL 사용을 언급한다고 가정합니다.이 질문은 MySQL에 관한 것입니다. MSSQL에 대한 이 게시물 을 참조하십시오
Mfoo

158

juli

SQL 예제에 감사드립니다. 쿼리를 시도했는데 제대로 작동하려면 약간의 변경이 필요하다고 생각합니다.

SELECT * 
FROM information_schema.COLUMNS 
WHERE 
    TABLE_SCHEMA = 'db_name' 
AND TABLE_NAME = 'table_name' 
AND COLUMN_NAME = 'column_name'

그것은 나를 위해 일했다.

감사!


제한된 연구 결과에 따르면 모든 호스팅 환경에 information_schema DB가있는 것은 아닙니다. 내가 사용한 모든 cpanel 환경에 있습니다. 이 제공된 솔루션은 기존 DB에 따라 다릅니다.
cardi777

2
이 답변은 MySQL에 특정한 SHOW COLUMNS와 달리 ANSI 표준 방법을 사용하여 테이블 정보를 가져 오기 때문에 "SHOW COLUMNS"를 사용하는 것보다 낫습니다. 따라서이 솔루션은 다른 데이터베이스와 함께 작동합니다. "information_schema"를 사용하면 이상하게 들릴 수 있으며 표준 SQL 방식이 아니라고 생각할 것입니다.
orrd

5
이 답변은 열의 존재에 대한 정보 만 제공합니다. 일부 DDL 문을 조건부로 실행하려면 다음과 같은 문을 허용하는 프로 시저로 전체 를 래핑해야합니다. 프로 시저를 래핑하는 방법에 대한 예제는 stackoverflow.com/questions/7384711/…IF참조하십시오. 열에 대한 테스트 및 조건부 DML 문
Christopher Schultz

: @Iain stackoverflow.com/questions/32962149/... 나는 당신의 대답에 대해 참조 한
아마르 싱

이는 SQL 삽입의 위험을 줄이는 매개 변수화 된 쿼리에 사용할 수 있으므로 아래의 "SHOW COLUMNS"접근 방식보다 좋습니다. DATABASE () 함수를 사용하여 TABLE_SCHEMA 열을 채울 수 있다는 것을 추가하고 싶었습니다.
Andrew

16

@Mchl이 묘사 한 구체적인 예를 찾고있는 사람을 돕기 위해 다음과 같은 것을 시도하십시오.

SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'my_schema' AND TABLE_NAME = 'my_table' AND COLUMN_NAME = 'my_column'

false를 반환하면 (결과 없음) 열이 존재하지 않는 것입니다.


2
나는 그것이 있어야한다고 생각 TABLE_NAME = 'my_table'TABLE_SCHEMA가 테이블에 스키마입니다, 즉.SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'my_schema' AND TABLE_NAME = 'my_table' AND COLUMN_NAME = 'my_column'
AaronHolland

10

information_schema 데이터베이스없이 일반 PHP를 사용하는 또 다른 방법은 다음과 같습니다.

$chkcol = mysql_query("SELECT * FROM `my_table_name` LIMIT 1");
$mycol = mysql_fetch_array($chkcol);
if(!isset($mycol['my_new_column']))
  mysql_query("ALTER TABLE `my_table_name` ADD `my_new_column` BOOL NOT NULL DEFAULT '0'");

information_schema를 사용하지 않으려는 이유는 무엇입니까? 이 목적을 위해서만 존재합니다. (또한이 스레드는 상당히 오래되어 이미 응답되었습니다.)
Leigh

1
내 테스트에서 information_schema를 사용하는 것보다 약 10-50 배 빠릅니다. 테이블에 행이 하나 이상 있어야하므로 항상 보장 할 수는 없습니다.
Martijn

isset()배열 키가 있지만 값이 NULL 인 경우 'false'를 던집니다 . 다음 array_key_exists()과 같이 사용하는 것이 좋습니다if( !array_key_exists( 'my_new_column', $mycol ) )
Paul Geisler

1
이 답변은 간단한 isset()확인을 간과했기 때문에 얼굴이 답답해졌습니다 . 질문을 해결하지는 못하지만 select 쿼리를 이미 실행하고 결과를 메모리에 저장해야하는 것이 좋습니다.
사이펀

10

위의 @lain 주석에서 시작 하여이 저장 프로 시저를 던졌습니다. 몇 번 이상 호출 해야하는 경우 (그리고 PHP가 필요하지 않음) 좋습니다.

delimiter //
-- ------------------------------------------------------------
-- Use the inforamtion_schema to tell if a field exists.
-- Optional param dbName, defaults to current database
-- ------------------------------------------------------------
CREATE PROCEDURE fieldExists (
OUT _exists BOOLEAN,      -- return value
IN tableName CHAR(255),   -- name of table to look for
IN columnName CHAR(255),  -- name of column to look for
IN dbName CHAR(255)       -- optional specific db
) BEGIN
-- try to lookup db if none provided
SET @_dbName := IF(dbName IS NULL, database(), dbName);

IF CHAR_LENGTH(@_dbName) = 0
THEN -- no specific or current db to check against
  SELECT FALSE INTO _exists;
ELSE -- we have a db to work with
  SELECT IF(count(*) > 0, TRUE, FALSE) INTO _exists
  FROM information_schema.COLUMNS c
  WHERE 
  c.TABLE_SCHEMA    = @_dbName
  AND c.TABLE_NAME  = tableName
  AND c.COLUMN_NAME = columnName;
END IF;
END //
delimiter ;

협력 fieldExists

mysql> call fieldExists(@_exists, 'jos_vm_product', 'child_option', NULL) //
Query OK, 0 rows affected (0.01 sec)

mysql> select @_exists //
+----------+
| @_exists |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

mysql> call fieldExists(@_exists, 'jos_vm_product', 'child_options', 'etrophies') //
Query OK, 0 rows affected (0.01 sec)

mysql> select @_exists //
+----------+
| @_exists |
+----------+
|        1 |
+----------+

@quickshiftin 장관, 정말 감사합니다. 이 테이블 인 경우 나를 확인하는 데 도움이 만료 할 에 의해, 확인 경우 ExpirationDate필드. 😊
Jeancarlo Fontalvo

@JeancarloFontalvo 나의 기쁨! 또한 mysql-inspectors 프로젝트를 확인 하여 더 높은 수준의 메소드로 스키마를 검사하기 시작했습니다.
quickshiftin

1
세상에 그것은 도서관과 같습니다. 공유해 주셔서 감사합니다 미스터!
Jeancarlo Fontalvo

8

정보 스키마에서 column_name 만 선택하고이 쿼리 결과를 변수에 넣습니다. 그런 다음 변수를 테스트하여 테이블을 변경해야하는지 여부를 결정하십시오.

추신 COLUMNS 테이블에 대해 TABLE_SCHEMA를 지정하지 마십시오.


1
나는 MySQL에 익숙하지 않다. 여기에 작은 예제를 게시 할 수 있습니까?
박수

2

이 간단한 스크립트를 사용하고 있습니다 :

mysql_query("select $column from $table") or mysql_query("alter table $table add $column varchar (20)");

데이터베이스에 이미 연결되어 있으면 작동합니다.


이것은 또한 테이블에 데이터 행이있는 경우에만 작동합니다. 그러나 테이블이 비어 있으면 작동하지 않습니다.
orrd

1
완벽하지 않고, 오래된 드라이버를 사용하고, 테이블이 비어 있으면 작동하지 않으며, 입력이 이스케이프되지 않지만 한 줄로 수행 한 방법이 마음에 듭니다. +1
나는 곰을 한 번 씨름했다.

1

테이블에 존재하지 않는 경우 열을 동적으로 추가하기위한 정말 좋은 스크립트를 넣은 Mfoo에게 감사드립니다. 나는 PHP로 그의 대답을 향상시켰다 . 이 스크립트는 또한 실제로 '테이블 추가' mysql comand 가 필요한 테이블 수를 찾는 데 도움이됩니다 . 레시피를 맛보십시오. 매력처럼 작동합니다.

<?php
ini_set('max_execution_time', 0);

$host = 'localhost';
$username = 'root';
$password = '';
$database = 'books';

$con = mysqli_connect($host, $username, $password);
if(!$con) { echo "Cannot connect to the database ";die();}
mysqli_select_db($con, $database);
$result=mysqli_query($con, 'show tables');
$tableArray = array();
while($tables = mysqli_fetch_row($result)) 
{
     $tableArray[] = $tables[0];    
}

$already = 0;
$new = 0;
for($rs = 0; $rs < count($tableArray); $rs++)
{
    $exists = FALSE;

    $result = mysqli_query($con, "SHOW COLUMNS FROM ".$tableArray[$rs]." LIKE 'tags'");
    $exists = (mysqli_num_rows($result))?TRUE:FALSE;

    if($exists == FALSE)
    {
        mysqli_query($con, "ALTER TABLE ".$tableArray[$rs]." ADD COLUMN tags VARCHAR(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL");
        ++$new;
        echo '#'.$new.' Table DONE!<br/>';
    }
    else
    {
        ++$already;
        echo '#'.$already.' Field defined alrady!<br/>';    
    }
    echo '<br/>';
}
?>

1

이것은 샘플 PDO에서 저에게 효과적입니다.

public function GetTableColumn() {      
$query  = $this->db->prepare("SHOW COLUMNS FROM `what_table` LIKE 'what_column'");  
try{            
    $query->execute();                                          
    if($query->fetchColumn()) { return 1; }else{ return 0; }
    }catch(PDOException $e){die($e->getMessage());}     
}

0

ALTER TABLE / MODIFY COLS 또는 기타 다른 테이블 모드 조작을 TRANSACTION 내에 두지 마십시오. 트랜잭션은 ALTERations가 아닌 QUERY 실패를 롤백 할 수 있기 때문에 트랜잭션에서 매번 오류가 발생합니다.

테이블에서 SELECT * 쿼리를 실행하고 열이 있는지 확인하십시오 ...


ALTERMySQL에서 (그리고 DDL과 같은) 실제로 트랜잭션을 암시 적으로 커밋합니다. 그러나 SELECT *를 사용하면 열의 존재를 확인하기 위해 네트워크에서 큰 오버 헤드가 생성됩니다. 대신 시도해보십시오 SELECT my_col_to_check FROM t LIMIT 0: mysql이 오류를 생성하면 열이 존재하지 않을 것입니다 (여전히 네트워크 문제 또는 기타 문제 일 수 있으므로 오류를 확인하십시오). 오류가 발생하지 않으면 열이 존재합니다. 열 존재 여부를 확인하는 가장 좋은 방법인지 확실하지 않습니다.
Xenos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.