Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
Sergey Kasatkin Member Откуда: Новосибирск Сообщений: 44 |
Пусть есть ХП. В ней определены какие-то переменные. Далее в ней выполняем через 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 ? |
24 янв 19, 13:53 [21793328] Ответить | Цитировать Сообщить модератору |
Гавриленко Сергей Алексеевич Member Откуда: Moscow Сообщений: 37155 |
DECLARE @id int SET @id = 5 exec sp_executesql N'SELECT * FROM table WHERE id = @id', '@id int', @id |
||||
24 янв 19, 13:59 [21793341] Ответить | Цитировать Сообщить модератору |
zby Member Откуда: Мск Сообщений: 53 |
Sergey Kasatkin, Для этого используют sp_ExecuteSql |
24 янв 19, 14:00 [21793343] Ответить | Цитировать Сообщить модератору |
iap Member Откуда: Москва Сообщений: 47052 |
А вот вернуть наверх значение - это да, только через OUTPUT-параметры sp_executesql |
||
24 янв 19, 14:12 [21793365] Ответить | Цитировать Сообщить модератору |
Sergey Kasatkin Member Откуда: Новосибирск Сообщений: 44 |
Спасибо всем ответившим, теперь понял. Попутно вопрос, если можно. Верно ли я знаю/помню, что использование запроса в виде SELECT * FROM table WHERE id = @id более эффективно (понятно, что для разных случаев мы передаём разные значения @id), нежели выполнение запроса SELECT * FROM table WHERE id = 5 когда на место 5 мы подставляем (динамическим формированием текста SQL-запроса) разные значения? Например, эффективнее тем, что при построении плана запроса в первом случае учитывается, что вот тут будет изменяемое значение, что ускорит использование этого плана запроса для последующих запросов? У меня есть какое-то воспоминание, что способ с явным указанием переменных рекомендовался как более эффективный. Но либо память подводит, либо уже всё давно не так. Хотелось бы уточнить. |
24 янв 19, 14:50 [21793412] Ответить | Цитировать Сообщить модератору |
Владислав Колосов Member Откуда: Сообщений: 8353 |
Sergey Kasatkin, Емнип не более эффективно, но создается прецедент прослушивания параметров (в зависимости от настроек параметризации для базы), в результате которого план запроса может быть использован повторно. При указании скаляров будет закеширован новый план для каждого значения. |
24 янв 19, 16:40 [21793620] Ответить | Цитировать Сообщить модератору |
Yasha123 Member Откуда: Сообщений: 1957 |
вообще-то у него не параметры, а переменные. ибо даже если внутри процедуры написано DECLARE @id int SET @id = 5 SELECT * FROM table WHERE id = @id -- так работает то это все равно переменная, а не параметр. переменные не прослушиваются. поэтому как раз в случае переменных не используется статистика. зато если влепить константу, то как раз используется, так что план, скорее всего, будет оптимальным. будет ли ТС использовать sp_executesql, еще вопрос. но если будет, то вот тогда да, сработает прослушивание. правда, всего лишь в первое выполнение |
||
24 янв 19, 17:12 [21793661] Ответить | Цитировать Сообщить модератору |
Dzianis Member Откуда: Сообщений: 80 |
статистика все таки используется, только не в полном объеме. (если мы говорим про запрос в принципе, а не конкретный текст select * from вверху) |
||
24 янв 19, 18:27 [21793735] Ответить | Цитировать Сообщить модератору |
Yasha123 Member Откуда: Сообщений: 1957 |
это типа как? 1/3 статистики или 1/10? --- в случае переменной при отсутствии option(recompile) используется стандартная оценка в % от числа строк таблицы. никакая колоночная статистика не используется |
||||
24 янв 19, 18:37 [21793738] Ответить | Цитировать Сообщить модератору |
Владислав Колосов Member Откуда: Сообщений: 8353 |
Yasha123, я же правильно понимаю, что при указании переменной без rebuild выполняется оптимизация for unknown? |
24 янв 19, 18:37 [21793739] Ответить | Цитировать Сообщить модератору |
Владислав Колосов Member Откуда: Сообщений: 8353 |
recompile, конечно же. Ребилдил таблицы, прицепилось ![]() |
24 янв 19, 18:39 [21793740] Ответить | Цитировать Сообщить модератору |
Dzianis Member Откуда: Сообщений: 80 |
оценка в % от числа строк таблицы - это то же статистика то ) |
||
1 фев 19, 18:13 [21800022] Ответить | Цитировать Сообщить модератору |
Yasha123 Member Откуда: Сообщений: 1957 |
Dzianis, да надо же. оценка "верну одну треть таблицы вне зависимости от числа строк" статистикой и близко не пахнет. это эмпирическая оценка |
1 фев 19, 19:00 [21800070] Ответить | Цитировать Сообщить модератору |
Mind Member Откуда: Лучший город на Земле Сообщений: 2322 |
Так что оценка по DENSITY конечно не идеальная, но не так уж плоха. Использование константы несомненно лучше, но 100 тысяч одинаковых запросов с разными значениями сожрут кучу памяти и процессорного времени на перекомпиляцию. |
||
5 фев 19, 05:04 [21801656] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |