ВЫБРАТЬ * ИСКЛЮЧИТЬ - PullRequest
       62

ВЫБРАТЬ * ИСКЛЮЧИТЬ

49 голосов
/ 05 января 2009

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

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

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

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

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

Ответы [ 14 ]

33 голосов
/ 05 января 2009

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

Делать это с динамическим 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
24 голосов
/ 05 января 2009

Создание представления на таблице, которое не включает столбцы BLOB-объектов

9 голосов
/ 10 августа 2013

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

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

HIDDEN
CHAR (1) НЕ НЕДЕЙСТВИТЕЛЕН С ПО УМОЛЧАНИЮ '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, оставлено для будущих читателей.

6 голосов
/ 10 апреля 2018

Есть ли СУБД, которая реализует что-то вроде 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      |
+-----------+----------+
5 голосов
/ 15 февраля 2012

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

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

my_relvar { ALL BUT description }

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

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

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

3 голосов
/ 05 января 2009

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

2 голосов
/ 27 февраля 2018

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

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

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

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

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

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


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

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

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

2 голосов
/ 05 января 2009

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

0 голосов
/ 04 августа 2017

Ради полноты, это возможно на диалекте 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 | +-----------+----------+

Кажется, есть и другой способ сделать это здесь без Дремеля.

0 голосов
/ 18 июля 2017

Здесь указана временная таблица, просто отбросьте ненужные столбцы и выберите * из измененной временной таблицы.

/* 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...