Modification dynamique de la table à sélectionner avec l'instruction SQL CASE
-
20-08-2019 - |
Question
J'essaie d'écrire une procédure stockée et, en fonction d'une certaine valeur de colonne, je souhaite pouvoir modifier la table dans laquelle je sélectionne. Je vais essayer de donner un exemple:
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
Comme vous pouvez le constater, non seulement je change de manière dynamique la table dans laquelle je fais mon choix, mais, comme ces deux tables ont été créées à deux moments différents par deux personnes différentes, les noms des colonnes sont également différents.
Donc, ma question est la suivante: quel est le meilleur moyen d'y parvenir, car SQL Server ne semble pas aimer ma requête que j'ai construite.
Si quelqu'un qui voit ce que j'essaie de faire peut suggérer un meilleur moyen de le faire, je serais tout à fait à l'écoute: -)
La solution
Vous ne pouvez pas utiliser l'instruction CASE dans la clause FROM, mais vous pouvez utiliser les éléments suivants:
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'
Autres conseils
Vous pouvez essayer de construire l'instruction SQL dynamique sous forme de chaîne, puis d'appeler la procédure stockée sp_executesql pour exécuter la chaîne.
Voir ici pour plus d'informations et d'exemples.
Je ne suis pas sûr de savoir pourquoi vous souhaitez effectuer certaines tâches dans une instruction SQL. Je ne suis pas un utilisateur de SQL Server, mais vous pouvez écrire quelque chose comme ceci dans une procédure stockée Oracle
If itemtype = 'A'
Then
<statement for table A>
Else
<statement for Table B>
End if
Quelque chose comme ça devrait fonctionner dans SQL Server aussi .. peut-être que quelqu'un pourrait développer cela?
Vous n'expliquez pas vraiment d'où vient ItemType
. Comme suggéré, UNION
peut s’appliquer si vous combinez simplement deux tables.
Voici une autre possibilité pouvant être liée à votre problème:
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
Il vaut mieux utiliser la requête UNION pour joindre les tables en premier, puis SELECT.
Vous pouvez également envisager de créer une vue pour l'une des tables. Ainsi, seules les colonnes dont vous avez besoin sont renommées, puis UNION, puis sélectionnez-la dans UNION.
Ou utilisez une table temporaire pour stocker le résultat de chaque requête. Placez la création de la table temp dans un CASE (pseudocode, non testé):
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