Как выбрать *, но без "Имена столбцов должны быть уникальными в каждом представлении" - PullRequest
3 голосов
/ 21 июня 2011

Мне нужно инкапсулировать набор таблиц JOIN, которые мы часто используем на сервере базы данных вендора. Мы используем одну и ту же логику JOIN во многих местах в извлечениях и т. Д., И казалось, что VIEW позволит определять и поддерживать JOIN в одном месте.

CREATE VIEW MasterView
AS
SELECT *
FROM entity_1 e1
INNER JOIN entity_2 e2 ON e2.parent_id = entity_1.id
INNER JOIN entity_3 e3 ON e3.parent_id = entity_2.id
/* other joins including business logic */
etc.

Проблема в том, что поставщик регулярно вносит изменения в БД (добавление столбцов, изменение имени), и я хочу, чтобы это автоматически отражалось в «MasterView».

SELECT * позволил бы это, но все базовые таблицы имеют столбцы идентификаторов, поэтому я получаю сообщение об ошибке «Имена столбцов в каждом представлении должны быть уникальными».

Я специально хочу избежать перечисления имен столбцов из таблиц, потому что: а) требуется частое обслуживание; б) в таблице несколько сотен столбцов.

Есть ли способ добиться динамизма SELECT *, но эффективно исключить определенные столбцы (т. Е. Идентификаторы)

Спасибо

Ответы [ 6 ]

5 голосов
/ 21 июня 2011

Я специально хочу избежать перечисления имен столбцов из таблиц, потому что: а) требуется частое обслуживание; б) в таблице несколько сотен столбцов.

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

SELECT * это плохая практика независимо от того, если кто-то добавляет двоичный столбец объемом 2 ГБ в одну из этих таблиц и заполняет его, вы действительно хотите, чтобы он был возвращен?

3 голосов
/ 21 июня 2011

Так же как и ответ Одеда (согласен на 100%) ...

Если кто-то изменяет базовые таблицы, вам все равно нужно поддерживать представление (с sp_refreshview).Изменения столбца не будут автоматически отображаться в представлении.См. "выберите * из таблицы" vs "выберите colA, colB и т. Д. Из таблицы" интересное поведение в SQL Server 2005

Так что ваше "отражение в требовании" MasterView "автоматически может"все равно не будет удовлетворен

Если вы хотите убедиться, что представление обновлено, используйте WITH SCHEMABINDING, который предотвратит изменения в базовых таблицах (до тех пор, пока они не будут удалены или удалены). Затем внесите изменения в столбец, затем повторно применитевид

3 голосов
/ 21 июня 2011

Один простой способ генерирования нужных вам столбцов:

select column_name+',' from information_schema.columns
where table_name='tt'
and column_name not in('ID')
1 голос
/ 03 апреля 2017

У меня была та же проблема, см. Пример ниже:

ALTER VIEW Summary AS SELECT * FROM Table1 AS t1 INNER JOIN Table2 AS t2 ON t1.Id = t2.Id

, и я столкнулся с упомянутой вами ошибкой, самое простое решение - использовать псевдоним перед *, например так:

SELECT t1.* FROM Table1 AS t1 INNER JOIN Table2 AS t2 ON t1.Id = t2.Id

Вы больше не должны видеть эту ошибку.

0 голосов
/ 08 августа 2014

Если у вас есть Select *, а затем вы используете JOIN, результат может включать столбцы с одинаковым именем, что невозможно сделать в представлении. Если вы выполняете запрос самостоятельно, он работает нормально, но не при создании Посмотреть.

Например:

**Table A**
ID, CatalogName, CatalogDescription
**Table B**
ID, CatalogName, CatalogDescription
**After the JOIN query**
ID, CatalogName, CatalogDescription, ID, CatalogName, CatalogDescription
That's not possible in a View.

Укажите уникальное имя для каждого столбца в представлении. Использование просто * не очень хорошая практика.

0 голосов
/ 11 июля 2011

В конце концов я пошел с этим, основываясь на предложении Мадхиванана.Это похоже на то, что позже предложил t-clausen.dk (спасибо за ваши усилия), хотя я нахожу стиль пути xml более элегантным, чем курсоры / разделы ранга.

Следующее воссоздает определение MasterView при запуске.Все столбцы в базовых таблицах начинаются с имени таблицы, поэтому я могу включить в представление два столбца с одинаковыми именами по умолчанию.Это само по себе решает мою первоначальную проблему, но я также включил предложение «WHERE column_name NOT IN», чтобы специально исключить определенные столбцы, которые никогда не будут использоваться в MasterView.

create procedure Utility_RefreshMasterView 
as
begin

    declare @entity_columns varchar(max)
    declare @drop_view_sql varchar(max)
    declare @alter_view_definition_sql varchar(max)

    /* create comma separated string of columns from underlying tables aliased to avoid name collisions */
    select @entity_columns = stuff((
        select ','+table_name+'.['+column_name+'] AS ['+table_name+'_'+column_name+']' 
        from information_schema.columns
        where table_name IN ('entity_1', 'entity_2')
        and column_name not in ('column to exclude 1', 'column to exclude 2')
        for xml path('')), 1, 1, '')


    set @drop_view_sql = 'if exists (select * from sys.views where object_id = object_id(N''[dbo].[MasterView]'')) drop view MasterView'

    set @alter_view_definition_sql = 
    'create view MasterView as select ' + @entity_columns + '
    from entity_1
    inner join entity_2 on entity_2 .id = entity_1.id
    /* other joins follow */'

    exec (@drop_view_sql)
    exec (@alter_view_definition_sql)

end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...