Як я можу динамічно створювати псевдоніми стовпців?


10

У мене є таблиця (не розроблена мною), яка містить 20 змінних стовпців. Тобто, залежно від того, який тип запису ви дивитесь, відповідна назва стовпця може змінюватися.

Можливі назви стовпців зберігаються в іншій таблиці, до якої я можу дуже легко запитувати.

Тому запит, який я справді шукаю, йде приблизно так:

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

Очевидно, що це не працює, тож як я можу отримати подібний результат?

" Я спробував створити рядок запиту та виконувати EXECUTEйого, але це просто повертає" Команди (и) завершені успішно "і, здається, не повертає набір рядків. Виявляється, я використовував неправильний запит для побудови динамічного SQL і як такий побудував порожню рядок. SQL Server, безумовно, правильно виконав порожню рядок.

Зауважте, що причиною того, що мені потрібно це зробити, а не просто жорстким кодуванням імен стовпців, є те, що імена стовпців можна налаштувати користувачем.


1
Що станеться, якщо ви надрукуєте рядок запиту, скопіюйте / вставте у нове вікно запиту та виконайте його там?
DenisT

"Користувацьке налаштування" означає, що існує сотні чи тисячі типів та / або псевдоніми, які часто змінюються? Якщо псевдоніми досить стабільні, я рекомендую створити ряд переглядів.
Йон усіх торгів

@DenisT, він нічого не виводить, що, можливо, вказує на те, що ще щось не так. Дякую за ведучий.
Hotchips

@JonofAllTrades На жаль, хоча вони досить стабільні, це дуже велика частина специфікації, що коли користувач щось змінює в програмному забезпеченні, ця річ також повинна змінюватися у звітах.
Hotchips

@DenisT Виявляється, мої підзапити, які використовувались для побудови динамічного SQL, були невірними та повернули нульові набори. Так SQL Server повернув порожній запит, який він належним чином успішно виконав. Дякуємо, що вказали на команду PRINT.
Hotchips

Відповіді:


12

Спробуйте наступний код:

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

Це повертає оператор SELECT: SELECT CONVERT(INT, Col1) AS [AccountID],CONVERT(VARCHAR(50), Col2) AS [AccountName],CONVERT(DATE, Col3) AS [AccountOpenDate] FROM #Data WHERE [Type] = 'Account'


Використання динамічного SQL є правильною відповіддю, враховуючи, що в запитанні було задано, як це зробити з SQL. Це також я намагався зробити, але неправильно.
Hotchips

Майте на увазі, що якщо ви приймаєте введення користувача та використовуєте його для створення динамічного SQL, то вам дійсно потрібно потурбуватися про введення SQL та санітарію входів. bobby-tables.com
Джонатан Ван Матре

@JonathanVanMatre Абсолютно. На щастя, це лише для внутрішнього використання, і всі входи вже додатково саніровані додатком.
Hotchips

7

Це звучить чудово для рішення переднього дисплея. Запит 1 поверне ваші дані, запит 2 буде відкликати імена стовпців і код, коли ви будуєте будь-яку структуру, яку ви використовуєте для відображення, ви встановлюєте заголовки з другого запиту.

Незважаючи на те, що можливий чистий метод SQL, це буде динамічним SQL, а кодовий зв'язок - це кошмар.

Також, ймовірно, ви шукаєте sp_executesqlі не тільки EXECUTE N'Query String'так, що може вирішити вашу проблему команд успішно завершено.


Я погоджуюся, і я могла це точно зробити в SSRS, але я не можу це зробити в іншому програмному звіті, яке я використовую на даний момент.
Hotchips
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.