2013-11-18 3 views
5

Я бегу на SQL Server 2012.TSQL Выберите из другой таблицы на основе значения CASE-

Представьте У меня есть 3 таблицы (Table1, Table2, Таблица3), что все имеют в общем 2 поля (ID, WhereParam) ,

Что было бы правильным путем для достижения этой цели?

SELECT ID FROM 
      (CASE @Var 
       WHEN "AA" THEN Table1 
       WHEN "BB" THEN Table2 
       ELSE Table3) 
     WHERE "TableSelected".WhereParam = @WhereParam 
+4

Нет, вы не можете сделать это. 'CASE' в T-SQL является ** выражением **, которое может возвращать разные значения - это ** NOT ** оператор управления потоком, такой как' Switch' в C#, вы не можете использовать 'CASE' для условного выполнения использования кода 'IF' вместо –

+2

Я думаю, именно поэтому я спрашивал, как правильно достичь чего-то подобного: -) –

ответ

9

Использование IF (правильный способ)

IF @Var = 'AA' 
BEGIN 
    SELECT ID FROM Table1 
    -- WHERE ... 
END 
ELSE IF @Var = 'BB' 
BEGIN 
    SELECT ID FROM Table2 
    -- WHERE ... 
END 
ELSE 
BEGIN 
    SELECT ID FROM Table3 
    -- WHERE ... 
END 

Другие способы (вы должны избегать, но я выложу для справки)

Использование динамического SQL

DECLARE @sql NVARCHAR(MAX) 
SELECT @sql = 'SELECT ID FROM ' + CASE @Var WHEN 'AA' THEN 'Table1' 
              WHEN 'BB' THEN 'Table2' ELSE 'Table3' END + ' -- WHERE ...' 
EXEC(@sql) 

Использование UNION

SELECT Id 
FROM Table1 
WHERE @Var='AA' 
-- AND ... 

UNION ALL 

SELECT Id 
FROM Table2 
WHERE @Var='BB' 
-- AND ... 

UNION ALL 

SELECT Id 
FROM Table3 
WHERE @Var NOT IN('AA', 'BB') 
-- AND ... 
+1

Вы должны взглянуть на [Проклятие и благословения динамического SQL] (http://www.sommarskog.se /dynamic_sql.html) В нем описывается, как избежать проблемы с SQL-инъекцией у вас, необходимость цитирования имен таблиц и проблемы с разрешениями с динамическим sql, который вы опубликовали. –

+1

@Conrad Frix: Строго говоря, предоставленный ответ не имеет проблемы с SQL-инъекцией. Имена таблиц - это все литералы, поэтому SQL не может быть изменен путем предоставления вредоносной переменной. Ссылка, которую вы предоставили, по-прежнему является отличным ресурсом, если этот подход будет использоваться, однако. – Allan

+1

@ Аллен, ты прав, я неправильно читаю код. –

6

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

Select ID from (
    Select ID, WhereParam from Table1 where @Var = 'AA' 
    union all 
    Select ID, WhereParam from Table2 where @Var = 'BB' 
    union all 
    Select ID, WhereParam from Table3 where @Var not in ('AA','BB')) 
where WhereParam = @WhereParam 
+0

В моем случае @Var представляет идентификатор текущего пользователя. Пользователь «AA» не имеет доступа к Таблице 2 и Таблице 3, и аналогичным образом «BB» не имеет доступа к Таблице 1 и Таблице 3 и т. Д. .. Что может быть возможным решением в моем сценарии? –

3

Использование UNION ALL:

SELECT ID FROM Table1 
    WHERE @Var = 'AA' and Table1.WhereParam = @WhereParam 
UNION ALL 
SELECT ID FROM Table2 
    WHERE @Var = 'BB' and Table2.WhereParam = @WhereParam 
UNION ALL 
SELECT ID FROM Table3 
    WHERE @Var not in ('AA', 'BB') and Table3.WhereParam = @WhereParam 
Смежные вопросы