SQL Server 2008: выберите, затем обновите инструкцию

#sql #sql-server-2008

#sql #sql-server-2008

Вопрос:

Я выполняю ВНУТРЕННЕЕ объединение между 6 таблицами для модуля для моего приложения, в основном это берет prostaff, получает их имя и адрес электронной почты и сравнивает это со списком кандидатов на работу.

В mod_employmentAppJobs мне нужно присвоить столбцу для каждой выбранной строки значение true. По сути, это устанавливает флаг, который сообщает sql не выбирать столбец, потому что мы уже отправили электронное письмо этому пользователю. Это битовое поле.

Как мне установить для поля emailSent значение true в инструкции SQL? — К вашему сведению, Coldfusion 8 — это сервер приложений….

 SELECT  *
FROM    pro_Profile p 
        INNER JOIN pro_Email e ON p.profileID = e.profileID
        INNER JOIN mod_userStatus m ON p.profileID = m.profileID 
        <!--- Joins the pro staff profiles to the employment app ---> 
        INNER JOIN mod_employmentAppJobTitles a ON p.profileID = a.departmentID
         <!--- Join Job titles to the jobs ---> 
        INNER JOIN mod_employmentAppJobs b ON a.jobTitleID=b.jobTitleID
        <!--- Joining the table on where the profile equals everything else ---> 
        INNER JOIN mod_employmentAppProfile c ON c.eAppID = b.eAppID 
WHERE   b.emailSent = 'False'
  

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

1. Если это битовое поле, я думаю, вы могли бы установить значение 1 (для true) или 0 (для false).

2. Также вот в чем дело, его необходимо обновить, но ему необходимо вернуть данные после SQL.

3. Ее легче читать, если установлено значение false, и она работает в любом случае.

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

5. Да, Марко. Мне нужно получить данные, затем установите для поля emailSent значение false.

Ответ №1:

У вас есть несколько вариантов.

1) Используйте временную таблицу и сначала выберите данные там, обновите mod_employmentAppJobs и выполните выбор из временной таблицы, чтобы получить ваши данные.

Итак, это будет выглядеть примерно так.

создайте временную таблицу

 CREATE TABLE #tmpTABLE 
(
  EmailAddress varchar(100),
  JobTitle varchar(50),
  JobTitleId bigint 
  ......
)
  

Вставьте в нее

 INSERT INTO #tmpTable
SELECT EmailAddress,JobTitle, ........
    FROM pro_Profile p 
    INNER JOIN pro_Email e 
    ON p.profileID = e.profileID
    INNER JOIN mod_userStatus m 
    ON p.profileID = m.profileID 
    <!--- Joins the pro staff profiles to the employment app ---> 
    INNER JOIN mod_employmentAppJobTitles a
    ON p.profileID = a.departmentID
    INNER JOIN mod_employmentAppJobs b
    <!--- Join Job titles to the jobs ---> 
    ON a.jobTitleID=b.jobTitleID
    <!--- Joining the table on where the profile equals everything else ---> 
    INNER JOIN mod_employmentAppProfile c
    ON c.eAppID = b.eAppID 
    WHERE b.emailSent = 'False'
  

Обновите исходную таблицу (я бы рекомендовал индекс jobTitleId во временной таблице для повышения производительности, если это применимо)

 UPDATE mod_employmentAddJobs
    SET EmailSent="true"
    FROM mod_employmentAppJobs b
      INNER JOIN #tmpTable tmp
    ON b.jobTitleID=tmp.jobTitleID
  

Верните фактические данные обратно на уровень приложения

 SELECT * FROM #tmpTable
  

Для лучшего вкуса я рекомендую добавить BEGIN TRAN…ЗАФИКСИРУЙТЕ…ВЫПОЛНИТЕ ОТКАТ и НАЧНИТЕ TRY ..END TRY НАЧНИТЕ CATCH…ЗАВЕРШИТЕ по вкусу и в соответствии с требованиями бизнеса.

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

2) Вы можете использовать предложение OUTPUT инструкции update.

 UPDATE mod_employmentAddJobs
    SET EmailSent="true"
    FROM pro_Profile p 
    INNER JOIN pro_Email e 
    ON p.profileID = e.profileID
    INNER JOIN mod_userStatus m 
    ON p.profileID = m.profileID 
    <!--- Joins the pro staff profiles to the employment app ---> 
    INNER JOIN mod_employmentAppJobTitles a
    ON p.profileID = a.departmentID
    INNER JOIN mod_employmentAppJobs b
    <!--- Join Job titles to the jobs ---> 
    ON a.jobTitleID=b.jobTitleID
    <!--- Joining the table on where the profile equals everything else ---> 
    INNER JOIN mod_employmentAppProfile c
    ON c.eAppID = b.eAppID 
    WHERE b.emailSent = 'False'
  

Вставлен вывод.*

Это должно вернуть вам результирующий набор обратно на уровень вашего приложения

Ответ №2:

Вы могли бы сохранить результат во временной таблице. Вы можете использовать данные во временной таблице и по-прежнему возвращать их в конце. Это много ввода, но довольно просто:

 -- Select data into temporary table
declare @result table (jobTitleID int, ...)

INSERT  @result
        (jobTitleID, ...)
SELECT  jobTitleID
FROM    pro_Profile p 
...

-- Update unreadMail flag
update  mod_employmentAppJobs 
set     unreadMail = 'False'
where   jobTitleID in (select jobTitleId from @result)

-- Return result to application
select  jobTitleId, ...
from    @result
  

Ответ №3:

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

Ответ №4:

Ну, это всего лишь идея, а не лучшее решение.
Вы могли бы получить данные (для которых бит равен false) в DataReader, а затем выполнить команду, устанавливающую бит в значение true для идентификаторов, содержащихся в Dataset.
Dataset возвращает необходимые данные…

Ответ №5:

Я просто добавил a в конец, и это сработало:

     UPDATE mod_employmentAppJobs
    SET emailSent = 'True'
  

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

1. Но что произойдет, если между запуском инструкции SELECT и выполнением инструкции UPDATE есть вставка? Будут записи, помеченные как TRUE, если они никогда не были возвращены из инструкции SELECT.