Using 3 updates in the same Store Procedure? Small Error
You start the SP with ;WITH RatingLines ...
which connects to the first UPDATE
statement, not the other ones. This construct creates a CTE that is only visible to the first statement that follows it. More explanation can be found in the TN for WITH common_table_expression (Transact-SQL). In particular this excerpt from Remarks highlights this:
A CTE must be followed by a single SELECT, INSERT, UPDATE, MERGE, or DELETE statement that references some or all the CTE columns.
To have this table known for all statements in your SP, create a table variable or a temporary table for the RatingLines
instead.
Outline using a temporary table would be as follows:
Select RDA.[CTS] AS [CTS]
,RDA.[B_KEY] AS [B_KEY]
,RDA.[H_KEY] AS [H_KEY]
,RDA.[RT_ID] AS [RT_ID]
,RDA.[RT_AVGRATING] AS [RT_AVGRATING]
,RDDA.[RTD_COMMENT] AS [RTD_COMMENT]
INTO #RatingLines -- Create #RatingLines as temporary table
From [DynNavHRS].[HRSDB].[HTL_RATING_ALL_DA] RDA
Join [DynNavHRS].[HRSDB].[HTL_RATING_DETAIL_ALL_DA] RDDA
ON RDA.RT_ID =RDDA.RT_ID
AND RDDA.[RTD_COMMENT] <> ''
AND RDA.[B_KEY]='19214642';
-- Throughout the rest of the SP, use #RatingLines as your ratings table; eg:
...
INNER JOIN #RatingLines RL1
...
-- At the end of the SP, drop the temporary table
DROP TABLE #RatingLines;
Temp view in stored procedure is valid only on first UPDATE
Yes Temp view will be invalid because scope of cte is limited to first update statement. So you insert results into temp table. And use it down in procedure where ever you want.
USE [MyDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_MySP]
@passedParam VARCHAR(32)
AS
BEGIN
if object_id('tempdb..#t1') is not null
drop table #t1
SELECT [myTable1].[Id] into #t1
FROM [dbo].[myTable1] LEFT JOIN [dbo].[myTable2] ON [myTable1].Id = [myTable2].[DeviceId]
WHERE
--The temp view is valid here
UPDATE [dbo].[myTable1]
SET [myTable1].[Ready] = 0, [myTable1].[Reason] = NULL
WHERE
[myTable1].[Id] IN (SELECT [Id] FROM #t1)
--The temp view is NO LONGER VALID from this point
UPDATE [dbo].[myTable1]
SET [myTable1].[Reason] = CONCAT([myTable1].[Reason],'Reason 1.')
WHERE
--all kind of conditions
UPDATE [dbo].[myTable1]
SET [myTable1].[Reason] = CONCAT([myTable1].[Reason],'Reason 2.')
WHERE
--all kind of conditions
UPDATE [dbo].[myTable1]
SET [myTable1].[Reason] = CONCAT([myTable1].[Reason],'Reason 3.')
WHERE
--all kind of conditions
UPDATE [dbo].[myTable1]
SET [myTable1].[Reason] = CONCAT([myTable1].[Reason],'Reason 4.')
WHERE
--all kind of conditions
END
UPDATE statement not working in stored procedure; No error & no exception is happening
The UPDATE
statement is working, but updates 0 rows, as shown per your log (Row Updated =0
). This is not an error, your updates evaluate the where clause, finds 0 rows matching, and performs 0 modification. In Oracle, an update that doesn't match any row in the where clause is still a success.
Now why does it happen. Let's take your first update:
UPDATE tblhotel
SET acrooms = acrooms, nacrooms = nacrooms
WHERE date1 = (to_date(date1, 'mm/dd/yyyy'))
AND hotelid = 'hotelid' ;
I think you want to update the row that have the column hotelid
with the value passed as parameter. There are a few problems with that:
- First of all, you're not comparing the column and the parameter, but the column with a constant. Parameters don't use quotes. Constants (VARCHAR2) do.
- Secondly, you shouldn't call a parameter with the same name as your column, this causes confusion and could even cause variable shadowing. I recommend using a prefix that no column whatsoever uses in your schema. One common prefix for parameters is
p_
. - Finally, you don't need conversion functions if your parameter are of the good type (since your parameter
p_date1
is of type date, you don't need theto_date
function).
So if you rename your parameters p_hotelid
and p_date1
, your statement should read:
UPDATE tblhotel
SET acrooms = acrooms, nacrooms = nacrooms
WHERE date1 = p_date1
AND hotelid = p_hotelid;
In this case there is no confusion nor conversion error possible.
On an unrelated note:
- there seems to be a mismatch between your procedure name and the log it generates: no insertion will ever be done by update statements.
- Don't catch
when others
, let the error propagate. PL/SQL will rollback the procedure changes if the error propagates. PL/SQL statements (DML and blocks) are atomic by nature, they either fail completely or succeed entirely.
How to make a SQL UPDATE procedure use more than 1 table in the calculation? Doing so gives me error 1054
Do you just want to refer to new
? If so, I assume you only want to update one row in stock
rather than all of them. You need a where
clause
CREATE DEFINER=`root`@`localhost` TRIGGER reduce_available
AFTER INSERT ON book_customer FOR EACH ROW
BEGIN
UPDATE stock s
SET s.current_amount = s.current_amount - new.amount
WHERE s.book_id = new.book_id;
END;
How can multiple Stored Procedures update same row at same time?
You have to admit, this seems like a highly unusual thing to do. I wonder if it wouldn't be better to update separate tables, and then have a single update statement at the end that would join the individual tables to the final one? (i.e. update a set a.[1] = ... from a inner join b inner join c
etc.).
But, if you want to continue down this path, then just set READ UNCOMMITTED from within each of your stored procedures. That is the best bet.
Stored procedure inserting the same record repeatedly instead of looping through list from SELECT
You have the same problems as another recent post here: Iterate over a table with a non-int id value
- Why do a loop? Just do it as a single SQL statement
- If you must use a loop, you will need to update your @Dealer value at each run (e.g., to the next DealerId) otherwise it will just infinitely loop with the same DealerID value
- Don't do a loop.
Here's an example not needing a loop.
ALTER PROCEDURE [dbo].[P_billing_batch_set]
@varBillingBatchRosterID int
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
INSERT INTO dbo.billing_batch (DealerID, BillingBatchRosterID)
SELECT DISTINCT vi.DealerID, @varBillingBatchRosterID
FROM dbo.vehicle_info vi
INNER JOIN dbo.dealer_info di ON di.DealerID = vi.DealerID
WHERE di.DealerActive = 1
AND (vi.ItemStatusID < 4
OR vi.ItemStatusID = 5
OR vi.ItemStatusID = 8
);
END TRY
BEGIN CATCH
SELECT ' There was an error: ' + error_message() AS ErrorDescription;
END CATCH;
END;
Note I
- Changed the LEFT JOIN to an INNER JOIN as your WHERE clause needs the record to exist in the dealer_info table
- Moved the
SET NOCOUNT ON;
to be within the BEGIN-END section - Moved the
END
to the end - Renamed your stored procedure as per the excellent comment from @marc_s (on the question itself)
Related Topics
Access 2007: "Select Count(Distinct ..."
How to Display Oracle Schema Size with SQL Query
How to Perform a Replace on Varbinary Data in SQL
Most Recent Record in a Left Join
Adding MySQL Alias Fields Together
Has_Many :Through Multiple Has_One Relationships
How to Find Duplicate Entries in a Database Table
Using the Web.Config to Set Up My SQL Database Connection String
Join Tables on Columns of Composite Foreign/Primary Key in a Query
Conditional SQLite Check Constraint
How to Use Merge on Linked Servers
How to Copy Data from One Table to Another (Where Both Have Other Fields Too That Are Not in Common)
How to Store a Tree in SQL Database
How to Determine Which Columns Are Shared Between Two Tables
How to Do a Find/Replace in T-Sql