Обновление таблицы на основе запроса Select в хранимой процедуре / ColdFusion - PullRequest
0 голосов
/ 26 августа 2009

Я использую ColdFusion for для проекта и у меня есть письменный запрос, который, я думаю, может быть быстрее с использованием хранимой процедуры, но я не специалист по T-SQL, поэтому я не уверен, как это сделать для сравнения.

Я выполняю начальный запрос, который выбирает несколько полей из таблицы на основе динамически созданного cfquery. Я думаю, что знаю, как преобразовать этот запрос в хранимую процедуру SQL Server.

Однако сразу после этого я беру все идентификаторы первичного ключа из этого запроса и запускаю другой запрос к отдельной таблице, которая «блокирует» записи с этими идентификаторами. Блокировка - это битовое поле (флаг) во второй таблице, которая сообщает системе, что эта запись «извлечена». Я завернул оба запроса в cftransaction, чтобы они выполнялись как единое целое.

Обзор кода:

<cftransaction>
   <cfquery name="selectQuery">
      SELECT id, field2, field3
      FROM table1
      WHERE (bunch of conditions here)
   </cfquery>

   <cfquery name="updateQuery">
      UPDATE table2
      SET lockField = 1
      WHERE table2.id IN (#ValueList(selectQuery.id#)
   </cfquery>
</cftransaction>

Затем я возвращаю набор результатов selectQuery в мое приложение, которое использует его для вывода некоторых данных. Как бы я выполнил то же самое в одной хранимой процедуре SQL Server 2008, которую я мог бы вызвать с помощью cfstoredproc?

Опять же, я думаю, что собственный способ CF (с cfquery) не так эффективен, как хранимая процедура, поскольку мне нужно извлечь набор результатов обратно в CF, а затем вызвать другой запрос обратно в БД. Одна хранимая процедура делает все в БД, а затем возвращает исходный набор результатов запроса для использования.

Есть идеи?

Ответы [ 4 ]

1 голос
/ 26 августа 2009

Ваша проблема "куча условий здесь". Эти условия всегда статичны? Так это всегда: (FOO = @x AND BAR = @y)? Или это условно, когда иногда FOO вообще не существует как условие?

Если FOO присутствует не всегда, значит, у вас проблема с сохраненным процессом. T-SQL не может выполнять динамическое построение запросов, фактически даже допуская, что это как бы сводит на нет смысл процедуры, которая заключается в компиляции и предварительной оптимизации SQL. Конечно, вы МОЖЕТЕ сделать это, но в итоге вам просто нужно создать строку SQL внутри тела proc и затем выполнить ее в конце. Вам гораздо лучше использовать CFQuery с cfqueryparams. На самом деле вы рассматривали это вместо этого?

   <cfquery name="updateQuery">
      UPDATE table2
      SET lockField = 1
      WHERE table2.id IN (SELECT id
                          FROM table1
                          WHERE (bunch of conditions here))
   </cfquery>
1 голос
/ 27 августа 2009

Вы можете добавить предложение OUTPUT в инструкцию UPDATE, чтобы захватить идентификаторы обновленных записей и вставить их в таблицу переменных / временных таблиц. Затем вернитесь к таблице 1, чтобы вернуть набор результатов.

DECLARE @UpdatedRecords TABLE ( ID INT )

UPDATE  t2
SET     t2.lockField = 1
OUTPUT  Inserted.ID INTO @UpdatedRecords ( ID )
FROM    table2 t2 INNER JOIN table1 t1  ON t2.id = t1.id
WHERE   (bunch of conditions for table1 here)

SELECT  t1.id, t1.field2, t1.field3
FROM    table1 t1 INNER JOIN @UpdatedRecords u ON t1.id = u.id

Имейте в виду, что если таблица1 находится в постоянном потоке, другие значения ("field2" и "field3") не гарантируются такими, какими они были, когда произошло ОБНОВЛЕНИЕ. Но я думаю, что ваш нынешний метод также подвержен этой проблеме.

0 голосов
/ 17 марта 2015

Нет необходимости в SPROC.

UPDATE table2
SET table2.lockField = 1
FROM table1 
WHERE table1.id = table2.id
  AND table1.field2 = <cfqueryparam ....> 
  AND table1.field3 = <cfqueryparam ....>
0 голосов
/ 26 августа 2009

Вы можете выполнить обновление в одном запросе, сделав свой первый запрос подзапросом, а затем используя отдельный оператор для возврата результатов. Все это может быть одна хранимая процедура:

  CREATE PROCEDURE myUpdate
      @Variable [datatype], etc...
  AS
  BEGIN
    UPDATE table2
    SET lockField = 1
    WHERE table2.id IN (
        SELECT id
        FROM table1
        WHERE (bunch of conditions here)
    )
    SELECT id, field2, field3
    FROM table1
    WHERE (bunch of conditions here)
  END

Возможно, вам придется передать некоторые параметры, но это основная структура хранимой процедуры. Тогда вы можете позвонить из ColdFusion так:

<cfstoredproc procedure="myUpdate">
    <cfprocparam type="[CF SQL Type]" value="[CF Variable]">
    etc...
    <cfprocresult name="selectQuery" resultSet="1">
</cfstoredproc>

Вы можете использовать эти результаты запроса так же, как и раньше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...