Рефакторированная проекция SQL?

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

Я понимаю, что два запроса ниже имеют дело с двумя разными таблицами, но эти таблицы в основном содержат данные одного типа (разные предикаты требуют двух запросов), и я думаю о двух проекциях ниже, как о "одной и той же вещи, определенной в двух местах",

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

Учитывая это, и без использования динамического SQL и без '*' в любой проекции (не разрешено в моей производственной среде), могу ли я один раз определить "набор столбцов" и использовать его в обоих запросах?

SELECT columnA
    , columnB
    , columnC
FROM Data

SELECT columnA
    , columnB
    , columnC
FROM DataArchive

4 ответа

Решение

Ваша база должна быть объединением Data и DataArchive и использовать встроенную табличную функцию (SQL Server 2005 и выше)?

CREATE FUNCTION UnifiedData (@LiveOnly bit, @ArchiveOnly bit)
RETURNS TABLE
AS
RETURN (
    SELECT columnA
           ,columnB
           ,columnC
    FROM (
        SELECT 'Live' AS Src, * 
        FROM Data
        WHERE @ArchiveOnly = 0

        UNION ALL

        SELECT 'Archive' AS Src, *
        FROM DataArchive
        WHERE @LiveOnly = 0
    )
)

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

Создайте представление Data UNION ALL DataArchive. Если позже вы сможете выполнить рефакторинг и объединить две таблицы, это будет прозрачно для ваших существующих запросов.

Я не могу придумать какой-либо эффективный способ сделать это. Вы могли бы, конечно, сделать вид с UNION ALL из двух таблиц с добавлением столбца, который содержит имя таблицы в виде строки, затем выполните SELECT columnA, columnB, columnC FROM view WHERE table = 'Data' но это похоже на довольно уродливый хак.

Да, SQL ужасен в этом смысле. Не существует универсального удовлетворительного способа сделать это. Вот пример использования синонимов:

if object_id('DataSynonym') is not null drop synonym DataSynonym
create synonym DataSynonym for Data
select columnA, columnB, columnC from DataSynonym

if object_id('DataSynonym') is not null drop synonym DataSynonym
create synonym DataSynonym for DataArchive
select columnA, columnB, columnC from DataSynonym

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

Временные представления / функции или переменные представления / функции будут иметь большое значение для решения проблемы. Или макроязык, как то, что доступно в SAS.

Другие вопросы по тегам