문제

나는 하나를 제외하고 특정 MySQL 테이블에서 모든 열을 가져오기 위해 select 문을 사용하려고 합니다.이를 수행하는 간단한 방법이 있습니까?

편집하다:이 테이블에는 53개의 열이 있습니다(내 디자인 아님).

도움이 되었습니까?

해결책

실제로 방법이 있습니다. 이 작업을 수행하려면 물론 권한이 필요합니다.

SET @sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), '<columns_to_omit>,', '') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '<table>' AND TABLE_SCHEMA = '<database>'), ' FROM <table>');

PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

교체 <table>, <database> and <columns_to_omit>

다른 팁

mysql 정의(수동)에는 그런 것이 없습니다.하지만 정말 많은 수의 열이 있는 경우 col1, ..., col100, 다음이 유용할 수 있습니다.

mysql> CREATE TEMPORARY TABLE temp_tb SELECT * FROM orig_tb;
mysql> ALTER TABLE temp_tb DROP col_x;
mysql> SELECT * FROM temp_tb;

이 경우 뷰가 더 잘 작동할까요?

CREATE VIEW vwTable
as  
SELECT  
    col1  
    , col2  
    , col3  
    , col..  
    , col53  
FROM table

넌 할 수있어:

SELECT column1, column2, column4 FROM table WHERE whatever

아마도 당신은 좀 더 일반적인 해결책을 찾고 있었을 것입니다.

필드 값을 제외하려는 경우(예:보안 문제/민감한 정보의 경우 해당 열을 null로 검색할 수 있습니다.

예를 들어

SELECT *, NULL AS salary FROM users

내가 아는 한, 그렇지 않습니다.다음과 같이 할 수 있습니다:

SELECT col1, col2, col3, col4 FROM tbl

원하는 열을 수동으로 선택하세요.그러나 많은 열을 원할 경우 다음을 수행할 수 있습니다.

SELECT * FROM tbl 

그리고 원하지 않는 것은 무시하세요.

귀하의 특별한 경우에는 다음을 제안합니다.

SELECT * FROM tbl

몇 개의 열만 원하지 않는 한.4개의 열만 원하는 경우 다음을 수행하십시오.

SELECT col3, col6, col45, col 52 FROM tbl

괜찮겠지만 50개의 열을 원한다면 쿼리를 작성하는 코드를 읽기가 (너무?) 어려워질 것입니다.

@Mahomedalid와 @Junaid의 솔루션을 시도하는 동안 문제를 발견했습니다.그래서 공유하려고 생각했습니다.열 이름에 체크인과 같은 공백이나 하이픈이 있으면 쿼리가 실패합니다.간단한 해결 방법은 열 이름 주위에 백틱을 사용하는 것입니다.수정된 쿼리는 다음과 같습니다.

SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(CONCAT("`", COLUMN_NAME, "`")) FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;

선택하고 싶지 않은 컬럼에 데이터가 너무 많아서 속도 문제로 포함하고 싶지 않고 다른 컬럼을 자주 선택하는 경우 새 테이블을 생성하는 것이 좋습니다. 일반적으로 원본 테이블의 키로 선택하지 않는 필드 하나를 사용하여 원본 테이블에서 해당 필드를 제거합니다.추가 필드가 실제로 필요할 때 테이블을 조인합니다.

당신은 사용할 수 있습니다 my_table 설명 그 결과를 사용하여 SELECT 문을 동적으로 생성합니다.

내 주요 문제는 테이블을 조인할 때 얻는 열이 많다는 것입니다.이것이 귀하의 질문에 대한 답변은 아니지만(다음에서 특정 열을 제외한 모든 열을 선택하는 방법) 하나 표), 지정할 수 있다는 점을 언급할 가치가 있다고 생각합니다. table. 단지 지정하는 대신 특정 테이블에서 모든 열을 가져옵니다. .

이것이 어떻게 매우 유용할 수 있는지에 대한 예는 다음과 같습니다.

select users.*, phone.meta_value as phone, zipcode.meta_value as zipcode

from users

left join user_meta as phone
on ( (users.user_id = phone.user_id) AND (phone.meta_key = 'phone') )

left join user_meta as zipcode
on ( (users.user_id = zipcode.user_id) AND (zipcode.meta_key = 'zipcode') )

결과는 사용자 테이블의 모든 열과 메타 테이블에서 조인된 두 개의 추가 열입니다.

나는 의 대답을 좋아했다 @Mahomedalid 이 사실 외에도 @Bill Karwin.에 의해 제기될 수 있는 문제 @Jan Koritak 제가 직면한 것은 사실이지만 그에 대한 트릭을 찾았고 문제에 직면한 모든 사람을 위해 여기에서 공유하고 싶습니다.

다음과 같이 준비된 문의 하위 쿼리에서 REPLACE 함수를 where 절로 바꿀 수 있습니다.

내 테이블 및 열 이름 사용

SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;

따라서 해당 필드만 제외하겠습니다. id 하지만 company_id

이것이 해결책을 찾는 사람에게 도움이 되기를 바랍니다.

문안 인사

모든 열을 쿼리하는 경우에도 쿼리할 열을 지정하는 것이 좋습니다.

따라서 명세서에 각 열의 이름을 기재하는 것이 좋습니다(원하지 않는 열은 제외).

SELECT
    col1
    , col2
    , col3
    , col..
    , col53

FROM table

그냥 해

SELECT * FROM table WHERE whatever

그런 다음 선호하는 프로그래밍 언어로 열을 삭제하세요.PHP

while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) {
   unset($data["id"]);
   foreach ($data as $k => $v) { 
      echo"$v,";
   }      
}

나는 모든 열을 나열하는 "간단한" 솔루션에 동의하지만 이는 부담스러울 수 있으며 오타로 인해 많은 시간이 낭비될 수 있습니다.쿼리에 붙여넣기에 적합한 열 이름을 검색하기 위해 "getTableColumns" 함수를 사용합니다.그렇다면 내가 해야 할 일은 내가 원하지 않는 것을 삭제하는 것뿐입니다.

CREATE FUNCTION `getTableColumns`(tablename varchar(100)) 
          RETURNS varchar(5000) CHARSET latin1
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE res  VARCHAR(5000) DEFAULT "";

  DECLARE col  VARCHAR(200);
  DECLARE cur1 CURSOR FOR 
    select COLUMN_NAME from information_schema.columns 
    where TABLE_NAME=@table AND TABLE_SCHEMA="yourdatabase" ORDER BY ORDINAL_POSITION;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
  OPEN cur1;
  REPEAT
       FETCH cur1 INTO col;
       IF NOT done THEN 
          set res = CONCAT(res,IF(LENGTH(res)>0,",",""),col);
       END IF;
    UNTIL done END REPEAT;
  CLOSE cur1;
  RETURN res;

결과는 쉼표로 구분된 문자열을 반환합니다. 예:

col1,col2,col3,col4,...col53

그것만으로는 충분하지 않다는 점에 동의합니다. Select *, 다른 곳에서 언급했듯이 필요하지 않은 것이 BLOB인 경우 오버헤드가 발생하는 것을 원하지 않습니다.

나는 보다 필요한 데이터를 사용하면 다음을 수행할 수 있습니다. Select * 편안하게 - 데이터베이스 소프트웨어가 이를 지원하는 경우.그렇지 않으면 거대한 데이터를 다른 테이블에 넣으십시오.

처음에는 정규식을 사용할 수 있다고 생각했지만, MYSQL 문서 당신은 할 수없는 것 같습니다.내가 당신이라면 다른 언어(예: PHP)를 사용하여 가져오려는 열 목록을 생성하고 이를 문자열로 저장한 다음 이를 사용하여 SQL을 생성할 것입니다.

나도 이것을 원했기 때문에 대신 함수를 만들었습니다.

public function getColsExcept($table,$remove){
    $res =mysql_query("SHOW COLUMNS FROM $table");

    while($arr = mysql_fetch_assoc($res)){
        $cols[] = $arr['Field'];
    }
    if(is_array($remove)){
        $newCols = array_diff($cols,$remove);
        return "`".implode("`,`",$newCols)."`";
    }else{
        $length = count($cols);
        for($i=0;$i<$length;$i++){
            if($cols[$i] == $remove)
                unset($cols[$i]);
        }
        return "`".implode("`,`",$cols)."`";
    }
}

따라서 작동 방식은 테이블을 입력한 다음 원하지 않는 열을 입력하거나 배열로 입력하는 것입니다.array("id","이름","어떤열이든")

따라서 선택에서는 다음과 같이 사용할 수 있습니다.

mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");

또는

mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");

@Mahomedalid의 답변에 동의하세요.하지만 나는 준비된 진술 같은 것을 하고 싶지 않았고 모든 필드를 입력하고 싶지도 않았습니다.그래서 제가 가진 것은 어리석은 해결책이었습니다.phpmyadmin->sql->select의 테이블로 이동하면 쿼리 복사본 교체가 덤프되고 완료됩니다!:)

저는 Thomas의 답변(+1 ;))에 동의하지만 귀하가 ~하지 않다 원하는 데이터가 거의 포함되어 있지 않습니다.엄청난 양의 텍스트, xml 또는 바이너리 blob이 포함된 경우 각 열을 개별적으로 선택하는 데 시간을 투자하세요.그렇지 않으면 성능이 저하됩니다.건배!

예, 테이블에 따라 I/O가 높을 수 있지만 여기서는 제가 찾은 해결 방법이 있습니다.

Select *
into #temp
from table

alter table #temp drop column column_name

Select *
from #temp

Mahomedalid가 게시한 답변에는 작은 문제가 있습니다.

교체 기능 코드 내부에서 "를 교체했습니다.<columns_to_delete>,"를 ""로 대체할 경우 마지막 필드에 char 쉼표 ","가 없고 문자열에서 제거되지 않기 때문에 교체할 ​​필드가 연결 문자열의 마지막 필드인 경우 이 대체에 문제가 있습니다.

내 제안:

SET @sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME),
                  '<columns_to_delete>', '\'FIELD_REMOVED\'')
           FROM INFORMATION_SCHEMA.COLUMNS
           WHERE TABLE_NAME = '<table>'
             AND TABLE_SCHEMA = '<database>'), ' FROM <table>');

교체 <table>, <database> 그리고`

제거된 열은 "FIELD_REMOVED" 문자열로 대체됩니다. 제 경우에는 메모리를 안전하게 보호하려고 했기 때문에 작동합니다.(제가 제거한 필드는 약 1MB의 BLOB입니다.)

@Mahomedalid 답변을 바탕으로 "mysql에서 일부 열을 제외한 모든 열 선택"을 지원하기 위해 몇 가지 개선 작업을 수행했습니다.

SET @database    = 'database_name';
SET @tablename   = 'table_name';
SET @cols2delete = 'col1,col2,col3';

SET @sql = CONCAT(
'SELECT ', 
(
    SELECT GROUP_CONCAT( IF(FIND_IN_SET(COLUMN_NAME, @cols2delete), NULL, COLUMN_NAME ) )
    FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tablename AND TABLE_SCHEMA = @database
), 
' FROM ',
@tablename);

SELECT @sql;

열이 많으면 이 SQL을 사용하여 group_concat_max_len을 변경하세요.

SET @@group_concat_max_len = 2048;

어쩌면 나에게 해결책이 있을지도 모른다 얀 코리타크 불일치를 지적했다

SELECT CONCAT('SELECT ',
( SELECT GROUP_CONCAT(t.col)
FROM
(
    SELECT CASE
    WHEN COLUMN_NAME = 'eid' THEN NULL
    ELSE COLUMN_NAME
    END AS col 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'
) t
WHERE t.col IS NOT NULL) ,
' FROM employee' );

테이블 :

SELECT table_name,column_name 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'

================================

table_name  column_name
employee    eid
employee    name_eid
employee    sal

================================

쿼리 결과:

'SELECT name_eid,sal FROM employee'

항상 동일한 열인 경우 해당 열이 없는 뷰를 만들 수 있습니다.

그렇지 않으면, 아니요, 저는 그렇게 생각하지 않습니다.

생성된 SQL이 마음에 들고 평가된다면 SQL을 사용하여 SQL을 생성할 수 있습니다.이는 정보 스키마에서 열 이름을 추출하는 일반적인 솔루션입니다.다음은 Unix 명령줄의 예입니다.

대체

  • mysql 명령을 사용한 MYSQL
  • 테이블 이름이 포함된 TABLE
  • 제외된 필드 이름이 있는 EXCLUDEDFIELD
echo $(echo 'select concat("select ", group_concat(column_name) , " from TABLE") from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1) | MYSQL

해당 열을 제외한 열 목록을 구성하려면 실제로 이 방법으로 열 이름을 한 번만 추출한 다음 구성한 쿼리를 사용하면 됩니다.

그래서 다음과 같습니다.

column_list=$(echo 'select group_concat(column_name) from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1)

이제 $column_list 사용자가 구성하는 쿼리의 문자열입니다.

특히 제거할 열 수가 적은 경우 이 문제를 해결하기 위해 또 다른 관점을 추가하고 싶습니다.

다음과 같은 DB 도구를 사용할 수 있습니다. MySQL 워크벤치 select 문을 생성하려면 생성된 문의 해당 열을 수동으로 제거하고 이를 SQL 스크립트에 복사하면 됩니다.

MySQL Workbench에서 생성하는 방법은 다음과 같습니다.

테이블을 마우스 오른쪽 버튼으로 클릭 -> SQL 편집기로 보내기 -> 모든 문 선택.

허용되는 답변에는 몇 가지 단점이 있습니다.

  • 테이블이나 열 이름에 백틱이 필요한 경우 실패합니다.
  • 생략하려는 열이 목록의 마지막에 있으면 실패합니다.
  • 테이블 이름을 두 번(선택용으로 한 번, 쿼리 텍스트용으로 한 번) 나열해야 하는데 이는 중복되고 불필요합니다.
  • 잠재적으로 열 이름을 반환할 수 있습니다. 잘못된 순서

이러한 모든 문제는 단순히 역따옴표를 포함함으로써 극복될 수 있습니다. SEPARATOR 당신을 위해 GROUP_CONCAT 그리고 WHERE 대신에 조건 REPLACE().내 목적(그리고 다른 많은 사람들의 목적)을 위해 테이블 ​​자체에 나타나는 것과 동일한 순서로 열 이름이 반환되기를 원했습니다.이를 달성하기 위해 여기서는 명시적인 방법을 사용합니다. ORDER BY 조항 안의 GROUP_CONCAT() 기능:

SELECT CONCAT(
    'SELECT `',
    GROUP_CONCAT(COLUMN_NAME ORDER BY `ORDINAL_POSITION` SEPARATOR '`,`'),
    '` FROM `',
    `TABLE_SCHEMA`,
    '`.`',
    TABLE_NAME,
    '`;'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE `TABLE_SCHEMA` = 'my_database'
    AND `TABLE_NAME` = 'my_table'
    AND `COLUMN_NAME` != 'column_to_omit';

이에 대한 답변을 내는 데 꽤 늦었습니다. 이것이 제가 항상 해왔던 방식이라고 생각하고 솔직히 최고의 답변보다 100배 더 좋고 깔끔합니다. 누군가가 그것을 볼 수 있기를 바랍니다.그리고 유용하다고 생각하세요

    //create an array, we will call it here. 
    $here = array();
    //create an SQL query in order to get all of the column names
    $SQL = "SHOW COLUMNS FROM Table";
        //put all of the column names in the array
        foreach($conn->query($SQL) as $row) {
            $here[] = $row[0];
        }
    //now search through the array containing the column names for the name of the column, in this case i used the common ID field as an example
    $key = array_search('ID', $here);
    //now delete the entry
    unset($here[$key]);

Select *는 SQL 안티패턴입니다.다음과 같은 여러 가지 이유로 프로덕션 코드에서 사용하면 안 됩니다.

처리하는 데 시간이 조금 더 걸립니다.작업이 수백만 번 실행되면 이러한 작은 부분이 중요할 수 있습니다.이러한 유형의 엉성한 코딩으로 인해 속도가 느려지는 느린 데이터베이스는 성능 조정이 가장 어려운 종류입니다.

이는 필요한 것보다 더 많은 데이터를 전송하고 있어 서버와 네트워크 병목 현상이 발생할 수 있음을 의미합니다.내부 조인이 있는 경우 필요한 것보다 더 많은 데이터를 보낼 가능성은 100%입니다.

특히 어디서나 표시하고 싶지 않은 새 열을 추가한 경우 유지 관리 문제가 발생합니다.또한 새 열이 있는 경우 해당 열로 무엇을 할지 결정하기 위해 인터페이스에 대한 작업을 수행해야 할 수도 있습니다.

이는 뷰를 깨뜨릴 수 있습니다(SQL 서버에서는 이것이 사실이라는 것을 알고 있으며, mysql에서는 사실일 수도 있고 아닐 수도 있습니다).

누군가 다른 순서로 열이 포함된 테이블을 재구축할 만큼 어리석은 경우(하면 안 되지만 항상 발생하는 일) 모든 종류의 코드가 손상될 수 있습니다.특히 지정하지 않고 갑자기 도시를 address_3 필드에 넣는 경우와 같이 삽입을 위한 코드는 데이터베이스가 열 순서대로만 진행될 수 있기 때문입니다.이는 데이터 유형이 변경될 때 충분히 나쁘지만 교체된 열이 동일한 데이터 유형을 가질 때 더 나쁩니다. 왜냐하면 때때로 정리하기 어려운 잘못된 데이터를 삽입할 수 있기 때문입니다.데이터 무결성에 주의를 기울여야 합니다.

삽입에 사용되는 경우 한 테이블에는 새 열이 추가되고 다른 테이블에는 추가되지 않으면 삽입이 중단됩니다.

트리거가 중단될 수 있습니다.트리거 문제는 진단하기 어려울 수 있습니다.

열 이름을 추가하는 데 걸리는 시간에 대해 이 모든 것을 합산하세요(도대체 열 이름 위로 드래그할 수 있는 인터페이스가 있을 수도 있습니다(SQL Server에서는 그렇게 한다는 것을 알고 있습니다. 이것은 mysql 쿼리를 작성하는 데 사용하는 도구입니다.) "유지 관리 문제, 성능 문제, 데이터 무결성 문제를 일으킬 수 있지만 개발 시간을 5분 절약했습니다."를 살펴보겠습니다. 원하는 특정 열에.

나는 또한 이 책을 읽어볼 것을 제안합니다:http://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers-ebook/dp/B00A376BB2/ref=sr_1_1?s=digital-text&ie=UTF8&qid=1389896688&sr=1-1&keywords=sql+antipatterns

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top