powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Контекст исполнения Exec() и доступ из него ко внешним переменным
14 сообщений из 14, страница 1 из 1
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764283
Sergey Kasatkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пусть есть ХП.
В ней определены какие-то переменные.
Далее в ней выполняем через EXEC() некий SQL-запрос.

Вопрос: почему при этом если в текст этого запроса включить переменные, определённые в ХП, то возникает ошибка "переменная не определена"?

В то же время, если внутри ХП вписать текст запроса с использованием этой же переменной - то всё отлично рабтает?

Видимо запрос из EXEC() выполняется "в другом контексте", где не видны локальные переменные. но где это описано в справке? не могу найти.
И есть ли способ значения "внешних" по отношению к тексту запроса внутри EXEC() использовать в этом запросе?

Пример о чем речь:

DECLARE @id int
SET @id = 5

SELECT * FROM table WHERE id = @id -- так работает

EXEC('SELECT * FROM table WHERE id = @id') -- а так не работает, "неизвестная переменная @id", почему?

Если ли способ внутри запроса EXEC() увидеть @id ?
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764294
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sergey Kasatkin почему при этом если в текст этого запроса включить переменные, определённые в ХП, то возникает ошибка "переменная не определена"?Потому что у переменных есть документированная область видимости.

Sergey KasatkinЕсли ли способ внутри запроса EXEC() увидеть @id ?
Код: sql
1.
2.
3.
4.
DECLARE @id int
SET @id = 5

exec sp_executesql N'SELECT * FROM table WHERE id = @id', '@id int', @id
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764296
zby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sergey Kasatkin,

Для этого используют sp_ExecuteSql
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764314
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zbySergey Kasatkin,

Для этого используют sp_ExecuteSqlМожно сформировать строку запроса @sql с использованием переменных и выполнить запрос EXEC(@sql) без всякой процедуры.
А вот вернуть наверх значение - это да, только через OUTPUT-параметры sp_executesql
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764355
Sergey Kasatkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо всем ответившим, теперь понял.

Попутно вопрос, если можно.

Верно ли я знаю/помню, что использование запроса в виде
Код: sql
1.
SELECT * FROM table WHERE id = @id


более эффективно (понятно, что для разных случаев мы передаём разные значения @id),
нежели выполнение запроса
Код: sql
1.
SELECT * FROM table WHERE id = 5


когда на место 5 мы подставляем (динамическим формированием текста SQL-запроса) разные значения?

Например, эффективнее тем, что при построении плана запроса в первом случае учитывается, что вот тут будет изменяемое значение, что ускорит использование этого плана запроса для последующих запросов?

У меня есть какое-то воспоминание, что способ с явным указанием переменных рекомендовался как более эффективный.
Но либо память подводит, либо уже всё давно не так.
Хотелось бы уточнить.
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764513
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sergey Kasatkin,

Емнип не более эффективно, но создается прецедент прослушивания параметров (в зависимости от настроек параметризации для базы), в результате которого план запроса может быть использован повторно. При указании скаляров будет закеширован новый план для каждого значения.
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764551
Фотография Yasha123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владислав КолосовЕмнип не более эффективно, но создается прецедент прослушивания параметров
вообще-то у него не параметры, а переменные.
ибо даже если внутри процедуры написано
Код: sql
1.
2.
3.
4.
DECLARE @id int
SET @id = 5

SELECT * FROM table WHERE id = @id -- так работает


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

будет ли ТС использовать sp_executesql, еще вопрос.
но если будет, то вот тогда да, сработает прослушивание.
правда, всего лишь в первое выполнение
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764601
Dzianis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Yasha123поэтому как раз в случае переменных не используется статистика.
зато если влепить константу, то как раз используется, так что план, скорее всего,
будет оптимальным.


статистика все таки используется, только не в полном объеме.
(если мы говорим про запрос в принципе, а не конкретный текст select * from вверху)
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764604
Фотография Yasha123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DzianisYasha123поэтому как раз в случае переменных не используется статистика.
зато если влепить константу, то как раз используется, так что план, скорее всего,
будет оптимальным.


статистика все таки используется, только не в полном объеме.
(если мы говорим про запрос в принципе, а не конкретный текст select * from вверху)
это типа как?
1/3 статистики или 1/10?
---
в случае переменной при отсутствии option(recompile)
используется стандартная оценка в % от числа строк таблицы.
никакая колоночная статистика не используется
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764605
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yasha123,

я же правильно понимаю, что при указании переменной без rebuild выполняется оптимизация for unknown?
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39764606
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
recompile, конечно же. Ребилдил таблицы, прицепилось
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39768427
Dzianis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Yasha123в случае переменной при отсутствии option(recompile)
используется стандартная оценка в % от числа строк таблицы.
никакая колоночная статистика не используется

оценка в % от числа строк таблицы - это то же статистика то )
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39768454
Фотография Yasha123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dzianis,
да надо же.
оценка "верну одну треть таблицы вне зависимости от числа строк" статистикой и близко не пахнет.
это эмпирическая оценка
...
Рейтинг: 0 / 0
Контекст исполнения Exec() и доступ из него ко внешним переменным
    #39769451
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yasha123Dzianis,
да надо же.
оценка "верну одну треть таблицы вне зависимости от числа строк" статистикой и близко не пахнет.
это эмпирическая оценкаКонечно значение переменной не известно и поэтому гистограмма статистики не используется, но зато используется DENSITY_VECTOR, и не надо говорить что это не часть статистики. Если сделать условие на равенство для достаточно равномерно распределенных значений, то количество ожидаемых строк будет достаточно точным. В случае же если значения неравномерно распределены, то прослушивание паматров и использование реальных значений статистики будет работать хорошо только до тех пор пока случайно не скомпилируется план с "нестандартным" значением и тогда это может оказаться еще хуже, чем использование оценки по DENSITY. Варианты решения в такой ситуации либо OPTION(RECOMPILE), что будет работать в любом случае, хоть переменная, хоть параметр, либо OPTIMIZE(FOR UNKNOWN) что абсолютно тоже самое что и переменная.

Так что оценка по DENSITY конечно не идеальная, но не так уж плоха. Использование константы несомненно лучше, но 100 тысяч одинаковых запросов с разными значениями сожрут кучу памяти и процессорного времени на перекомпиляцию.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Контекст исполнения Exec() и доступ из него ко внешним переменным
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]