Alterando dinamicamente qual tabela para selecionar com a instrução SQL CASE
-
20-08-2019 - |
Pergunta
Estou tentando escrever um procedimento armazenado e, dependendo de um determinado valor da coluna, quero poder alterar de que tabela seleciono. Vou tentar dar um exemplo:
SELECT ItemNumber,
ItemType,
Description
FROM
CASE ItemType
WHEN 'A' THEN TableA
ELSE TableB
END
WHERE
CASE ItemType
WHEN 'A' THEN ItemNumber = @itemNumber
ELSE PartNumber = @itemNumber
END
Como você pode ver, não apenas estou alterando dinamicamente a tabela que seleciono, mas como essas duas tabelas foram feitas em dois momentos diferentes por duas pessoas diferentes, os nomes das colunas também são diferentes.
Portanto, minha pergunta é: qual é a melhor maneira de conseguir isso, já que o SQL Server não parece gostar da minha consulta que eu construí.
Se alguém que vê o que estou tentando fazer pode sugerir uma maneira melhor de fazer isso, eu estaria todos ouvidos :-)
Solução
Você não pode usar a declaração de caso na cláusula, mas pode usar o seguinte:
SELECT itemnumber, itemtype, description
FROM tablea
WHERE itemnumber = @itemnumber AND itemtype = 'A'
UNION ALL
SELECT itemnumber, itemtype, description
FROM tableb
WHERE partnumber = @itemnumber AND itemtype <> 'A'
Outras dicas
Você pode tentar criar a instrução SQL dinâmica como uma string e, em seguida, chamando o procedimento armazenado sp_executesql para executar a string.
Ver aqui Para mais informações e exemplos.
Não sei por que você quer fazer as coisas em uma declaração SQL .. Eu não sou uma pessoa do servidor SQL, mas em um procedimento armazenado do Oracle, você pode escrever algo assim
If itemtype = 'A'
Then
<statement for table A>
Else
<statement for Table B>
End if
Algo assim também deve funcionar no SQL Server .. Talvez alguém possa expandir isso?
Você realmente não está explicando onde ItemType
está vindo de. Como sugerido UNION
Pode ser aplicável se você estiver simplesmente combinando duas tabelas.
Aqui está outra possibilidade que pode estar relacionada ao seu problema:
SELECT ItemNumber,
ItemType,
COALESCE(TableA.Description, TableB.Description) AS Description
FROM Items
LEFT JOIN TableA
ON Items.ItemType = 'A'
AND TableA.ItemNumber = Items.ItemNumber
LEFT JOIN TableB
ON Items.ItemType <> 'A'
AND TableB.ItemNumber = Items.ItemNumber
Você é melhor usar a consulta da Union para se juntar às tabelas primeiro e depois selecionar.
Além disso, você pode criar uma visão para uma das tabelas, por isso puxa apenas as colunas necessárias ao renomear, depois a união e depois selecionar no sindicato.
Ou use uma tabela temporária para armazenar o resultado de cada consulta. Coloque a criação da tabela de temperatura em um caso (pseudocódigo, não testado):
CASE @itemType
WHEN 'A'
SELECT ACol1 AS Col1, ACol2 AS Col2
FROM TABLE_A
INTO #tempTable
WHERE ItemNumber = @itemNumber
ELSE
SELECT BCol1 AS Col1, BCol2 AS Col2
FROM TABLE_B
INTO #tempTable
WHERE PartNumber = @itemNumber
END
SELECT * FROM #tempTable