Почему невозможно динамически установить псевдоним столбца?

#sql #sql-server #stored-procedures

#sql #sql-сервер #хранимые процедуры

Вопрос:

У меня есть хранимая процедура, и я хочу передать псевдоним столбца в качестве параметра, что-то вроде:

 SELECT u.userLoginName AS @columnName
FROM -- some JOINs
WHERE -- some conditions
  

где @columnName может быть один из двух параметров, и он устанавливается перед оператором SELECT в соответствии с некоторым условием.
Я уже знаю, что это можно сделать только с помощью динамического SQL, но я не понимаю, почему?

Я знаю, что порядок выполнения запроса таков: FROM и JOINs -> ГДЕ -> GROUP BY и только затем SELECT.

Итак, если на данный момент я уже получил результирующий набор, то есть итоговую таблицу, почему я не могу просто переименовать имя столбца в @columnName ? Что происходит в фоновом режиме, чего я не вижу?

Комментарии:

1. Потому что SQL не является языком сценариев. Это не такой язык, как Powershell, который поддерживает внедрение параметров для представления объектов, имен и т.д. Оператор SQL должен быть четко определен, и вы не можете заменять части запроса, требующие литералов, параметром / переменной. Тот факт, что вы хотите изменить имя столбца (динамически), подразумевает, что здесь у вас проблема xy .

2. Это происходит не только на сервере Microsoft SQL Server, или, более конкретно, на диалекте T-SQL, @DaleK . Другие языки SQL часто не поддерживают замену литералов переменными (я не могу вспомнить ни одного, который бы это делал, но я бы не удивился, что он там есть). Если бы они это сделали, это не соответствовало бы «стандартному поведению».

3. Обратите внимание, что вы можете задать имя столбца динамически с помощью dynamic SQL. Но, если вы просто хотите динамически изменить псевдоним столбца, то это, безусловно, не является задачей для Data Engine и должно быть на вашем уровне представления.

4. Верно ли это и для PostgreSQL?

Ответ №1:

Возможно, это ответ на ваш вопрос.

Результирующий набор SQL концептуально подобен таблице: он имеет четко определенные строки и столбцы и не упорядочен, если не создан с помощью явного order by .

SQL-запрос обрабатывается в два этапа: он компилируется и оптимизируется, затем выполняется. (К счастью, некоторые базы данных теперь также начинают обеспечивать динамическую оптимизацию, но запросы все еще проходят фазу компиляции.)

Вся информация о результирующем наборе должна быть известна на этапе компиляции — и это включает в себя результирующие имена столбцов и типы столбцов. Динамические имена предотвратили бы это. Они будут известны только на этапе выполнения.

Обратите внимание, что это относится и к параметрам в качестве идентификатора. Параметры заменяются в начале фазы выполнения.

Это не является ограничением какой-либо конкретной базы данных. Это применимо ко всем из них. Я подозреваю, что некоторые более современные базы данных реализованы таким образом, который допускал бы более динамическое присвоение имен, но я не знаю ни о каких базах данных, которые действительно реализуют это, кроме как через динамический SQL.

Ответ №2:

Это возможно, но вы должны использовать динамический запрос. Давайте предположим, что у нас есть следующая таблица

 Create table #TBL ([Months] VARCHAR(3), Value INT)
INSERT INTO #TBL values
('Jan',20),('Feb',12),('Jan',15),('Mar',25),
('Feb',18),('Jan',9),('Mar',10),('Jan',19)
GO
  

И я хочу динамически задавать имена столбцов с помощью переменной. Я могу использовать приведенный ниже код

 DECLARE @M VARCHAR(10)='Months',
        @T VARCHAR(10)='Total'
-- Dynamic query to get the column name
DECLARE @qry VARCHAR(MAX)
SET @qry = 'SELECT  [Months] AS ' @M ',
             sum(Value) as ' @T '    
      FROM #TBL
      group by [Months]
      DROP TABLE #TBL'
EXEC (@qry)
  

Обратите внимание, что сам запрос должен быть динамическим