среда, 11 апреля 2012 г.

[prog] Открыл для себя команду OUTPUT в T-SQL

Как-то так сложилось, что с реляционными БД дело приходилось иметь не часто и не серьезно. Поэтому знания SQL у меня самые поверхностные и общие. Посему прошу опытных людей сильно надо мной не смеяться, полагаю, что для многих из вас то, что я расскажу ниже давно знакомо.

Если мне приходится работать с РСУБД, то довольной распространенной операцией является такая – поднять N строк из какой-то таблицы по какому-то условию, затем для этих N строк обновить столбец, который хранит дату и время обработки строки.

Пользуясь обычным SQL эта операция выполняется так: сначала выбирается N строк, на затем выполняется UPDATE. Причем, второй шаг можно делать по разному. Можно тупо в цикле для каждой строки вызывать UPDATE, а можно сначала ключи обновляемых строк поместить во вспомогательную временную таблицу, после чего запустить один UPDATE (этот подход, по моим наблюдениям, обычно работает быстрее, по крайней мере, в условиях работы с MSSQL через ODBC.).

Но недавно таки заглянул в MS-овскую документацию по T-SQL и обнаружил там интересную штуку, которая изрядно облегчает жизнь и ускоряет работу с БД – это команда OUTPUT, которая может использоваться внутри T-SQL-ых SELECT, INSERT, UPDATE и DELETE.

С ее помощью приведенный выше пример с выборкой и обновлением метки времени вырождается в более эффективную последовательность действий: сначала вызывается UPDATE для N первых строк, удовлетворяющих нужному условию, а в секции OUTPUT этого UPDATE предписывается поместить содержимое нужных мне столбцов измененных строк во временную таблицу. После чего делается простой SELECT из временной таблицы. Что-то вроде:

UPDATE TOP(N)
  SET processed_at = GETDATE()
  OUTPUT
       inserted.column_1,
       inserted.column_2,
       ...
       inserted.column_N
    INTO #tmp_table
  WHERE ...;
SELECT * FROM #tmp_table;
TRUNCATE TABLE #tmp_table;

Получается очень удобно, намного удобнее, чем через “обобщенный SQL”. Правда тут происходит более жесткая привязка к конкретной БД. Плюс еще особенности (в частности, порядок следования столбцов в OUTPUT должен в точности соответствовать порядку следования столбцов во временной таблице). Но если нет необходимости поддерживать разные типы БД, то вполне работоспособно.

PS. А еще в T-SQL есть какие-то table variables, с которыми я пока еще не разобрался, руки еще не дошли.

Комментариев нет: