Pregunta

Estoy intentando utilizar una declaración de selección para obtener todas las columnas de una determinada tabla MySQL excepto una.¿Existe una forma sencilla de hacer esto?

EDITAR:Hay 53 columnas en esta tabla (NO ES MI DISEÑO)

¿Fue útil?

Solución

En realidad hay una manera, necesitas tener permisos, por supuesto, para hacer esto...

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;

Reemplazo <table>, <database> and <columns_to_omit>

Otros consejos

En las definiciones de MySQL (manual) no existe tal cosa.Pero si tienes una cantidad realmente grande de columnas col1, ..., col100, lo siguiente puede resultar útil:

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

¿Funcionaría mejor una Vista en este caso?

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

Tu puedes hacer:

SELECT column1, column2, column4 FROM table WHERE whatever

sin obtener la columna 3, aunque ¿quizás estabas buscando una solución más general?

Si busca excluir el valor de un campo, p.Por motivos de seguridad/información confidencial, puede recuperar esa columna como nula.

p.ej.

SELECT *, NULL AS salary FROM users

Hasta donde yo sé, no lo hay.Puedes hacer algo como:

SELECT col1, col2, col3, col4 FROM tbl

y elija manualmente las columnas que desee.Sin embargo, si desea muchas columnas, es posible que desee hacer:

SELECT * FROM tbl 

y simplemente ignora lo que no quieres.

En su caso particular, le sugeriría:

SELECT * FROM tbl

a menos que solo quieras unas pocas columnas.Si solo quieres cuatro columnas, entonces:

SELECT col3, col6, col45, col 52 FROM tbl

estaría bien, pero si desea 50 columnas, entonces cualquier código que realice la consulta sería (¿demasiado?) difícil de leer.

Mientras probaba las soluciones de @Mahomedalid y @Junaid encontré un problema.Entonces pensé en compartirlo.Si el nombre de la columna tiene espacios o guiones como check-in, la consulta fallará.La solución sencilla es utilizar una comilla invertida alrededor de los nombres de las columnas.La consulta modificada está a continuación.

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;

Si la columna que no quería seleccionar tenía una gran cantidad de datos y no quería incluirla debido a problemas de velocidad y selecciona las otras columnas con frecuencia, le sugiero que cree una nueva tabla. con el único campo que normalmente no selecciona con una clave de la tabla original y elimine el campo de la tabla original.Únase a las tablas cuando ese campo adicional sea realmente obligatorio.

Podrías usar DESCRIBIR mi_tabla y use los resultados de eso para generar la declaración SELECT dinámicamente.

Mi principal problema son las muchas columnas que obtengo al unir tablas.Si bien esta no es la respuesta a su pregunta (cómo seleccionar todas las columnas excepto ciertas de uno tabla), creo que vale la pena mencionar que puedes especificar table. para obtener todas las columnas de una tabla en particular, en lugar de simplemente especificar .

A continuación se muestra un ejemplo de cómo esto podría resultar muy ú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') )

El resultado son todas las columnas de la tabla de usuarios y dos columnas adicionales que se unieron desde la metatabla.

Me gustó la respuesta de @Mahomedalid además de este hecho informado en comentario de @Bill Karwin.El posible problema planteado por @Jan Koritak Es cierto que me enfrenté a eso, pero encontré un truco para eso y solo quiero compartirlo aquí para cualquiera que enfrente el problema.

podemos reemplazar la función REEMPLAZAR con la cláusula donde en la subconsulta de la declaración preparada de esta manera:

Usando mi tabla y nombre de columna

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;

Entonces, esto excluirá solo el campo. id pero no company_id

Espero que esto ayude a cualquiera que busque una solución.

Saludos

Es una buena práctica especificar las columnas que está consultando incluso si consulta todas las columnas.

Por lo tanto, le sugiero que escriba el nombre de cada columna en la declaración (excluyendo la que no desea).

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

FROM table

Solo haz

SELECT * FROM table WHERE whatever

Luego suelte la columna en su lenguaje de programación favorito:PHP

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

Estoy de acuerdo con la solución "simple" de enumerar todas las columnas, pero esto puede resultar engorroso y los errores tipográficos pueden provocar una gran pérdida de tiempo.Utilizo una función "getTableColumns" para recuperar los nombres de mis columnas adecuadas para pegarlas en una consulta.Entonces todo lo que tengo que hacer es eliminar los que no quiero.

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;

Su resultado devuelve una cadena delimitada por comas, por ejemplo...

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

Estoy de acuerdo en que no es suficiente Select *, si el que no necesita, como se mencionó en otra parte, es un BLOB, no querrá que se produzca esa sobrecarga.

yo crearía un vista con los datos requeridos, entonces puedes Select * cómodamente, si el software de base de datos los admite.De lo contrario, coloque los datos enormes en otra tabla.

Al principio pensé que se podían usar expresiones regulares, pero como he estado leyendo documentos MYSQL parece que no puedes.Si yo fuera usted, usaría otro lenguaje (como PHP) para generar una lista de columnas que desea obtener, la almacenaría como una cadena y luego la usaría para generar el SQL.

Yo también quería esto, así que creé una función en su lugar.

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

Entonces, cómo funciona es que ingresas a la tabla, luego a una columna que no deseas o como en una matriz:matriz("id","nombre","cualquier columna")

Entonces en select podrías usarlo así:

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

o

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

De acuerdo con la respuesta de @ Mahomedalid.Pero no quería hacer algo como una declaración preparada y no quería escribir todos los campos.Entonces lo que tuve fue una solución tonta.Vaya a la tabla en phpmyadmin->sql->select, vuelca la consulta, copia, reemplaza y ¡listo!:)

Si bien estoy de acuerdo con la respuesta de Thomas (+1;)), me gustaría agregar la advertencia de que asumiré la columna que usted no want apenas contiene datos.Si contiene enormes cantidades de texto, xml o blobs binarios, tómese el tiempo para seleccionar cada columna individualmente.De lo contrario, su rendimiento se verá afectado.¡Salud!

Sí, aunque puede haber una E/S alta dependiendo de la tabla, aquí hay una solución que encontré para ello.

Select *
into #temp
from table

alter table #temp drop column column_name

Select *
from #temp

La respuesta publicada por Mahomedalid tiene un pequeño problema:

El código de función de reemplazo interno estaba reemplazando "<columns_to_delete>," por "", este reemplazo tiene un problema si el campo a reemplazar es el último en la cadena concat debido a que el último no tiene la coma char "," y no se elimina de la cadena.

Mi propuesta:

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

Reemplazo <table>, <database> y `

La columna eliminada se reemplaza por la cadena "FIELD_REMOVED". En mi caso, esto funciona porque estaba intentando proteger la memoria.(El campo que estaba eliminando es un BLOB de alrededor de 1 MB)

Según la respuesta de @Mahomedalid, he realizado algunas mejoras para admitir "seleccionar todas las columnas excepto algunas en 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;

Si tiene muchas columnas, use este SQL para cambiar group_concat_max_len

SET @@group_concat_max_len = 2048;

Quizás tenga una solución Jan Koritak señaló la discrepancia

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

Mesa :

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 de la consulta:

'SELECT name_eid,sal FROM employee'

Si siempre es la misma columna, entonces puede crear una vista que no la tenga.

De lo contrario, no, no lo creo.

Puede utilizar SQL para generar SQL si lo desea y evaluar el SQL que produce.Esta es una solución general ya que extrae los nombres de las columnas del esquema de información.A continuación se muestra un ejemplo de la línea de comandos de Unix.

Sustituyendo

  • MYSQL con tu comando mysql
  • TABLA con el nombre de la tabla
  • EXCLUDEDFIELD con nombre de campo excluido
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

En realidad, solo necesitará extraer los nombres de las columnas de esta manera una sola vez para construir la lista de columnas, excluyó esa columna y luego simplemente use la consulta que ha creado.

Entonces algo 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)

Ahora puedes reutilizar el $column_list cadena en las consultas que usted construye.

Me gustaría agregar otro punto de vista para resolver este problema, especialmente si tiene una pequeña cantidad de columnas para eliminar.

Podrías usar una herramienta de base de datos como Banco de trabajo MySQL para generar la declaración de selección por usted, solo tiene que eliminar manualmente esas columnas para la declaración generada y copiarla a su secuencia de comandos SQL.

En MySQL Workbench la forma de generarlo es:

Haga clic derecho en la tabla -> enviar al Editor Sql -> Seleccionar toda la declaración.

La respuesta aceptada tiene varias deficiencias.

  • Falla cuando los nombres de tablas o columnas requieren comillas invertidas
  • Falla si la columna que desea omitir es la última en la lista
  • Requiere enumerar el nombre de la tabla dos veces (una para la selección y otra para el texto de la consulta), lo cual es redundante e innecesario.
  • Potencialmente puede devolver nombres de columnas en el orden incorrecto

Todos estos problemas se pueden superar simplemente incluyendo comillas invertidas en el SEPARATOR para tu GROUP_CONCAT y usando un WHERE condición en lugar de REPLACE().Para mis propósitos (y me imagino que para muchos otros) quería que los nombres de las columnas se devolvieran en el mismo orden en que aparecen en la tabla misma.Para lograr esto, aquí utilizamos un explícito ORDER BY cláusula dentro del GROUP_CONCAT() función:

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

Llegué bastante tarde a encontrar una respuesta para esto, así es como siempre lo he hecho y, francamente, es 100 veces mejor y más claro que la mejor respuesta, solo espero que alguien la vea.Y encontrarlo ú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]);

Seleccionar * es un antipatrón de SQL.No debería usarse en código de producción por muchas razones, entre ellas:

Se tarda un poquito más en procesarlo.Cuando las cosas se ejecutan millones de veces, esos pequeños fragmentos pueden importar.Una base de datos lenta donde la lentitud es causada por este tipo de codificación descuidada es el tipo más difícil de ajustar el rendimiento.

Significa que probablemente esté enviando más datos de los que necesita, lo que provoca cuellos de botella tanto en el servidor como en la red.Si tiene una unión interna, las posibilidades de enviar más datos de los que necesita son del 100%.

Causa problemas de mantenimiento, especialmente cuando ha agregado nuevas columnas que no desea que se vean en todas partes.Además, si tiene una nueva columna, es posible que deba hacer algo en la interfaz para determinar qué hacer con esa columna.

Puede interrumpir las vistas (sé que esto es cierto en el servidor SQL, puede ser cierto o no en MySQL).

Si alguien es lo suficientemente tonto como para reconstruir las tablas con las columnas en un orden diferente (lo cual no deberías hacer, pero sucede todo el tiempo), todo tipo de código puede fallar.Especialmente codifique para una inserción, por ejemplo, donde de repente coloca la ciudad en el campo dirección_3 porque, sin especificar, la base de datos solo puede seguir el orden de las columnas.Esto es bastante malo cuando los tipos de datos cambian, pero es peor cuando las columnas intercambiadas tienen el mismo tipo de datos porque en algún momento puedes insertar datos incorrectos que son un desastre para limpiar.Debe preocuparse por la integridad de los datos.

Si se usa en una inserción, romperá la inserción si se agrega una nueva columna en una tabla pero no en la otra.

Podría romper los gatillos.Los problemas desencadenantes pueden ser difíciles de diagnosticar.

Sume todo esto con el tiempo que lleva agregar los nombres de las columnas (diablos, incluso puede tener una interfaz que le permita arrastrar los nombres de las columnas (sé que sí en SQL Server, apuesto a que hay alguna manera de (Esta es una herramienta que usas para escribir consultas MySQL.) Veamos, "Puedo causar problemas de mantenimiento, puedo causar problemas de rendimiento y puedo causar problemas de integridad de datos, pero bueno, me ahorré cinco minutos de tiempo de desarrollo". en las columnas específicas que desee.

También te sugiero que leas este libro: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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top