Comment puis-je dynamiquement alias des colonnes?


10

J'ai une table (non conçue par moi) qui a 20 colonnes nommées de manière variable. Autrement dit, selon le type d'enregistrement que vous consultez, le nom applicable de la colonne peut changer.

Les noms de colonnes possibles sont stockés dans une autre table, que je peux interroger très facilement.

Par conséquent, la requête que je recherche vraiment ressemble à ceci:

SELECT Col1 AS (SELECT ColName FROM Names WHERE ColNum = 1 and Type = @Type),
       Col2 AS (SELECT ColName FROM Names WHERE ColNum = 2 and Type = @Type)
FROM   Tbl1 
WHERE  Type = @Type

Évidemment, cela ne fonctionne pas, alors comment obtenir un résultat similaire?

' J'ai essayé de construire une chaîne de requête et de l' EXECUTEintégrer, mais cela ne fait que retourner "Commande (s) terminée avec succès" et ne semble pas retourner un ensemble de lignes. Il s'avère que j'utilisais une requête incorrecte pour construire le SQL dynamique et en tant que tel, j'ai construit une chaîne vide. SQL Server a définitivement exécuté correctement la chaîne vide.

Notez que la raison pour laquelle j'ai besoin que cela se produise, plutôt que de simplement coder en dur les noms de colonne, est que les noms de colonne sont configurables par l'utilisateur.


1
Que se passe-t-il si vous IMPRIMEZ la chaîne de requête, copiez / collez dans une nouvelle fenêtre de requête et l'exécutez là?
DenisT

«Configurable par l'utilisateur», ce qui signifie qu'il existe des centaines ou des milliers de types et / ou d'alias changés fréquemment? Si les alias sont assez stables, je recommanderais de créer une série de vues.
Jon of All Trades

@DenisT, il ne produit rien, ce qui indique peut-être aussi que quelque chose d'autre ne va pas. Merci pour l'exemple.
Hotchips

@JonofAllTrades Malheureusement, bien qu'ils soient assez stables, cela fait partie de la spécification que lorsque l'utilisateur change quelque chose dans le logiciel, cette chose doit également changer dans les rapports.
Hotchips

@DenisT Il s'avère que mes sous-requêtes utilisées pour créer le SQL dynamique étaient incorrectes et renvoyaient des ensembles nuls. SQL Server a donc renvoyé une requête vide, qu'il a dûment exécutée avec succès. Merci d'avoir signalé la commande IMPRIMER.
Hotchips

Réponses:


12

Essayez le code suivant:

CREATE TABLE #Names
(
    [Type] VARCHAR(50),
    ColNum SMALLINT,
    ColName VARCHAR(50),
    ColDataType VARCHAR(20)
)

INSERT  INTO #Names VALUES
('Customer', 1, 'CustomerID', 'INT'),
('Customer', 2, 'CustomerName', 'VARCHAR(50)'),
('Customer', 3, 'CustomerJoinDate', 'DATE'),
('Customer', 4, 'CustomerBirthDate', 'DATE'),
('Account', 1, 'AccountID', 'INT'),
('Account', 2, 'AccountName', 'VARCHAR(50)'),
('Account', 3, 'AccountOpenDate', 'DATE'),
('CustomerAccount', 1, 'CustomerID', 'INT'),
('CustomerAccount', 2, 'AccountID', 'INT'),
('CustomerAccount', 3, 'RelationshipSequence', 'TINYINT')


CREATE TABLE #Data
(
    [Type] VARCHAR(50),
    Col1 VARCHAR(50),
    Col2 VARCHAR(50),
    Col3 VARCHAR(50),
    Col4 VARCHAR(50),
    Col5 VARCHAR(50),
    Col6 VARCHAR(50),
    Col7 VARCHAR(50)
)

INSERT  INTO #Data VALUES
('Customer', '1', 'Mr John Smith', '2005-05-20', '1980-11-15', NULL, NULL, NULL),
('Customer', '2', 'Mrs Hayley Jones', '2009-10-10', '1973-04-03', NULL, NULL, NULL),
('Customer', '3', 'ACME Manufacturing Ltd', '2012-12-01', NULL, NULL, NULL, NULL),
('Customer', '4', 'Mr Michael Crocker', '2014-01-13', '1957-01-23', NULL, NULL, NULL),
('Account', '1', 'Smith-Jones Cheque Acct', '2005-05-25', NULL, NULL, NULL, NULL),
('Account', '2', 'ACME Business Acct', '2012-12-01', NULL, NULL, NULL, NULL),
('Account', '3', 'ACME Social Club', '2013-02-10', NULL, NULL, NULL, NULL),
('Account', '4', 'Crocker Tipping Fund', '2014-01-14', NULL, NULL, NULL, NULL),
('CustomerAccount', '1', '1', '1', NULL, NULL, NULL, NULL),
('CustomerAccount', '2', '1', '2', NULL, NULL, NULL, NULL),
('CustomerAccount', '2', '3', '2', NULL, NULL, NULL, NULL),
('CustomerAccount', '3', '2', '1', NULL, NULL, NULL, NULL),
('CustomerAccount', '3', '3', '1', NULL, NULL, NULL, NULL),
('CustomerAccount', '4', '2', '2', NULL, NULL, NULL, NULL),
('CustomerAccount', '4', '4', '1', NULL, NULL, NULL, NULL)


DECLARE @Type VARCHAR(50) = 'Account' -- Or Customer, or CustomerAccount

DECLARE @SQLText NVARCHAR(MAX) = ''

SELECT  @SQLText += 'SELECT '

SELECT  @SQLText += ( -- Add in column list, with dynamic column names.
                SELECT  'CONVERT(' + ColDataType + ', Col' + CONVERT(VARCHAR, ColNum) + ') AS [' + ColName + '],'
                FROM    #Names
                WHERE   [Type] = @Type FOR XML PATH('')
            )

SELECT  @SQLText = LEFT(@SQLText, LEN(@SQLText) - 1) + ' ' -- Remove trailing comma

SELECT  @SQLText += 'FROM #Data WHERE [Type] = ''' + @Type + ''''

PRINT   @SQLText
EXEC    sp_executesql @SQLText

Cela renvoie l'instruction SELECT: SELECT CONVERT(INT, Col1) AS [AccountID],CONVERT(VARCHAR(50), Col2) AS [AccountName],CONVERT(DATE, Col3) AS [AccountOpenDate] FROM #Data WHERE [Type] = 'Account'


L'utilisation de SQL dynamique est la bonne réponse, étant donné que la question demandait comment le faire avec SQL. C'était aussi quelque chose que j'avais essayé de faire, mais incorrectement.
Hotchips

Gardez à l'esprit que si vous acceptez les entrées utilisateur et que vous les utilisez pour créer du SQL dynamique, vous devez vraiment, vraiment vous soucier de l'injection SQL et de la désinfection des entrées. bobby-tables.com
Jonathan Van Matre

@JonathanVanMatre Absolument. Heureusement, ce n'est que pour un usage interne, et toutes les entrées sont déjà nettoyées par l'application.
Hotchips

7

Cela semble primordial pour une solution d'affichage frontal. La requête 1 retirerait vos données, la requête 2 retirerait les noms de colonne et le code lorsque vous créez la structure que vous utilisez pour afficher, vous définissez les en-têtes de la deuxième requête.

Bien qu'une méthode SQL pure soit possible, elle sera du SQL dynamique et la maintenance du code serait un cauchemar.

Aussi, vous recherchez probablement sp_executesqlet pas seulement EXECUTE N'Query String'car cela peut résoudre votre problème de commande terminée avec succès.


Je suis d'accord, et je pourrais certainement le faire dans SSRS, mais je ne peux pas le faire dans les autres logiciels de génération de rapports que j'utilise actuellement.
Hotchips
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.