MySQL에서 하나를 제외한 모든 열을 선택하시겠습니까?
문제
나는 하나를 제외하고 특정 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