Wie kann ich Spalten dynamisch aliasen?

10

Ich habe eine Tabelle (nicht von mir entworfen) mit 20 variabel benannten Spalten. Das heißt, je nachdem, welche Art von Datensatz Sie betrachten, kann sich der zutreffende Name der Spalte ändern.

Die möglichen Spaltennamen werden in einer anderen Tabelle gespeichert, die ich sehr einfach abfragen kann.

Daher lautet die Abfrage, nach der ich wirklich suche, ungefähr so:

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

Das funktioniert natürlich nicht. Wie kann ich also ein ähnliches Ergebnis erzielen?

' Ich habe versucht EXECUTE, eine Abfragezeichenfolge zu erstellen und zu erstellen, aber das gibt nur "Befehl (e) erfolgreich abgeschlossen" zurück und scheint kein Rowset zurückzugeben. Es stellte sich heraus, dass ich eine falsche Abfrage verwendet habe, um das dynamische SQL zu erstellen, und als solche eine leere Zeichenfolge erstellt habe. SQL Server hat die leere Zeichenfolge definitiv korrekt ausgeführt.

Beachten Sie, dass der Grund dafür, dass dies auftritt, anstatt nur die Spaltennamen fest zu codieren, darin besteht, dass die Spaltennamen vom Benutzer konfigurierbar sind.

Hotchips
quelle
1
Was passiert, wenn Sie die Abfragezeichenfolge DRUCKEN, in ein neues Abfragefenster kopieren / einfügen und dort ausführen?
DenisT
"Vom Benutzer konfigurierbar" bedeutet, dass Hunderte oder Tausende von Typen und / oder Aliasnamen häufig geändert werden? Wenn die Aliase ziemlich stabil sind, würde ich empfehlen, eine Reihe von Ansichten zu erstellen.
Jon of All Trades
@DenisT, es wird nichts ausgegeben, was möglicherweise darauf hinweist, dass auch etwas anderes nicht stimmt. Danke für die Führung.
Hotchips
@ JonofAllTrades Obwohl sie ziemlich stabil sind, ist es leider ein wesentlicher Teil der Spezifikation, dass sich das Ding auch in den Berichten ändern muss, wenn der Benutzer etwas in der Software ändert.
Hotchips
@DenisT Es stellt sich heraus, dass meine zum Erstellen des dynamischen SQL verwendeten Unterabfragen falsch waren und Nullmengen zurückgaben. Daher hat SQL Server eine leere Abfrage zurückgegeben, die ordnungsgemäß erfolgreich ausgeführt wurde. Vielen Dank, dass Sie auf den Befehl PRINT hingewiesen haben.
Hotchips

Antworten:

12

Versuchen Sie den folgenden Code:

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

Dies gibt die SELECT-Anweisung zurück: SELECT CONVERT(INT, Col1) AS [AccountID],CONVERT(VARCHAR(50), Col2) AS [AccountName],CONVERT(DATE, Col3) AS [AccountOpenDate] FROM #Data WHERE [Type] = 'Account'

garthmillar
quelle
Die Verwendung von dynamischem SQL ist die richtige Antwort, da in der Frage gefragt wurde, wie dies mit SQL geschehen soll. Es war auch etwas, was ich versucht hatte, aber falsch.
Hotchips
Denken Sie daran, dass Sie sich wirklich, wirklich Gedanken über die SQL-Injektion und die Bereinigung von Eingaben machen müssen , wenn Sie Benutzereingaben akzeptieren und diese zum Erstellen von dynamischem SQL verwenden . bobby-tables.com
Jonathan Van Matre
@ JonathanVanMatre Auf jeden Fall. Glücklicherweise ist dies nur für den internen Gebrauch und alle Eingaben werden bereits von der App bereinigt.
Hotchips
7

Dies klingt für eine Front-End-Display-Lösung am besten. Abfrage 1 würde Ihre Daten zurückziehen, Abfrage 2 würde die Spaltennamen zurückziehen und im Code, wenn Sie die Struktur erstellen, die Sie zur Anzeige verwenden, die Überschriften aus der zweiten Abfrage festlegen.

Während eine Pure SQL-Methode möglich sein kann, handelt es sich um dynamisches SQL, und die Codepflege wäre ein Albtraum.

Auch Sie suchen wahrscheinlich sp_executesqlund nicht nur EXECUTE N'Query String'das kann Ihr Problem des Befehls erfolgreich abgeschlossen beheben.

RubberChickenLeader
quelle
Ich stimme zu, und ich könnte dies definitiv in SSRS tun, aber ich kann es nicht in der anderen Berichtssoftware tun, die ich gerade verwende.
Hotchips