We have a number of stored procedures that are used by BizTalk to fetch n rows from a queue (and a joined table) and update the status of those items at the same time.
I am trying to modify these queries to remove the use of table variables and instead do the work in a single statement. I have succeeded with some, but this particular example is tricky because there is a join
in the CTE, and I want to return some of the joined columns even though they weren't part of the update
.
This is what I have come up with:
;with q as
(
select top (@FetchCount)
iq.InQueueId,
itk.[Message],
iq.PatNo,
iq.DistrictNo,
itk.Interaction,
iq.[Status]
from
InQueue iq
join Itk on iq.InQueueId = itk.InQueueId
join [Endpoint] e on iq.[Endpoint] = e.EndpointId
join EndpointName en on en.EndpointNameId = e.Name
where
en.Name = 'XYZ'
and iq.[Status] = @StatusNew
order by
iq.InQueueId
)
update
q
set
[Status] = @StatusSelected
output
inserted.InQueueId as [Id],
inserted.[Message] as [Msg],
inserted.DistrictNo,
inserted.Interaction
This immediately fails with the following error:
The column reference "inserted.Message" is not allowed because it refers to a base table that is not being modified in this statement.
Clearly this is because the columns Message and Interaction cannot be returned as part of the inserted
set, because they are in a different table and therefore weren't updated.
So I attempted to change the output
clause to:
output
inserted.InQueueId as [Id],
q.[Message] as [Msg],
inserted.DistrictNo,
q.Interaction
This fails with the error:
The multi-part identifier "q.Message" could not be bound.
Is it possible to achieve this without rewriting the query to use either temporary tables or table variables?
Specifies a temporary named result set, known as a common table expression (CTE). This is derived from a simple query and defined within the execution scope of a single SELECT, INSERT, UPDATE, DELETE or MERGE statement. This clause can also be used in a CREATE VIEW statement as part of its defining SELECT statement.
In Oracle 10g you can just use the UPDATE part of the MERGE statement. This worked very well since I am able to use the Subquery. in the USING clause and it essentially works as a Common Table Expression.
After you define your WITH clause with the CTEs, you can then reference the CTEs as you would refer any other table. However, you can refer a CTE only within the execution scope of the statement that immediately follows the WITH clause.
You can use the deleted
set in the output clause to reference columns in your CTE in tables that are not updated
e.g.
output
inserted.InQueueId as [Id],
deleted.[Message] as [Msg],
inserted.DistrictNo,
deleted.Interaction
The deleted
and inserted
sets in an update
could also be thought of as before and after, although the terminology here matches delete...output
and insert...output
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With