sql - todas - SELECCIONAR*EXCEPTO
seleccionar todo excepto sql server (14)
¿Hay algún RDBMS que implemente algo como SELECT * EXCEPT?
Sí, Google Big Query implementa SELECT * EXCEPTO :
Una instrucción SELECT * EXCEPT especifica los nombres de una o más columnas para excluir del resultado. Todos los nombres de columna coincidentes se omiten de la salida.
WITH orders AS(
SELECT 5 as order_id,
"sprocket" as item_name,
200 as quantity
)
SELECT * EXCEPT (order_id)
FROM orders;
Salida:
+-----------+----------+
| item_name | quantity |
+-----------+----------+
| sprocket | 200 |
+-----------+----------+
¿Hay algún RDBMS que implemente algo como SELECT * EXCEPT
? Lo que busco es obtener todos los campos, excepto un campo TEXTO / BLOB específico, y me gustaría simplemente seleccionar todo lo demás.
Casi a diario me quejo con mis compañeros de trabajo de que alguien debería implementar esto ... Es terriblemente molesto que no exista.
Editar: entiendo la preocupación de todos por SELECT *
. Sé los riesgos asociados con SELECT *
. Sin embargo, esto, al menos en mi situación, no se usaría para ningún código de nivel de producción, o incluso código de nivel de desarrollo; estrictamente para la depuración, cuando necesito ver todos los valores fácilmente.
Como he indicado en algunos de los comentarios, donde trabajo es estrictamente una tienda de línea de comandos, haciendo todo a través de ssh. Esto dificulta el uso de herramientas GUI (no se permiten conexiones externas a la base de datos), etc., etc.
Gracias por las sugerencias sin embargo.
¿Hay algún RDBMS que implemente algo como SELECT * EXCEPTO
¡Sí! El verdadero lenguaje relacional Tutorial D permite que la proyección se exprese en términos de los atributos que se eliminarán en lugar de los que se deben guardar, por ejemplo
my_relvar { ALL BUT description }
De hecho, es equivalente a SQL SELECT *
es { ALL BUT }
.
Su propuesta para SQL es valiosa pero escuché que el grupo de usuarios ya la ha puesto en el comité de estándares de SQL y rechazado por el grupo del proveedor :(
También se solicitó explícitamente para SQL Server, pero la solicitud se cerró como ''no se corregirá''.
Aléjate de SELECT *, te estás preparando para problemas. Siempre especifique exactamente qué columnas quiere. De hecho, es bastante refrescante que la "característica" que está solicitando no exista.
Aquí, la opción de la tabla Temp, simplemente suelte las columnas no requeridas y seleccione * de la tabla temporal alterada.
/* Get the data into a temp table */
SELECT * INTO #TempTable
FROM
table
/* Drop the columns that are not needed */
ALTER TABLE #TempTable
DROP COLUMN [columnname]
SELECT * from #TempTable
Como han dicho otros, no es una buena idea hacer esto en una consulta porque es propenso a problemas cuando alguien cambia la estructura de la tabla en el futuro. Sin embargo, hay una manera de hacer esto ... y no puedo creer que realmente esté sugiriendo esto, pero en el espíritu de responder la pregunta REAL ...
Hazlo con SQL dinámico ... esto hace todas las columnas excepto la columna "descripción". Podría convertir esto fácilmente en una función o proceso almacenado.
declare @sql varchar(8000),
@table_id int,
@col_id int
set @sql = ''select ''
select @table_id = id from sysobjects where name = ''MY_Table''
select @col_id = min(colid) from syscolumns where id = @table_id and name <> ''description''
while (@col_id is not null) begin
select @sql = @sql + name from syscolumns where id = @table_id and colid = @col_id
select @col_id = min(colid) from syscolumns where id = @table_id and colid > @col_id and name <> ''description''
if (@col_id is not null) set @sql = @sql + '',''
print @sql
end
set @sql = @sql + '' from MY_table''
exec @sql
Como otros dicen: SELECT * es una mala idea.
Algunas razones:
- Obtenga solo lo que necesita (cualquier cosa más es un desperdicio)
- Indexación (indexe lo que necesita y puede obtenerlo más rápidamente. Si solicita un grupo de columnas no indexadas, también, sus planes de consulta sufrirán.
Cree una vista en la tabla que no incluya las columnas de blobs
Creo que la razón por la que no existe es que el autor de una consulta solo (por cuestiones de rendimiento) solo solicite lo que van a mirar / necesitar (y, por lo tanto, saber qué columnas especificar) - si alguien agrega un par más blobs en el futuro, estarías retirando campos potencialmente grandes que no vas a necesitar.
DB2 lo permite. Las columnas tienen un atributo / especificador de Hidden
.
De la documentación de syscolumns
OCULTO
CHAR (1) NOT NULL WITH DEFAULT ''N''
Indica si la columna está implícitamente oculta:P Parcialmente escondido. La columna está implícitamente oculta de SELECT *.
N No oculto La columna es visible para todas las declaraciones SQL.
Crear documentación de tablas Como parte de la creación de su columna, debe especificar el modificador IMPLICITLY HIDDEN
A continuación, se muestra un ejemplo de DDL de Implicitly Hidden Columns
CREATE TABLE T1
(C1 SMALLINT NOT NULL,
C2 CHAR(10) IMPLICITLY HIDDEN,
C3 TIMESTAMP)
IN DB.TS;
Si esta capacidad es tan efectiva para impulsar la adopción de DB2 se deja como un ejercicio para los lectores futuros.
En aras de la exhaustividad, esto es posible en el dialecto DremelSQL, haciendo algo como:
WITH orders AS (SELECT 5 as order_id, "foobar12" as item_name, 800 as quantity) SELECT * EXCEPT (order_id) FROM orders;
+-----------+----------+ | item_name | quantity | +-----------+----------+ | foobar12 | 800 | +-----------+----------+
También parece haber otra forma de hacerlo here sin Dremel.
Es una vieja pregunta, pero espero que esto todavía pueda ser útil.
DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = COALESCE(@SQL + '', '', '' '' ) + name FROM sys.columns WHERE name <> ''colName'' AND object_id = (SELECT id FROM sysobjects WHERE name = ''tblName'')
SELECT @SQL = ''SELECT '' + @SQL + '' FROM '' + ''tblName''
EXEC sp_executesql @SQL
Procedimiento almacenado:
usp_SelectAllExcept ''tblname'', ''colname''
ALTER PROCEDURE [dbo].[usp_SelectAllExcept]
(
@tblName SYSNAME
,@exception VARCHAR(500)
)
AS
DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = COALESCE(@SQL + '', '', '' '' ) + name from sys.columns where name <> @exception and object_id = (Select id from sysobjects where name = @tblName)
SELECT @SQL = ''SELECT '' + @SQL + '' FROM '' + @tblName
EXEC sp_executesql @SQL
Necesitaba algo como lo que @Glen pide para aliviar mi vida con HASHBYTES ().
Mi inspiración fueron las respuestas de @Jasmine y @Zerubbabel. En mi caso, tengo diferentes esquemas, por lo que el mismo nombre de tabla aparece más de una vez en sys.objects. Como esto puede ayudar a alguien con el mismo escenario, aquí va:
ALTER PROCEDURE [dbo].[_getLineExceptCol]
@table SYSNAME,
@schema SYSNAME,
@LineId int,
@exception VARCHAR(500)
AS
DECLARE @SQL NVARCHAR(MAX)
BEGIN
SET NOCOUNT ON;
SELECT @SQL = COALESCE(@SQL + '', '', '' '' ) + name
FROM sys.columns
WHERE name <> @exception
AND object_id = (SELECT object_id FROM sys.objects
WHERE name LIKE @table
AND schema_id = (SELECT schema_id FROM sys.schemas WHERE name LIKE @schema))
SELECT @SQL = ''SELECT '' + @SQL + '' FROM '' + @schema + ''.'' + @table + '' WHERE Id = '' + CAST(@LineId AS nvarchar(50))
EXEC(@SQL)
END
GO
Sí, finalmente está :) SQL Standard 2016 define funciones de tabla polimórfica
SQL: 2016 introduce funciones de tabla polimórficas (PTF) que no necesitan especificar el tipo de resultado por adelantado. En cambio, pueden proporcionar un procedimiento de componente de descripción que determina el tipo de devolución en tiempo de ejecución. Ni el autor del PTF ni el usuario del PTF necesitan declarar las columnas devueltas por adelantado.
Los PTF descritos por SQL: 2016 aún no están disponibles en ninguna base de datos probada.10 Los lectores interesados pueden consultar el informe técnico gratuito "Funciones de tabla polimórfica en SQL" publicado por ISO. Los siguientes son algunos de los ejemplos discutidos en el informe:
CSVreader, que lee la línea de encabezado de un archivo CVS para determinar el número y los nombres de las columnas de retorno
Pivot (en realidad unpivot), que convierte los grupos de columnas en filas (por ejemplo: phonetype, phonenumber) - me: no hay cadenas más codificadas :)
TopNplus, que pasa por N filas por partición y una fila adicional con los totales de las filas restantes
Oracle 18c
implementa este mecanismo. 18c Ejemplo de función de tabla polimórfica de Skip_col Ejemplo de función de tabla dinámica polimórfica de Oracle Live SQL y Skip_col
Este ejemplo muestra cómo omitir datos en función del nombre / tipo de datos específico:
CREATE PACKAGE skip_col_pkg AS
-- OVERLOAD 1: Skip by name
FUNCTION skip_col(tab TABLE, col columns)
RETURN TABLE PIPELINED ROW POLYMORPHIC USING skip_col_pkg;
FUNCTION describe(tab IN OUT dbms_tf.table_t,
col dbms_tf.columns_t)
RETURN dbms_tf.describe_t;
-- OVERLOAD 2: Skip by type --
FUNCTION skip_col(tab TABLE,
type_name VARCHAR2,
flip VARCHAR2 DEFAULT ''False'')
RETURN TABLE PIPELINED ROW POLYMORPHIC USING skip_col_pkg;
FUNCTION describe(tab IN OUT dbms_tf.table_t,
type_name VARCHAR2,
flip VARCHAR2 DEFAULT ''False'')
RETURN dbms_tf.describe_t;
END skip_col_pkg;
y el cuerpo:
CREATE PACKAGE BODY skip_col_pkg AS
/* OVERLOAD 1: Skip by name
* NAME: skip_col_pkg.skip_col
* ALIAS: skip_col_by_name
*
* PARAMETERS:
* tab - The input table
* col - The name of the columns to drop from the output
*
* DESCRIPTION:
* This PTF removes all the input columns listed in col from the output
* of the PTF.
*/
FUNCTION describe(tab IN OUT dbms_tf.table_t,
col dbms_tf.columns_t)
RETURN dbms_tf.describe_t
AS
new_cols dbms_tf.columns_new_t;
col_id PLS_INTEGER := 1;
BEGIN
FOR i IN 1 .. tab.column.count() LOOP
FOR j IN 1 .. col.count() LOOP
tab.column(i).pass_through := tab.column(i).description.name != col(j);
EXIT WHEN NOT tab.column(i).pass_through;
END LOOP;
END LOOP;
RETURN NULL;
END;
/* OVERLOAD 2: Skip by type
* NAME: skip_col_pkg.skip_col
* ALIAS: skip_col_by_type
*
* PARAMETERS:
* tab - Input table
* type_name - A string representing the type of columns to skip
* flip - ''False'' [default] => Match columns with given type_name
* otherwise => Ignore columns with given type_name
*
* DESCRIPTION:
* This PTF removes the given type of columns from the given table.
*/
FUNCTION describe(tab IN OUT dbms_tf.table_t,
type_name VARCHAR2,
flip VARCHAR2 DEFAULT ''False'')
RETURN dbms_tf.describe_t
AS
typ CONSTANT VARCHAR2(1024) := upper(trim(type_name));
BEGIN
FOR i IN 1 .. tab.column.count() LOOP
tab.column(i).pass_through :=
CASE upper(substr(flip,1,1))
WHEN ''F'' THEN dbms_tf.column_type_name(tab.column(i).description)
!=typ
ELSE dbms_tf.column_type_name(tab.column(i).description)
=typ
END /* case */;
END LOOP;
RETURN NULL;
END;
END skip_col_pkg;
Y uso de muestra:
-- skip number cols
SELECT * FROM skip_col_pkg.skip_col(scott.dept, ''number'');
-- only number cols
SELECT * FROM skip_col_pkg.skip_col(scott.dept, ''number'', flip => ''True'')
-- skip defined columns
SELECT *
FROM skip_col_pkg.skip_col(scott.emp, columns(comm, hiredate, mgr))
WHERE deptno = 20;
Recomiendo leer todo el ejemplo (crear funciones independientes en lugar de llamadas a paquetes).
Podría sobrecargar fácilmente el método de omisión, por ejemplo: omita las columnas que no comienzan / finalizan con un prefijo / sufijo específico.
declare @sql nvarchar(max)
@table char(10)
set @sql = ''select ''
set @table = ''table_name''
SELECT @sql = @sql + ''['' + COLUMN_NAME + ''],''
FROM INFORMATION_SCHEMA.Columns
WHERE TABLE_NAME = @table
and COLUMN_NAME <> ''omitted_column_name''
SET @sql = substring(@sql,1,len(@sql)-1) + '' from '' + @table
EXEC (@sql);