Краткая история:
Я пишу хранимую процедуру для поддержки устаревшей системы отчетов (с использованием SQL Server Reporting Services 2000) в устаревшем веб-приложении.
В соответствии с исходным стилем реализации каждый отчет имеет отдельную хранимую процедуру в базе данных, которая выполняет все запросы, необходимые для возврата «окончательного» набора данных, который может быть просто воспроизведен сервером отчетов.
В связи с бизнес-требованиями этого отчета возвращенный набор данных имеет неизвестное количество столбцов (это зависит от пользователя, который выполняет отчет, но может иметь 4-30 столбцов).
На протяжении всей хранимой процедуры я сохраняю столбец UserID, чтобы отслеживать идентификатор пользователя для выполнения дополнительных запросов. В конце, однако, я делаю что-то вроде этого:
UPDATE #result
SET Name = ppl.LastName + ', ' + ppl.FirstName
FROM #result r
LEFT JOIN Users u ON u.id = r.userID
LEFT JOIN People ppl ON ppl.id = u.PersonID
ALTER TABLE #result
DROP COLUMN [UserID]
SELECT * FROM #result r ORDER BY Name
По сути, я установил для столбца Имя varchar (который ранее оставался пустым, пока выполнял некоторую логику поворота) желаемый формат имени в виде простого текста.
Когда закончите, я хочу удалить столбец UserID, так как пользователь отчета не должен видеть это.
Наконец, возвращенный набор данных имеет один столбец для имени пользователя и произвольное количество столбцов INT с суммарными показателями производительности. По этой причине я не могу просто исключить столбец UserID, поскольку SQL не поддерживает «SELECT * EXCEPT [UserID]» или тому подобное.
С этим известным (любые указатели стилей приветствуются, но не являются центральными для этой проблемы), вот проблема:
Когда я выполняю эту хранимую процедуру, я получаю ошибку выполнения:
Invalid column name 'userID'.
Однако, если я закомментирую свой оператор DROP COLUMN и сохраню идентификатор пользователя, хранимая процедура будет работать правильно.
Что происходит? Конечно, похоже, что операторы выполняются не по порядку и отбрасывают столбец, прежде чем я смогу использовать его для установки строк имен!
[Редактировать 1]
Я определил UserID ранее (вся хранимая процедура содержит около 200 лож, в основном не относящихся к делу логики, поэтому я вставлю фрагменты:
CREATE TABLE #result ([Name] NVARCHAR(256), [UserID] INT);
Чувствительность к регистру не проблема, но он указал мне на правильную линию - было одно место, где у меня был идентификатор пользователя вместо идентификатора пользователя. Теперь, когда я исправил случай, сообщение об ошибке жалуется на UserID.
Моя «испорченная» хранимая процедура также работает должным образом в SQL Server 2008 - это либо ошибка 2000 года, либо я совершенно не понимаю, как работал SQL Server.
Спасибо всем за участие!
Для тех, кто ищет это в будущем, я добавил чрезвычайно грубый обходной путь, чтобы быть 2000-совместимым, пока мы не обновим нашу рабочую версию:
DECLARE @workaroundTableName NVARCHAR(256), @workaroundQuery NVARCHAR(2000)
SET @workaroundQuery = 'SELECT [Name]';
DECLARE cur_workaround CURSOR FOR
SELECT COLUMN_NAME FROM [tempdb].INFORMATION_SCHEMA.Columns WHERE TABLE_NAME LIKE '#result%' AND COLUMN_NAME <> 'UserID'
OPEN cur_workaround;
FETCH NEXT FROM cur_workaround INTO @workaroundTableName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @workaroundQuery = @workaroundQuery + ',[' + @workaroundTableName + ']'
FETCH NEXT FROM cur_workaround INTO @workaroundTableName
END
CLOSE cur_workaround;
DEALLOCATE cur_workaround;
SET @workaroundQuery = @workaroundQuery + ' FROM #result ORDER BY Name ASC'
EXEC(@workaroundQuery);
Спасибо всем!