Извлекать записи из промежуточной таблицы или извлекать все, если они не существуют - PullRequest
0 голосов
/ 09 июля 2019

У меня есть следующая схема базы данных:

CREATE TABLE [dbo].[TableType]
    (
    [id]       INT NOT NULL, 
    [name]     VARCHAR(100) NOT NULL,
    CONSTRAINT [PK_TableType] PRIMARY KEY CLUSTERED ([id] ASC), 
)
CREATE TABLE [dbo].[ColumnType]
    (
    [id]       INT NOT NULL, 
    [name]     VARCHAR(100) NOT NULL,
    CONSTRAINT [PK_ColumnType] PRIMARY KEY CLUSTERED ([id] ASC), 
)
CREATE TABLE [dbo].[TableTypeAllowedObjectType]
    (
    [id]                    INT IDENTITY (1, 1) NOT NULL, 
    [id_table_type]         INT NOT NULL,
    [id_column_type]        INT NOT NULL,
    [default_value]         BIT NOT NULL,
    CONSTRAINT [PK_TableTypeAllowedObjectType] PRIMARY KEY CLUSTERED ([id] ASC), 
    CONSTRAINT [FK_TableTypeAllowedColumnType_ColumnType] FOREIGN KEY ([id_column_type]) REFERENCES [dbo].[ColumnType]([id]),
    CONSTRAINT [FK_TableTypeAllowedColumnType_TableType] FOREIGN KEY ([id_table_type]) REFERENCES [dbo].[TableType]([id]),
)

Образец данных:

DELETE FROM dbo.TableTypeAllowedObjectType;
DELETE FROM dbo.TableType;
DELETE FROM dbo.ColumnType;

INSERT INTO dbo.TableType (id, name) values (1, 'TableType1');
INSERT INTO dbo.TableType (id, name) values (2, 'TableType2');

INSERT INTO dbo.ColumnType (id, name) values (1, 'ColumnType1');
INSERT INTO dbo.ColumnType (id, name) values (2, 'ColumnType2');
INSERT INTO dbo.ColumnType (id, name) values (3, 'ColumnType3');

INSERT INTO dbo.TableTypeAllowedObjectType (id_table_type, id_column_type, default_value) values(1, 1, 0);
INSERT INTO dbo.TableTypeAllowedObjectType (id_table_type, id_column_type, default_value) values(1, 2, 0);

Мне нужно получить все ColumnType записи для id_table_type, если они есть в [dbo].[TableTypeAllowedObjectType].Если для конкретного id_table_type нет записей, запрос должен вернуть все записи ColumnType.

Предполагаемый запрос для TableType1 должен выглядеть следующим образом

SELECT * FROM dbo.ColumnType ... WHERE id_table_type = 1

и возвращать записи ColumnType:

1   ColumnType1
2   ColumnType2

Предполагаемый запрос для TableType2 должен возвращать все записи:

1   ColumnType1
2   ColumnType2
3   ColumnType3

в этом конкретном примере мне нужно получить все записи ColumnType для TableType2 и ColumnTypes 1 и 2 для TableType1.

ссылка SQLFiddle

Есть идеи, как добиться этого более или менее эффективным способом?

Спасибо.

1 Ответ

1 голос
/ 10 июля 2019

Вот пример, который мне удалось получить в SSMS:

-- Sample tables.
DECLARE @TableType TABLE ( [id] INT NOT NULL, [name] VARCHAR(100) NOT NULL );
DECLARE @ColumnType TABLE ( [id] INT NOT NULL, [name] VARCHAR(100) NOT NULL );
DECLARE @TableTypeAllowedObjectType TABLE (
    [id] INT IDENTITY (1, 1) NOT NULL, [id_table_type] INT NOT NULL, [id_column_type] INT NOT NULL, [default_value] BIT NOT NULL
);

-- Sample data.
INSERT INTO @TableType (id, [name]) VALUES (1, 'TableType1'), (2, 'TableType2');
INSERT INTO @ColumnType (id, [name]) VALUES (1, 'ColumnType1'), (2, 'ColumnType2'), (3, 'ColumnType3');
INSERT INTO @TableTypeAllowedObjectType (id_table_type, id_column_type, default_value) VALUES (1, 1, 0), (1, 2, 0);

-- Variable for table type id.
DECLARE @TableTypeID INT = 1;

-- Query data based on table type id.
IF EXISTS( SELECT * FROM @TableTypeAllowedObjectType WHERE id_table_type = @TableTypeID )
    SELECT * FROM @ColumnType AS ColumnType
    WHERE EXISTS (
        SELECT * FROM @TableTypeAllowedObjectType AS AllowedType
        WHERE 
            ColumnType.id = AllowedType.id_column_type
            AND AllowedType.id_table_type = @TableTypeID
    )
ELSE
    SELECT * FROM @ColumnType AS ColumnType
    WHERE NOT EXISTS (
        SELECT * FROM @TableTypeAllowedObjectType AS AllowedType
        WHERE 
            ColumnType.id = AllowedType.id_column_type
            AND AllowedType.id_table_type = @TableTypeID
    )

@ TableTypeID = 1 возвращает:

+----+-------------+
| id |    name     |
+----+-------------+
|  1 | ColumnType1 |
|  2 | ColumnType2 |
+----+-------------+

@ TableTypeID = 2 возвращает:

+----+-------------+
| id |    name     |
+----+-------------+
|  1 | ColumnType1 |
|  2 | ColumnType2 |
|  3 | ColumnType3 |
+----+-------------+

Я полагаю, это то, что вы ищете?

ОБНОВЛЕНИЕ: Добавление функциональности в TVF.

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

-- Create TVF.
CREATE FUNCTION dbo.GetTableTypeColumns (
    @TableTypeID INT
)
RETURNS @Results TABLE (
    id INT, [name] VARCHAR(50)
)
AS
BEGIN


    IF EXISTS( SELECT * FROM dbo.TableTypeAllowedObjectType WHERE id_table_type = @TableTypeID ) BEGIN

        INSERT INTO @Results ( id, [name] )
        SELECT * FROM dbo.ColumnType
        WHERE EXISTS (
            SELECT * FROM dbo.TableTypeAllowedObjectType AS AllowedType
            WHERE 
                ColumnType.id = AllowedType.id_column_type
                AND AllowedType.id_table_type = @TableTypeID
        )

    END ELSE BEGIN

        INSERT INTO @Results ( id, [name] )
        SELECT * FROM dbo.ColumnType
        WHERE NOT EXISTS (
            SELECT * FROM dbo.TableTypeAllowedObjectType AS AllowedType
            WHERE 
                ColumnType.id = AllowedType.id_column_type
                AND AllowedType.id_table_type = @TableTypeID
        )

    END

    RETURN

END
GO

Как только вы создали TVF, вы можете назвать его так:

SELECT * FROM dbo.GetTableTypeColumns( 1 );

Returns

+----+-------------+
| id |    name     |
+----+-------------+
|  1 | ColumnType1 |
|  2 | ColumnType2 |
+----+-------------+

Или

SELECT * FROM dbo.GetTableTypeColumns( 2 );

Returns

+----+-------------+
| id |    name     |
+----+-------------+
|  1 | ColumnType1 |
|  2 | ColumnType2 |
|  3 | ColumnType3 |
+----+-------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...