ВЫБЕРИТЕ * ЗА ИСКЛЮЧЕНИЕМ

Есть ли РСУБД, которая реализует что-то вроде SELECT * EXCEPT? Я получаю все поля, кроме определенного поля TEXT/BLOB, и я хотел бы просто выбрать все остальное.

Почти ежедневно я жалуюсь своим коллегам, что кто-то должен это реализовать... Это ужасно раздражает, что его не существует.

Edit: Я понимаю, что все относятся к SELECT *. Я знаю риски, связанные с SELECT *. Однако это, по крайней мере, в моей ситуации, не будет использоваться ни для какого кода уровня Продукции, ни даже кода уровня развития; строго для отладки, когда мне нужно легко увидеть все значения.

Как я уже говорил в некоторых комментариях, где я работаю, это строго магазин в командной строке, делая все по ssh. Это затрудняет использование любых инструментов gui (внешние подключения к базе данных не допускаются) и т.д. И т.д.

Спасибо за предложения, хотя.

Ответ 1

Как говорили другие, не рекомендуется делать это в запросе, потому что он подвержен проблемам, когда кто-то меняет структуру таблицы в будущем. Однако есть способ сделать это... и я не могу поверить, что я на самом деле предлагаю это, но в духе ответа на ФАКТИЧЕСКИЙ вопрос...

Сделайте это с помощью динамического SQL... это делает все столбцы, кроме столбца описания. Вы можете легко превратить это в функцию или сохраненную процедуру.

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

Ответ 2

Создайте представление в таблице, которое не содержит столбцы blob

Ответ 3

DB2 позволяет это. Столбцы имеют атрибут/спецификатор Hidden.

В документации syscolumns

HIDDEN
CHAR (1) NOT NULL WITH DEFAULT 'N'
Указывает, скрыт ли скрытый столбец:

P Частично скрыт. Столбец неявно скрыт от SELECT *.

N Не скрывается. Столбец виден всем операторам SQL.

Создать документацию по таблицам В качестве части создания столбца вы должны указать модификатор IMPLICITLY HIDDEN

Пример DDL из Неявно скрытых столбцов следует

CREATE TABLE T1
(C1 SMALLINT NOT NULL,
C2 CHAR(10) IMPLICITLY HIDDEN,
C3 TIMESTAMP)
IN DB.TS;

Независимо от того, является ли эта возможность таким разработчиком сделки, чтобы управлять принятием DB2, она остается в качестве упражнения для будущих читателей.

Ответ 4

  Есть ли СУБД, которая реализует что-то вроде SELECT * EXCEPT?

Да, Google Big Query реализует SELECT * EXCEPT:

Оператор SELECT * EXCEPT указывает имена одного или нескольких столбцов, которые необходимо исключить из результата. Все совпадающие имена столбцов опущены в выходных данных.

WITH orders AS(
  SELECT 5 as order_id,
  "sprocket" as item_name,
  200 as quantity
)
SELECT * EXCEPT (order_id)
FROM orders;

Выход:

+-----------+----------+
| item_name | quantity |
+-----------+----------+
| sprocket  | 200      |
+-----------+----------+

EDIT:

База данных H2 также поддерживает синтаксис SELECT * EXCEPT (col1, col2, ...).

Wildcard expression

Подстановочное выражение в операторе SELECT. Подстановочное выражение представляет все видимые столбцы. Некоторые столбцы могут быть исключены с помощью необязательного предложения EXCEPT.

Ответ 5

Есть ли какая-нибудь СУБД, которая реализует нечто вроде SELECT * EXCEPT

Да! По-настоящему реляционный язык Учебник D позволяет проецировать выражение в терминах атрибутов, подлежащих удалению, вместо тех, которые нужно сохранить, например.

my_relvar { ALL BUT description }

Фактически, его эквивалент SQL SELECT * равен { ALL BUT }.

Ваше предложение для SQL является достойным, но я слышал, что он уже был помещен в стандартный комитет SQL группой пользователей и отклонен группой поставщиков:(

Он также был явно запрошен для SQL Server, но запрос был закрыт как "не будет исправлять".

Ответ 6

Да, наконец, есть :) SQL Standard 2016 определяет Полиморфные функции таблицы

SQL: 2016 вводит полиморфные функции таблицы (PTF), которые не требуют указания типа результата. Вместо этого они могут предоставить описываемую процедуру компонента, которая определяет тип возврата во время выполнения. Ни автору PTF, ни пользователю PTF не нужно объявлять возвращенные столбцы заранее.

PTF, как описано в SQL: 2016, еще не доступны ни в одной проверенной базе данных. Заинтересованные читатели могут ссылаться на бесплатный технический отчет "Полиморфные функции таблицы в SQL", выпущенный ISO. Ниже приводятся некоторые примеры, рассмотренные в отчете:

  • CSVreader, который считывает строку заголовка файла CVS для определения числа и имен столбцов возврата

  • Pivot (фактически неавторизованный), который превращает группы столбцов в строки (например: phonetype, phonenumber) - me: больше нет привязанных строк :)

  • TopNplus, который проходит через N строк на раздел и одну дополнительную строку с итогами оставшихся строк


Oracle 18c реализует этот механизм. 18c. Пример функции полиморфной таблицы Skip_col. Пример функции Oracle Live SQL и Skip_col Polymorphic Table.

В этом примере показано, как пропустить данные на основе имени/конкретного типа данных:

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;

и тело:

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;  

И использование образца:

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

Я настоятельно рекомендую прочитать весь пример (создание автономных функций вместо вызовов пакетов).

Вы можете легко перегрузить метод пропуска, например: пропустить столбцы, которые не запускаются/не заканчиваются определенным префиксом/суффиксом.

db <> fidde demo

Ответ 7

Держитесь подальше от SELECT *, вы настраиваете себя на неприятности. Всегда указывайте точно, какие столбцы вы хотите. На самом деле это довольно освежает, что "функции", о которой вы просите, не существует.

Ответ 8

Я считаю, что обоснование для него не существует, так это то, что автор запроса должен (ради производительности) запрашивать только то, что они будут искать/нужно (и, следовательно, знать, какие столбцы указать) - если кто-то добавляет еще несколько капель в будущем, вы будете отвлекать потенциально большие поля, которые вам не понадобятся.

Ответ 9

Как говорят другие: SELECT * - плохая идея.

Некоторые причины:

  • Получите только то, что вам нужно (что-то большее - это отходы).
  • Индексирование (индексируйте то, что вам нужно, и вы можете получить его быстрее). Если вы попросите кучу неиндексированных столбцов, ваши планы запросов пострадают.

Ответ 10

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

Ответ 11

Это старый вопрос, но я надеюсь, что этот ответ все еще может быть полезным для других. Его также можно изменить, добавив более одного, кроме полей. Это может быть очень удобно, если вы хотите разворачивать таблицу со многими столбцами.

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

Хранимая процедура:

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

Ответ 12

Мне нужно было что-то вроде того, что @Glen просит облегчить мою жизнь с помощью HASHBYTES().

Мое вдохновение было ответом @Jasmine и @Zerubbabel. В моем случае у меня разные схемы, поэтому одно и то же имя таблицы появляется несколько раз в sys.objects. Поскольку это может помочь кому-то с тем же сценарием, вот оно:

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

Ответ 13

Параметр Temp table здесь, просто отмените требуемые столбцы и выберите * из измененной таблицы temp.

/* 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

Ответ 14

Для полноты, это возможно на диалекте DremelSQL, делая что-то вроде:

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 | +-----------+----------+

Также существует и другой способ сделать это здесь без Dremel.