Pergunta

Estou tentando utilizar uma instrução select para obter todas as colunas de uma determinada tabela MySQL, exceto um.Existe uma maneira simples de fazer isso?

EDITAR:Há 53 colunas nesta tabela (NÃO é o MEU DESIGN)

Foi útil?

Solução

Na verdade, há uma maneira, você precisa ter permissões é claro que para fazer isso ...

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;

Substituindo <table>, <database> and <columns_to_omit>

Outras dicas

No mysql definições (manual) não existe tal coisa.Mas se você tiver um grande número de colunas col1, ..., col100, a seguir podem ser úteis:

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

Seria um modo de Exibição trabalhar melhor neste caso?

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

Você pode fazer:

SELECT column1, column2, column4 FROM table WHERE whatever

sem ficar coluna3, que talvez estivesse à procura de uma solução mais geral?

Se você estiver olhando para excluir o valor de um campo, por exemplo,por questões de segurança e sensíveis de informações, você pode obter essa coluna como null.

exemplo:

SELECT *, NULL AS salary FROM users

Para o melhor de meu conhecimento, não há.Você pode fazer algo como:

SELECT col1, col2, col3, col4 FROM tbl

e escolher manualmente as colunas que você deseja.No entanto, se você quer um monte de colunas e, em seguida, você pode apenas querer fazer um:

SELECT * FROM tbl 

e simplesmente ignorar o que você não quer.

No seu caso particular, eu gostaria de sugerir:

SELECT * FROM tbl

a menos que você quiser apenas algumas colunas.Se você quiser apenas quatro colunas e, em seguida:

SELECT col3, col6, col45, col 52 FROM tbl

seria bom, mas se você deseja 50 colunas, em seguida, qualquer código que faz com que a consulta poderia tornar-se (muito?) difícil de ler.

Ao tentar as soluções por @Mahomedalid e @Junaid eu encontrei um problema.Assim o pensamento de compartilhá-lo.Se o nome da coluna é ter espaços ou hífens como check-in, em seguida, a consulta irá falhar.A solução simples é usar backtick em torno de nomes de coluna.Consulta modificada é abaixo

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;

Se a coluna que você não deseja selecionar tinha uma enorme quantidade de dados, e você não quiser incluí-lo devido a problemas de velocidade e selecione as outras colunas, muitas vezes, eu gostaria de sugerir que você crie uma nova tabela com um campo que você não costuma selecionar uma chave para a tabela original e remover o campo da tabela original.Associar as tabelas quando o campo extra é realmente necessário.

Você poderia usar DESCREVER my_table e utilizar os resultados do que para gerar a instrução SELECT dinamicamente.

O meu principal problema é o número de colunas que tenho quando associar tabelas.Enquanto esta não é a resposta para a sua pergunta (como selecionar todo, mas algumas colunas de um tabela), acho que vale a pena mencionar que você pode especificar table. para obter todas as colunas de uma determinada tabela, em vez de apenas a especificação do .

Aqui está um exemplo de como isso pode ser muito útil:

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

O resultado é que todas as colunas da tabela de usuários, e duas colunas adicionais que foram juntar-se a meta de tabela.

Gostei da resposta do @Mahomedalid além deste fato informado no comentário de @Bill Karwin.O possível problema levantado por @Jan Koritak é verdade que eu enfrentei, mas tenho de ter encontrado um truque para isso e só quiser compartilhá-lo aqui para quem enfrenta o problema.

podemos substituir a SUBSTITUIR a função com a cláusula where na sub-consulta de instrução Preparada como este:

Usando o meu nome de tabela e coluna

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;

Então, isso vai excluir apenas o campo id mas não company_id

Espero que isso irá ajudá-para quem procura uma solução.

Matéria

É uma boa prática para especificar as colunas que você está consultando mesmo se você consultar todas as colunas.

Então eu sugiro que você escreva o nome de cada coluna na instrução (excluindo o que você não quer).

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

FROM table

Basta fazer

SELECT * FROM table WHERE whatever

Em seguida, solte a coluna em você favoritos linguagem de programação:php

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

Eu concordo com o "simples" solução de listagem de todas as colunas, mas isso pode ser pesado, e erros de digitação podem causar muita perda de tempo.Eu uso uma função "getTableColumns" para recuperar os nomes das minhas colunas adequado para colar em uma consulta.Em seguida, tudo o que eu preciso fazer é excluir aqueles que eu não quero.

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;

O resultado retorna uma seqüência de caracteres delimitada por vírgula, por exemplo...

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

Eu concordo que ele não é suficiente para Select *, se você não precisa, como mencionado alhures, é um BLOB, você não quer ter essa sobrecarga creep.

Gostaria de criar um visualizar com os dados necessários e, em seguida, você pode Select * no conforto --se o software de banco de dados oferece suporte a eles.Outra coisa, colocar o enorme dados em outra tabela.

No começo eu pensei que você poderia usar expressões regulares, mas como eu estive lendo o MYSQL docs parece que você não pode.Se eu fosse você eu iria usar outro idioma (como o PHP) para gerar uma lista de colunas que você deseja obter, armazenar e como uma seqüência de caracteres e, em seguida, usar isso para gerar o SQL.

Eu queria isso também, então eu criei uma função em vez disso.

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)."`";
    }
}

Então, como ele funciona é que você inserir a tabela e, em seguida, uma coluna que você não quer ou como uma matriz:array("id","nome","whatevercolumn")

Assim, na escolha que você pode usá-lo assim:

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

ou

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

Concordo em @Mahomedalid resposta.Mas eu não queria fazer algo parecido instrução preparada e eu não queria digitar todos os campos.Então, o Que eu tinha era um bobo solução.Vá para a tabela no phpmyadmin->sql>select, ele descarta a consulta de cópia de substituir e pronto!:)

Enquanto eu concordo com o Thomas resposta (+1 ;)), eu gostaria de acrescentar a ressalva de que eu vou assumir a coluna que você não quer contém quase todos os dados.Se ele contém enormes quantidades de texto, xml ou blobs binários, em seguida, tomar o tempo para selecionar cada coluna individualmente.Seu desempenho será afetado de outra forma.Saúde!

Sim, apesar de ser alta e/S dependendo da tabela aqui está uma solução que eu encontrei para ele.

Select *
into #temp
from table

alter table #temp drop column column_name

Select *
from #temp

A resposta postado por Mahomedalid tem um pequeno problema:

Dentro de substituir o código de função foi substituindo "<columns_to_delete>,"por " que", esta substituição tem um problema se o campo para substituir é o último no concat cadeia devido a este último não tem o char vírgula "," e não é removido da cadeia.

A minha proposta:

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>');

Substituindo <table>, <database> e `

A coluna removida, é substituída pela seqüência de caracteres "FIELD_REMOVED" no meu caso isso funciona porque eu estava tentando para memória de segurança.(O campo estava removendo é um BLOB de cerca de 1 MB)

Com base no @Mahomedalid resposta, eu tenho feito algumas melhorias para suporte "selecione todas as colunas, exceto alguns no 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;

Se você tem um monte de colunas, use sql para alterar group_concat_max_len

SET @@group_concat_max_len = 2048;

Pode ser que eu tenha uma solução para Jan Koritak do apontou a discrepância

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' );

Tabela :

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

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

Resultado Da Consulta:

'SELECT name_eid,sal FROM employee'

Se é sempre a mesma coluna e, em seguida, você pode criar um modo de exibição que não tem mesmo.

Caso contrário, não, eu não penso assim.

Você pode usar o SQL para gerar SQL, se você gosta e avaliar o SQL produz.Esta é uma solução geral que extrai os nomes de coluna do esquema de informações.Aqui está um exemplo de linha de comando Unix.

Substituindo

  • O MYSQL com o comando mysql
  • TABELA com o nome da tabela
  • EXCLUDEDFIELD com excluídas nome do campo
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

Você realmente só precisa extrair os nomes de coluna dessa forma apenas uma vez para construir a coluna da lista de excluídos dessa coluna e, em seguida, basta usar a consulta que você tem construído.

Algo assim como:

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)

Agora você pode reutilizar o $column_list seqüência de caracteres em consultas de construir.

Eu gostaria de adicionar outro ponto de vista, a fim de resolver este problema, especialmente se você tiver um pequeno número de colunas de a remover.

Você pode usar uma ferramenta DB como O MySQL Workbench a fim de gerar a instrução select para você, assim você só tem que remover manualmente as colunas para a instrução gerada e copiar para o seu script SQL.

No MySQL Workbench o caminho para gerá-lo é:

Direito do mouse sobre a tabela -> enviar para o Editor de Sql -> Selecionar Tudo Instrução.

Aceito resposta tem várias deficiências.

  • Ele falha onde a tabela ou coluna de nomes necessita de aspas para traz
  • Ele falhará se a coluna que você deseja omitir é o último da lista
  • Ele requer de listagem o nome da tabela duas vezes (uma vez para selecionar e outra para o texto da consulta), o que é redundante e desnecessário
  • Ele pode retornar potencialmente nomes de coluna na ordem errada

Todos esses problemas podem ser superados por, simplesmente, incluindo aspas invertidas no SEPARATOR para a sua GROUP_CONCAT e usando um WHERE condição em vez de REPLACE().Para os meus propósitos (e imagino que muitos outros) eu queria os nomes das colunas retornadas na mesma ordem em que aparecem na tabela de si.Para conseguir isso, aqui nós usamos um explícito ORDER BY cláusula dentro do GROUP_CONCAT() função:

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

Estou bastante atrasado em throing uma resposta para isso, coloque esta é a maneira que sempre fiz e, francamente, é 100 vezes melhor e mais puro do que a melhor resposta, eu só espero que alguém vai vê-lo.E encontrá-lo útil

    //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]);

Seleccione: * é um SQL antipattern.Ele não deve ser usado no código de produção, por muitas razões, incluindo:

É preciso um pouquinho mais de tempo para processar.Quando as coisas estão a correr milhões de vezes, aqueles pequenos pedaços podem importa.Um banco de dados lento, onde a lentidão é causada por este tipo de desleixado codificação todo é o tipo mais difícil para optimizar o desempenho.

Isso significa que você, provavelmente, o envio de mais dados que você precisa, que faz com que o servidor de e gargalos de rede.Se você tem um inner join, as chances de enviar mais dados do que você precisa são de 100%.

Ele faz com que os problemas de manutenção, especialmente quando você tiver adicionado novas colunas que você não deseja vistas em todos os lugares.Ainda mais se você tiver uma nova coluna, você pode precisar fazer alguma coisa para a interface para determinar o que fazer com essa coluna.

Ele pode quebrar pontos de vista (eu sei que isto é verdade no SQl server, ele pode ou não ser verdadeira em mysql).

Se alguém é bobo o suficiente para recriar as tabelas com colunas em uma diferente ordem (que você não deve fazer, mas isso acontece todo o tempo), todo o tipo de código pode quebrar.Espcially código para uma inserção por exemplo, quando, de repente, você está colocando a cidade em address_3 campo porque sem especificar, a base de dados só pode ir sobre a ordem das colunas.Isto é ruim o suficiente quando os tipos de dados de mudar, mas pior quando troquei colunas têm o mesmo tipo de dados porque você pode ir, por algum tempo, a inserção de dados inválidos que é uma bagunça para limpar.Você precisa se preocupar com a integridade dos dados.

Se ele for usado em um insert, ele vai quebrar a se inserir uma nova coluna é adicionada em uma tabela, mas não o outro.

Ele pode quebrar dispara.Desencadear problemas pode ser difícil de diagnosticar.

Somar tudo isso contra o tempo que demorar para adicionar os nomes de coluna (heck, você pode até ter uma interface que permite que você arraste os nomes das colunas (eu sei o que eu faço no SQL Server, eu aposto que há alguma maneira de fazer isso é alguma ferramenta que você usa para escrever consultas mysql.) Vamos ver, "eu pode causar problemas de manutenção, eu pode causar problemas de desempenho e posso causar problemas de integridade de dados, mas ei, eu salvo a cinco minutos do dev tempo." Realmente só colocar nas colunas específicas que você deseja.

Eu também sugiro que você leia este livro: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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top