web-dev-qa-db-fra.com

Comment puis-je dynamiquement alias des colonnes?

J'ai une table (non conçue par moi) qui a 20 colonnes à noms variables. 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 EXECUTEing, mais cela retourne juste "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.

10
Hotchips

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'

12
garthmillar

Cela semble primordial pour une solution d'affichage frontal. La requête 1 retirerait vos données, la requête 2 retirerait les noms des colonnes 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.

Vous cherchez probablement aussi sp_executesql et pas seulement EXECUTE N'Query String' car cela peut résoudre votre problème de commande terminée avec succès.

7
RubberChickenLeader