У меня есть хранимая процедура, которая изменяет пользовательские данные определенным образом. Я передаю его user_id, и он делает свое дело. Я хочу выполнить запрос к таблице, а затем для каждого user_id, который я нашел, запустить хранимую процедуру один раз для этого user_id
Как бы я написал запрос для этого?
sql
sql-server
stored-procedures
MetaGuru
источник
источник
Ответы:
использовать курсор
ADDENDUM: [пример курсора MS SQL]
в MS SQL, вот пример статьи
обратите внимание, что курсоры медленнее, чем операции на основе множеств, но быстрее, чем ручные циклы while; более подробно в этом вопросе
ДОБАВЛЕНИЕ 2: если вы будете обрабатывать не только несколько записей, сначала перетащите их в временную таблицу и наведите курсор на временную таблицу; это предотвратит эскалацию SQL в блокировки таблиц и ускорит работу
ДОБАВЛЕНИЕ 3: и, конечно, если вы можете встроить то, что ваша хранимая процедура делает с каждым идентификатором пользователя, и выполнить все это как отдельный оператор обновления SQL, это было бы оптимальным
источник
попробуйте изменить свой метод, если вам нужно зациклить!
в родительской хранимой процедуре создайте таблицу #temp, содержащую данные, которые необходимо обработать. При вызове дочерней хранимой процедуры таблица #temp будет видна, и вы сможете ее обработать, надеясь работать со всем набором данных и без курсора или цикла.
это действительно зависит от того, что делает эта дочерняя хранимая процедура. Если вы ОБНОВЛЯЕТЕСЬ, вы можете «обновлять» из объединения в таблицу #temp и выполнять всю работу в одном операторе без цикла. То же самое можно сделать для INSERT и DELETE. Если вам нужно сделать несколько обновлений с IF, вы можете преобразовать их в несколько
UPDATE FROM
с помощью таблицы #temp и использовать операторы CASE или условия WHERE.При работе с базой данных старайтесь не думать о цикле, это приводит к реальной потере производительности, вызывает блокировку / блокировку и замедляет обработку. Если вы будете выполнять циклы везде, ваша система будет плохо масштабироваться, и будет очень сложно ускорить ее, когда пользователи начнут жаловаться на медленное обновление.
Опубликуйте содержание этой процедуры, которую вы хотите вызвать, в цикле, и я поставлю 9 из 10 раз, вы можете написать ее для работы с набором строк.
источник
Что-то вроде этой замены понадобится для ваших таблиц и имен полей.
источник
Вы можете сделать это с помощью динамического запроса.
источник
Разве это не может быть сделано с помощью определяемой пользователем функции для репликации того, что делает ваша хранимая процедура?
где udfMyFunction - это созданная вами функция, которая принимает идентификатор пользователя и выполняет с ним все, что вам нужно.
Смотрите http://www.sqlteam.com/article/user-defined-functions, чтобы узнать больше
Я согласен, что курсоров действительно следует избегать, где это возможно. И это обычно возможно!
(конечно, мой ответ предполагает, что вы заинтересованы только в получении выходных данных от SP и что вы не изменяете фактические данные. Я считаю, что «пользовательские данные изменяются определенным образом», немного двусмысленно по сравнению с первоначальным вопросом, так думал, что предложу это как возможное решение. Совершенно зависит от того, что вы делаете!)
источник
Используйте переменную таблицы или временную таблицу.
Как уже упоминалось ранее, курсор является последним средством. Главным образом потому, что он использует много ресурсов, блокирует проблемы и может быть признаком того, что вы просто не понимаете, как правильно использовать SQL.
Создайте переменную таблицы следующим образом (если вы работаете с большим количеством данных или у вас недостаточно памяти, используйте вместо этого временную таблицу ):
Это
id
важно.Замените
parent
иchild
некоторыми хорошими данными, например, соответствующими идентификаторами или целым набором данных для обработки.Вставьте данные в таблицу, например:
Объявите некоторые переменные:
И, наконец, создайте цикл while для данных в таблице:
Первый выбор извлекает данные из временной таблицы. Второй выбор обновляет @id.
MIN
возвращает ноль, если строки не были выбраны.Альтернативный подход состоит в том, чтобы выполнить цикл, пока в таблице есть строки,
SELECT TOP 1
и удалить выбранную строку из временной таблицы:источник
Мне нравится способ динамических запросов Дейва Ринкона, так как он не использует курсоры, он небольшой и простой. Спасибо, Дейв, за то, что поделился.
Но для моих нужд в Azure SQL и с «отличным» в запросе мне пришлось изменить код следующим образом:
Я надеюсь, что это поможет кому-то...
источник