Параметр сразу же экранируется в зависимости от типа данных - поэтому возвращается значение «Адрес1», а не фактическое значение для столбца.
Передать имя столбца не как параметр, а как объединенную строку:
DECLARE @sql nvarchar(500)
DECLARE @Param nvarchar(200)
SET @sql = 'select '+ @columnName +' from customer where custId = @custId'
SET @Param = N'@custId int'
EXEC sp_executesql @sql, @Param , @custId = 42
Подробнее о поведении можно прочитать здесь .
Единственная другая альтернатива, о которой я знаю, требует, чтобы вы использовали логику принятия решения для перенаправления на запрос, где имя столбца статически определено:
IF @columname = 'Address1'
BEGIN
SET @sql = 'select Address1 from customer where custId = @custId'
END