#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)
Обратите внимание, что сам запрос должен быть динамическим