There are uncommitted transactions / Lock request time out period exceeded - sql

Please assist. I am trying to write a script to change a data type of a column that has dependants in a table. So i decided to combine scripts and start from creating a temp table to move the data away from the proper table so i can drop it and re create it with a new data type for the column in question. The combined scripts executed fine but now they seem to lock other transaction in the database and when i close the script i get the errors in the title. here is my code below...
SET NOCOUNT ON
BEGIN TRY
BEGIN TRAN
PRINT '1.Drop Temporary Table'
IF EXISTS (SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'EmptyDepot.StoreStockTakeTemp')
AND type in (N'U'))
DROP TABLE EmptyDepot.StoreStockTakeTemp
PRINT '====Table Dropped'
PRINT '2.Create Temporary Table'
CREATE TABLE EmptyDepot.StoreStockTakeTemp
(
StoreStockTakeID INT NOT NULL,
CntrNum VARCHAR(11) NOT NULL,
DepotID INT NOT NULL,
StockCaptureDate DATE NOT NULL,
ChUser VARCHAR(50) NOT NULL,
ChDate SMALLDATETIME NOT NULL,
ChStamp TIMESTAMP NOT NULL,
)
PRINT '====Temporary Table Created'
PRINT '3.Populate Temporary Table'
INSERT INTO EmptyDepot.StoreStockTakeTemp
(
StoreStockTakeID,
CntrNum,
DepotID,
StockCaptureDate,
ChUser,
ChDate
)
SELECT StoreStockTakeID,
CntrNum,
DepotID,
StockCaptureDate,
ChUser,
ChDate
FROM EmptyDepot.StoreStockTake
PRINT '====Temporary Table Populated'
PRINT 'Begin Transaction'
PRINT '================='
PRINT '4.Drop Table'
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[EmptyDepot].[PK_StoreStockTakeID]') AND parent_object_id = OBJECT_ID(N'[EmptyDepot].[StoreStockTake]'))
ALTER TABLE [EmptyDepot].[StoreStockTake] DROP CONSTRAINT [PK_StoreStockTakeID]
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[EmptyDepot].[UX_CntrNum_DepotID]') AND parent_object_id = OBJECT_ID(N'[EmptyDepot].[StoreStockTake]'))
ALTER TABLE [EmptyDepot].[StoreStockTake] DROP CONSTRAINT [UX_CntrNum_DepotID]
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[EmptyDepot].[StoreStockTake]') AND type in (N'U'))
DROP TABLE [EmptyDepot].[StoreStockTake]
PRINT '====Table Dropped'
PRINT '5.Re-Create Table'
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
SET ANSI_PADDING ON
CREATE TABLE EmptyDepot.StoreStockTake
(
StoreStockTakeID INT NOT NULL,
CntrNum VARCHAR(11) NOT NULL,
DepotID INT NOT NULL,
StockCaptureDate DATE NOT NULL,
ChUser VARCHAR(50) NOT NULL,
ChDate SMALLDATETIME NOT NULL,
ChStamp TIMESTAMP NOT NULL,
CONSTRAINT PK_StoreStockTakeID PRIMARY KEY CLUSTERED
(
StoreStockTakeID ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON "PRIMARY"
) ON "PRIMARY"
PRINT '====Table Created'
PRINT '6.Populate Table'
INSERT
INTO EmptyDepot.StoreStockTake
(
StoreStockTakeID,
CntrNum,
DepotID,
StockCaptureDate,
ChUser,
ChDate
)
SELECT StoreStockTakeID,
CntrNum,
DepotID,
StockCaptureDate,
ChUser,
ChDate
FROM EmptyDepot.StoreStockTakeTemp
PRINT '====Table Populated'
COMMIT TRAN
PRINT 'Transaction Committed'
PRINT '====================='
END TRY
BEGIN CATCH
PRINT ERROR_NUMBER()
PRINT ERROR_MESSAGE()
PRINT ERROR_LINE()
ROLLBACK
PRINT 'Transaction Rolled Back'
PRINT '======================='
END CATCH

Script has some problems..
what happens if someone inserts rows while your script is executing?
is it true you don't need constraint (UX_CntrNum_DepotID) in new table?
what about indexes? there could be none thought..
you probably could just rename temp table so you do not need extra insert..
About uncommited transactions- cant see reason, but maybe you started some transaction before executing the command described?

Related

In Micrsoft SQL is an UPDLOCK hint sufficient to avoid deadlocks in an SP that either inserts if not exists or updates otherwise?

I have a C# program with multiple threads that calls an SP to get a unique incrementing value.
I'm trying to prevent deadlocks using query hints UPDLOCK and HOLDLOCK.
The SP
Selects value from a table,
insert if the value is not found (initial value is 1)
Or updates the table by incrementing the value from the first select
Returns the incremented value in an output parameter.
Here the table
CREATE TABLE MyCounters(
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Key] [nvarchar](20) NOT NULL UNIQUE,
[Counter] [bigint] NOT NULL,
CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
Questions
Will a single UPDLOCK be sufficient in the first select to prevent deadlocks?
Or do I need to select with UPDLOCK and HOLDLOCK?
Or do I need a second dummy select with UPDLOCK and HOLDLOCK to only lock the entire table for inserts but not for updates?
I've read this question but there no insert is used.
Below the simplified SP and after that a script I used to test in 2 tabs in SQL management studio. With only a single UPDLOCK the test script works (i.e. no deadlocks and counters at the correct values).
BEGIN TRANSACTION
DECLARE #Key nvarchar(3)
SET #Key = 'AA'
DECLARE #counter bigint
SET #counter=NULL
-- *** Question 1 *** Will a single UPDLOCK be sufficient in the first select to prevent deadlocks?
-- *** Question 2 *** 1. Or do I need to select with UPDLOCK and HOLDLOCK?
SELECT #counter=Counter FROM MyCounters WITH (UPDLOCK) WHERE Key = #Key
IF (#counter IS NULL)
BEGIN
-- *** Question 3 *** Or do I need a second dummy select with UPDLOCK and HOLDLOCK to only lock the entire table for inserts but not update?
-- lock the entire table before inserting (select into variable)
--DECLARE #temp bigint
--SELECT TOP 1 #temp = Counter FROM MyCounters WITH (UPDLOCK, HOLDLOCK)
SET #counter=1
INSERT INTO MyCounters ([Key],Counter) VALUES (#Key, #counter)
END
ELSE
BEGIN
SET #counter=#counter+1
UPDATE MyCounters SET Counter = #counter WHERE Key = #Key
END
SELECT #Key, #counter
COMMIT
Below the test script (which I ran in multiple tabs in SQL management studio)
BEGIN TRANSACTION
WAITFOR DELAY '00:00:05' --to give me a chance to start the script in multiple tabs
DECLARE #i int
SET #i=0
WHILE #i < 100
BEGIN
DECLARE #Key nvarchar(3)
SET #Key = 'A'+CONVERT(nvarchar(10),#i)
DECLARE #counter bigint
SET #counter=NULL
SELECT #counter=Counter FROM MyCounters WITH (UPDLOCK) WHERE Key = #Key
IF (#counter IS NULL)
BEGIN
-- lock the entire table before inserting (select into variable)
--DECLARE #temp bigint
--SELECT TOP 1 #temp = Counter FROM MyCounters WITH (UPDLOCK, HOLDLOCK)
SET #counter=1
INSERT INTO MyCounters ([Key],Counter) VALUES (#Key, #counter)
END
ELSE
BEGIN
SET #counter=#counter+1
UPDATE MyCounters SET Counter = #counter WHERE Key = #Key
END
SELECT #i, #Key, #counter
SET #i = #i + 1
END;
COMMIT
-- *** Question 1 *** Will a single UPDLOCK be sufficient in the first select to prevent deadlocks?
-- *** Question 2 *** 1. Or do I need to select with UPDLOCK and HOLDLOCK? SELECT #counter=Counter FROM MyCounters WITH (UPDLOCK) WHERE
Key = #Key
In in the default READ COMMITTED isolation level, the UPDLOCK will be released when the statement completes. Specify UPDLOCK,HOLDLOCK to retain locks until the transaction commits or rolls back.
I suggest you change the clustered primary key from the IDENTITY column to the natural key column Key or make the unique constraint the clustered index. This will improve performance. If you don't actually use the Id column, remove it entirely. Throwing an unused IDENTITY surrogate key on tables is a common anti-pattern.
--clustered unique constraint
CREATE TABLE dbo.MyCounters(
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Key] [nvarchar](20) NOT NULL CONSTRAINT UQ_MyCounters_Key UNIQUE CLUSTERED,
[Counter] [bigint] NOT NULL,
CONSTRAINT [PK_Table_1] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)
);
--remove unneeded surrogate key
CREATE TABLE dbo.MyCounters(
[Key] [nvarchar](20) NOT NULL CONSTRAINT PK_MyCounters PRIMARY KEY CLUSTERED,
[Counter] [bigint] NOT NULL
);
Also, add SET XACT_ABORT ON; to procs with explicit transactions to ensure the transaction is rolled back immediately after errors or client timeouts.

The DELETE statement conflicted with the REFERENCE constraint "FK_BlogCommentReply_BlogCommentId"

I have a blog and keeping it simple for discussion, the main tables are Blog, BlogComment, BlogCommentReply and User.
A blog belongs to a User.
A comment belongs to a blog/user.
A comment reply belongs to a blog/comment/user.
I want to delete a User - UserId = 5.
My delete user stored procedure deletes (wrapped in a transaction) in this order:
BlogCommentReply
BlogComment
Blog (if the user is the author of the blog only)
User
It deletes the entry(s) in the BlogCommentReply for the User, then attempts to delete the entry(s) in the BlogComment for the User.
I then get the error:
The DELETE statement conflicted with the REFERENCE constraint "FK_BlogCommentReply_BlogCommentId".
The conflict occurred in database "DBGbngDev", table "dbo.BlogCommentReply", column
'BlogCommentId'.
It still thinks there is an entry in the BlogCommentReply table.
Here is the execute of the stored procedure with debug selects in it to show that it deletes the BlogCommentReply entry but then fails on the delete of the BlogComment.
Table definitions:
----------------------- BlogComment table (parent to blogCommentReply)
CREATE TABLE [dbo].[BlogComment](
[BlogCommentId] [int] IDENTITY(1,1) NOT NULL,
[UserId] [int] NOT NULL,
[BlogId] [int] NOT NULL,
[BlogCommentContent] [varchar](max) NOT NULL,
[LikeCount] [int] NOT NULL,
[DisLikeCount] [int] NOT NULL,
[DateTimeOfBlogComment] [datetime] NOT NULL,
CONSTRAINT [PK_BlogComment] PRIMARY KEY CLUSTERED
(
[BlogCommentId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[BlogComment] WITH CHECK ADD CONSTRAINT [FK_BlogComment_BlogId] FOREIGN
KEY([BlogId])
REFERENCES [dbo].[Blog] ([BlogId])
GO
ALTER TABLE [dbo].[BlogComment] CHECK CONSTRAINT [FK_BlogComment_BlogId]
GO
ALTER TABLE [dbo].[BlogComment] WITH CHECK ADD CONSTRAINT [FK_BlogComment_UserId] FOREIGN
KEY([UserId])
REFERENCES [dbo].[User] ([UserId])
GO
ALTER TABLE [dbo].[BlogComment] CHECK CONSTRAINT [FK_BlogComment_UserId]
GO
----------------------- BlogCommentReply table (child)
CREATE TABLE [dbo].[BlogCommentReply](
[BlogCommentReplyId] [int] IDENTITY(1,1) NOT NULL,
[UserId] [int] NOT NULL,
[BlogCommentId] [int] NOT NULL,
[BlogId] [int] NOT NULL,
[BlogCommentReplyContent] [varchar](max) NOT NULL,
[LikeCount] [int] NOT NULL,
[DisLikeCount] [int] NOT NULL,
[DateTimeOfBlogCommentReply] [datetime] NOT NULL,
CONSTRAINT [PK_BlogCommentReply] PRIMARY KEY CLUSTERED
(
[BlogCommentReplyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[BlogCommentReply] WITH CHECK ADD CONSTRAINT [FK_BlogCommentReply_BlogCommentId]
FOREIGN KEY([BlogCommentId])
REFERENCES [dbo].[BlogComment] ([BlogCommentId])
GO
ALTER TABLE [dbo].[BlogCommentReply] CHECK CONSTRAINT [FK_BlogCommentReply_BlogCommentId]
GO
ALTER TABLE [dbo].[BlogCommentReply] WITH CHECK ADD CONSTRAINT [FK_BlogCommentReply_BlogId] FOREIGN
KEY([BlogId])
REFERENCES [dbo].[Blog] ([BlogId])
GO
ALTER TABLE [dbo].[BlogCommentReply] CHECK CONSTRAINT [FK_BlogCommentReply_BlogId]
GO
ALTER TABLE [dbo].[BlogCommentReply] WITH CHECK ADD CONSTRAINT [FK_BlogCommentReply_UserId] FOREIGN
KEY([UserId])
REFERENCES [dbo].[User] ([UserId])
GO
ALTER TABLE [dbo].[BlogCommentReply] CHECK CONSTRAINT [FK_BlogCommentReply_UserId]
GO
Extracted parts of the delete stored procedure (#a_UserId = 5):
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- Step 6. Get the number of blog comments replys for the user.
-- Note: there may not be any.
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SELECT #BlogCommentReplysCount = Count(*)
FROM dbo.BlogCommentReply
WHERE ( UserId = #a_UserId )
SELECT #ReturnCode = ##ERROR
IF #ReturnCode <> 0
BEGIN
ROLLBACK TRANSACTION
SELECT #Message = 'Critical Error - procedure DeleteBlog failed during the select of BlogCommentReply. User id: ' + CAST(#a_UserId AS VARCHAR) + '. '
RAISERROR (#Message, 16, 1)
END
SELECT '#BlogCommentReplysCount: ' + CAST(#BlogCommentReplysCount AS VARCHAR) + '. '
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- Step 7. Delete the BlogCommentReply entries for the user.
-- Note: the user may not have made any.
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DELETE dbo.BlogCommentReply
WHERE ( UserId = #a_UserId )
SELECT #ReturnCode = ##ERROR,
#RowCount = ##ROWCOUNT
IF #ReturnCode <> 0 AND #RowCount > 0
BEGIN
ROLLBACK TRANSACTION
SELECT #Message = 'Critical Error - procedure DeleteBlog failed during the delete of BlogCommentReply. User id: ' + CAST(#a_UserId AS VARCHAR) + '. '
RAISERROR (#Message, 16, 1)
END
SELECT 'Deleted BlogCommentReply'
SELECT '#ReturnCode: ' + CAST(#ReturnCode AS VARCHAR) + '. '
SELECT '#RowCount: ' + CAST(#RowCount AS VARCHAR) + '. '
SELECT '#a_UserId: ' + CAST(#a_UserId AS VARCHAR) + '. '
SELECT Count(*) as AFTERDELETE
FROM dbo.BlogCommentReply
WHERE ( UserId = #a_UserId )
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- Step 8. Get the number of blog comments for this user.
-- Note: there may not be any.
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SELECT #BlogCommentsCount = Count(*)
FROM dbo.BlogComment
WHERE ( UserId = #a_UserId )
SELECT #ReturnCode = ##ERROR
IF #ReturnCode <> 0
BEGIN
ROLLBACK TRANSACTION
SELECT #Message = 'Critical Error - procedure DeleteBlog failed during the select of BlogComment. User id: ' + CAST(#a_UserId AS VARCHAR) + '. '
RAISERROR (#Message, 16, 1)
END
SELECT '#BlogCommentsCount: ' + CAST(#BlogCommentsCount AS VARCHAR) + '. '
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- Step 9. Delete the BlogComment entries for the user.
-- Note: the user may not have made any.
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SELECT Count(*) as BEFORE
FROM dbo.BlogComment
WHERE ( UserId = #a_UserId )
SELECT 'Going to delete BlogComment'
DELETE dbo.BlogComment
WHERE ( UserId = #a_UserId )
SELECT #ReturnCode = ##ERROR,
#RowCount = ##ROWCOUNT
IF #ReturnCode <> 0 AND #RowCount > 0
BEGIN
ROLLBACK TRANSACTION
SELECT #Message = 'Critical Error - procedure DeleteBlog failed during the delete of BlogComment. User id: ' + CAST(#a_UserId AS VARCHAR) + '. '
RAISERROR (#Message, 16, 1)
END
SELECT 'Deleted BlogComment'
I think it's better to have your complete stored procedure script to check the error, but for the mean time I guess the problem is here:
DELETE dbo.BlogCommentReply
WHERE ( UserId = #a_UserId )
Ok, it's deleting all of comment replies which the related user (i.e. #a_UserId = 5) has.
But look at the rest of your script:
DELETE dbo.BlogComment
WHERE ( UserId = #a_UserId )
It's deleting all of user's comments, WHILE they may have some other comment replies for another users and they are not deleted. So I think the problem is here.
Maybe it's better to change the first deletion part to:
DELETE dbo.BlogCommentReply
WHERE ( UserId = #a_UserId )
DELETE dbo.BlogCommentReply
FROM [dbo].[BlogComment]
WHERE dbo.BlogCommentReply.BlogCommentId=[dbo].[BlogComment].BlogCommentId
AND [dbo].[BlogComment].UserId=#a_UserId
It's very simple you are deleting comment's reply of a specific user while other users might have reply under the same comment.
I you really want to delete all related info of a user , you have to go with different approach like finding all replies under that user's comment and delete those.

Checking for table columns before adding them in SQL Server

I need to script out a table modification at work. Rather than do a simple "if exists then drop and create", they want it to check for the new columns I'm adding, and only then alter the table with them if they don't exist.
Could someone help me with the script? Assume a simple table that looks like this currently:
CREATE TABLE myTable (
[ID] [int] NOT NULL,
[FirstName] [varchar] (20) NOT NULL,
[LastName] [varchar] (20) NOT NULL
)
.. I'd like to add an Address field, varchar(50) let's say, but only if it doesn't already exist in the schema.
IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'myTable' AND COLUMN_NAME = 'Address')
BEGIN
ALTER TABLE [dbo].[myTable] ADD
[Address] varchar(50) NOT NULL
END
Try this
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[myTable ]') AND type in (N'U'))
BEGIN
DROP TABLE [dbo].[myTable ]
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE myTable (
[ID] [int] NOT NULL,
[FirstName] [varchar] (20) NOT NULL,
[LastName] [varchar] (20) NOT NULL,
[Address] [varchar] (50) NOT NULL
)
OR
if not exists(select * from sys.columns
where Name = N'Address' and Object_ID = Object_ID(N'myTable'))
begin
alter table myTable
add Address varchar(50) NOT NULL
end
GO
Try this:
Here using it you can make check for multiple columns and get you table altered...
DECLARE #query VARCHAR(MAX)
IF EXISTS(SELECT * FROM sys.columns
WHERE Name = N'Address' AND OBJECT_ID = OBJECT_ID(N'<TableName>'))
BEGIN
SET
#query = 'ALTER TABLE <TableName> ADD Address varchar(50) GO'
END
--You can give multiple If conditions, example:
--IF EXISTS(SELECT * FROM sys.columns
--WHERE Name = N'<SomeOtherColumn>' AND OBJECT_ID = OBJECT_ID(N'<TableName>'))
--BEGIN
--SET
--#query = #query + 'ALTER TABLE <TableName> ADD <SomeOtherColumn> varchar(50) GO'
--END
EXEC sp_Executesql #query
IF 'col_name'
NOT IN
SELECT Name
FROM table_name.columns
ALTER TABLE table_name
ADD 'col_name' VARCHAR(65) NOT NULL
something like this?
EDIT: my friend believes this is much better
IF NOT EXISTS
(SELECT Name
FROM table_name.columns
Where Name='target_column_name')
ALTER TABLE table_name
ADD 'target_column_name' VARCHAR(65) NOTNULL

Long running INSERT query on SQL Server 2005

I have been sniffing out forums and blogs lately, but need some help with a long running query. It's part of a system of stored procedures. This specified statement used to run in about 5 minutes, but lately has been running up to 72 hours!
Here's the setup:
SQL Server 2005 with 28GB memory. Two mountpoints to a SAN with shared disks consisting of 10 spindles. Data is on one mountpoint, Log on another, tempdb on data space. Just one userdatabase on this server.
Here's two tables, condit and condmod. Condit contains 800K records, condmod is initially empty. I issue a truncate mcmain.condmod before the process starts, for testing purposes.
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DF__condit__con_notm__000AF8CF]') AND type = 'D')
BEGIN
ALTER TABLE [mcmain].[condit] DROP CONSTRAINT [DF__condit__con_notm__000AF8CF]
END
GO
/****** Object: Table [mcmain].[condit] Script Date: 02/07/2012 11:57:47 ******/
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mcmain].[condit]') AND type in (N'U'))
DROP TABLE [mcmain].[condit]
GO
/****** Object: Table [mcmain].[condit] Script Date: 02/07/2012 11:57:49 ******/
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mcmain].[condit]') AND type in (N'U'))
BEGIN
CREATE TABLE [mcmain].[condit](
[con_levgln] [char](13) NULL,
[con_stat] [char](4) NULL,
[con_dscgrp] [char](35) NULL,
[con_levart] [char](20) NULL,
[con_desc] [char](50) NULL,
[con_disc1] [numeric](5, 0) NULL,
[con_disc2] [numeric](5, 0) NULL,
[con_disc3] [numeric](5, 0) NULL,
[con_ntprce] [numeric](9, 0) NULL,
[con_dtstrt] [datetime] NULL,
[con_dtend] [datetime] NULL,
[con_volc] [char](8) NULL,
[con_updnmr] [char](20) NULL,
[con_notmod] [bit] NULL,
[con_ascver] [char](5) NULL,
[con_prddat] [datetime] NULL,
[con_cusgln] [char](13) NULL,
[con_cusdeb] [char](40) NULL,
[con_rowid] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DF__condit__con_notm__000AF8CF]') AND type = 'D')
BEGIN
ALTER TABLE [mcmain].[condit] ADD DEFAULT ((0)) FOR [con_notmod]
END
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DF__condmod__com_not__7E22B05D]') AND type = 'D')
BEGIN
ALTER TABLE [mcmain].[condmod] DROP CONSTRAINT [DF__condmod__com_not__7E22B05D]
END
GO
/****** Object: Table [mcmain].[condmod] Script Date: 02/07/2012 11:57:56 ******/
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mcmain].[condmod]') AND type in (N'U'))
DROP TABLE [mcmain].[condmod]
GO
/****** Object: Table [mcmain].[condmod] Script Date: 02/07/2012 11:57:58 ******/
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mcmain].[condmod]') AND type in (N'U'))
BEGIN
CREATE TABLE [mcmain].[condmod](
[com_levgln] [char](13) NULL,
[com_stat] [char](4) NULL,
[com_dscgrp] [char](35) NULL,
[com_levart] [char](20) NULL,
[com_desc] [char](50) NULL,
[com_disc1] [numeric](5, 0) NULL,
[com_disc2] [numeric](5, 0) NULL,
[com_disc3] [numeric](5, 0) NULL,
[com_ntprce] [numeric](9, 0) NULL,
[com_dtstrt] [datetime] NULL,
[com_dtend] [datetime] NULL,
[com_volc] [char](8) NULL,
[com_updnmr] [char](20) NULL,
[com_notmod] [bit] NULL,
[com_ascver] [char](8) NULL,
[com_prddat] [datetime] NULL,
[com_cusgln] [char](13) NULL,
[com_cusdeb] [char](40) NULL,
[com_rowid] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DF__condmod__com_not__7E22B05D]') AND type = 'D')
BEGIN
ALTER TABLE [mcmain].[condmod] ADD DEFAULT ((0)) FOR [com_notmod]
END
GO
Here's the isolated code that runs a long time:
DECLARE #TempIdTable TABLE ([com_rowid] Int PRIMARY KEY)
INSERT #TempIdTable([com_rowid])
SELECT cmd.[com_rowid]
FROM [mcmain].[condmod] AS cmd
LEFT OUTER JOIN [mcmain].[condit] AS cdt
ON con_levgln = com_levgln
AND IsNull(con_dscgrp,'') = IsNull(com_dscgrp,'')
AND IsNull(con_levart,'') = IsNull(com_levart,'')
AND IsNull(con_volc,'') = IsNull(com_volc,'')
AND IsNull(con_cusgln,'') = IsNull(com_cusgln,'')
AND IsNull(con_cusdeb,'') = IsNull(com_cusdeb,'')
WHERE con_levgln is NULL
--select * from #TempIdTable
INSERT INTO mcmain.condit(con_levgln
,con_stat
,con_dscgrp
,con_levart
,con_desc
,con_disc1
,con_disc2
,con_disc3
,con_ntprce
,con_dtstrt
,con_dtend
,con_volc
,con_notmod
,con_updnmr
,con_ascver
,con_cusgln
,con_cusdeb)
SELECT com_levgln
,com_stat
,com_dscgrp
,com_levart
,com_desc
,com_disc1
,com_disc2
,com_disc3
,com_ntprce
,com_dtstrt
,com_dtend
,com_volc
,com_notmod
,com_updnmr
,com_ascver
,com_cusgln
,com_cusdeb
FROM [mcmain].[condmod] AS cmd
INNER JOIN #TempIdTable AS tit
ON tit.com_rowid = cmd.com_rowid
The insert into the #TempIdTable takes forever. What can I do to speed up this process?
TIA
Cees Cappelle
p.s. I have clustered indexes on both tables, like:
/****** Object: Index [condmodTest] Script Date: 02/07/2012 13:24:34 ******/
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[mcmain].[condmod]') AND name = N'condmodTest')
CREATE CLUSTERED INDEX [condmodTest] ON [mcmain].[condmod]
(
[com_levgln] ASC,
[com_dscgrp] ASC,
[com_levart] ASC,
[com_volc] ASC,
[com_cusgln] ASC,
[com_cusdeb] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
If I do a straight select (just now), it takes 2 seconds.
Here's the code:
SELECT com_levgln
,com_stat
,com_dscgrp
,com_levart
,com_desc
,com_disc1
,com_disc2
,com_disc3
,com_ntprce
,com_dtstrt
,com_dtend
,com_volc
,com_notmod
,com_updnmr
,com_ascver
,com_cusgln
,com_cusdeb
FROM mcmain.condmod
LEFT OUTER JOIN mcmain.condit
ON con_levgln = com_levgln
AND IsNull(con_dscgrp,'') = IsNull(com_dscgrp,'')
AND IsNull(con_levart,'') = IsNull(com_levart,'')
AND IsNull(con_volc,'') = IsNull(com_volc,'')
AND IsNull(con_cusgln,'') = IsNull(com_cusgln,'')
AND IsNull(con_cusdeb,'') = IsNull(com_cusdeb,'')
WHERE con_levgln is NULL
I just did a Actial Execution plan with the following code. It took 3'16'' ???
truncate table mcmain.condit
CREATE TABLE #TempIdTable ([com_rowid] Int PRIMARY KEY)
-- DECLARE #TempIdTable TABLE
-- ([com_rowid] Int PRIMARY KEY)
INSERT #TempIdTable
([com_rowid])
SELECT cmd.[com_rowid]
FROM [mcmain].[condmod] AS cmd
LEFT OUTER JOIN [mcmain].[condit] AS cdt
ON con_levgln = com_levgln
AND IsNull(con_dscgrp,'') = IsNull(com_dscgrp,'')
AND IsNull(con_levart,'') = IsNull(com_levart,'')
AND IsNull(con_volc,'') = IsNull(com_volc,'')
AND IsNull(con_cusgln,'') = IsNull(com_cusgln,'')
AND IsNull(con_cusdeb,'') = IsNull(com_cusdeb,'')
WHERE con_levgln is NULL
-- AND com_updnmr = #plannummer
INSERT INTO mcmain.condit
(con_levgln
,con_stat
,con_dscgrp
,con_levart
,con_desc
,con_disc1
,con_disc2
,con_disc3
,con_ntprce
,con_dtstrt
,con_dtend
,con_volc
,con_notmod
,con_updnmr
,con_ascver
,con_cusgln
,con_cusdeb)
SELECT com_levgln
,com_stat
,com_dscgrp
,com_levart
,com_desc
,com_disc1
,com_disc2
,com_disc3
,com_ntprce
,com_dtstrt
,com_dtend
,com_volc
,com_notmod
,com_updnmr
,com_ascver
,com_cusgln
,com_cusdeb
FROM [mcmain].[condmod] AS cmd
INNER JOIN #TempIdTable AS tit
ON tit.com_rowid = cmd.com_rowid
Same statement but using a tablevariable took 1'39''
When I run the sp, the same statement takes hours and hours. Still don't get it.
If the SELECT itself takes a long time
You could consider using NOT EXISTS rather than OUTER JOIN ... NULL as this is often more efficient.
Also I would get rid of the non sargable ISNULL comparisons.
SELECT cmd.[com_rowid]
FROM [mcmain].[condmod] AS cmd
WHERE NOT EXISTS (SELECT *
FROM [mcmain].[condit] AS cdt
WHERE con_levgln = com_levgln
AND EXISTS (SELECT con_dscgrp,
con_levart,
con_volc,
con_cusgln,
con_cusdeb
INTERSECT
SELECT com_dscgrp,
com_levart,
com_volc,
com_cusgln,
com_cusdeb))
If the SELECT runs quite quickly on its own but just not when inserting to the table variable then check whether in the quick case you get a parallel plan.
Queries that insert to table variables do not get parallelised so if that is the issue you could consider changing to a #temp table.
If neither of these suggestions help then I suggest you start monitoring the wait types when this procedure runs. See the paper "SQL Server 2005 Waits and Queues"
Note: the use of #tables uses tempdb.
You should try increasing the number of temp db files... you can start with the number of tempdb files equal to the number of procs you have... but as a good starting point just jump to 10... The problem you could be having is contention for tempdb files. You should look for page latching in tempdb.
This article discusses how the generalization I wrote above is a misconception (but not necessarily wrong) but in doing so does a good job of explaining the issue. It also points you to other articles which give informatoin on how to look for page latching.
A SQL Server DBA myth a day: (12/30) tempdb should always have one data file per processor core

Very strange SQL update issue

I have a table called ApprovalTasks... Approvals has a status column
I also have a view called ApprovalsView
When I try a straight update :
update ApprovalTasks set Status = 2 where ApprovalTaskID = 48
I'm getting this error message:
Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'dbo.ApprovalsView' with unique index 'IX_ApprovalTaskID'.
The statement has been terminated.
Any idea why this is happening?
Here is the create table script:
USE [CSPMOSSApplication]
GO
/****** Object: Table [dbo].[ApprovalTasks] Script Date: 12/11/2008 12:41:35 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[ApprovalTasks](
[ApprovalTaskID] [int] IDENTITY(1,1) NOT NULL,
[ApproverID] [int] NOT NULL,
[DueDate] [datetime] NULL,
[Status] [smallint] NOT NULL,
[ApprovedRejectedDate] [datetime] NULL,
[Reason] [nvarchar](1024) COLLATE Finnish_Swedish_CI_AS NULL,
[OrganizationID] [int] NOT NULL,
[TicketID] [int] NOT NULL,
[Link] [nchar](255) COLLATE Finnish_Swedish_CI_AS NULL,
[GlobalApproverID] [int] NULL,
CONSTRAINT [PK_Approval_Tasks] PRIMARY KEY CLUSTERED
(
[ApprovalTaskID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
USE [CSPMOSSApplication]
GO
ALTER TABLE [dbo].[ApprovalTasks] WITH NOCHECK ADD CONSTRAINT [FK_Approval_Tasks_ApprovalTaskStatuses] FOREIGN KEY([Status])
REFERENCES [dbo].[ApprovalTaskStatuses] ([ApprovalTaskStatusID])
GO
ALTER TABLE [dbo].[ApprovalTasks] CHECK CONSTRAINT [FK_Approval_Tasks_ApprovalTaskStatuses]
GO
ALTER TABLE [dbo].[ApprovalTasks] WITH NOCHECK ADD CONSTRAINT [FK_Approval_Tasks_Organizations] FOREIGN KEY([OrganizationID])
REFERENCES [dbo].[Organizations] ([OrganizationID])
GO
ALTER TABLE [dbo].[ApprovalTasks] CHECK CONSTRAINT [FK_Approval_Tasks_Organizations]
GO
ALTER TABLE [dbo].[ApprovalTasks] WITH NOCHECK ADD CONSTRAINT [FK_Approval_Tasks_Tickets] FOREIGN KEY([TicketID])
REFERENCES [dbo].[Tickets] ([TicketID])
GO
ALTER TABLE [dbo].[ApprovalTasks] CHECK CONSTRAINT [FK_Approval_Tasks_Tickets]
GO
ALTER TABLE [dbo].[ApprovalTasks] WITH NOCHECK ADD CONSTRAINT [FK_Approval_Tasks_Users] FOREIGN KEY([ApproverID])
REFERENCES [dbo].[Users] ([UserID])
GO
ALTER TABLE [dbo].[ApprovalTasks] CHECK CONSTRAINT [FK_Approval_Tasks_Users]
PK_Approval_Tasks(Clustered)
USE [CSPMOSSApplication]
GO
/****** Object: Index [PK_Approval_Tasks] Script Date: 12/11/2008 12:45:50 ******/
ALTER TABLE [dbo].[ApprovalTasks] ADD CONSTRAINT [PK_Approval_Tasks] PRIMARY KEY CLUSTERED
(
[ApprovalTaskID] ASC
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]
IX_ApprovalTaskID(Clsutered)
SE [CSPMOSSApplication]
GO
SET ARITHABORT ON
GO
SET CONCAT_NULL_YIELDS_NULL ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
SET ANSI_PADDING ON
GO
SET ANSI_WARNINGS ON
GO
SET NUMERIC_ROUNDABORT OFF
GO
/****** Object: Index [IX_ApprovalTaskID] Script Date: 12/11/2008 12:47:27 ******/
CREATE UNIQUE CLUSTERED INDEX [IX_ApprovalTaskID] ON [dbo].[ApprovalsView]
(
[ApprovalTaskID] ASC
)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]
Create View Script
USE [CSPMOSSApplication]
GO
-- =============================================
-- Script Template
-- =============================================
-- [ApprovalTasks]: add columns Link, GlobalApproverID
IF NOT EXISTS(SELECT 1 FROM sysobjects,syscolumns WHERE sysobjects.id = syscolumns.id
AND sysobjects.name = 'ApprovalTasks' AND syscolumns.name = 'Link')
BEGIN
ALTER TABLE ApprovalTasks ADD [Link] [nchar] (255) COLLATE Finnish_Swedish_CI_AS NULL
PRINT 'Column ApprovalTasks.Link was added.'
END
IF NOT EXISTS(SELECT 1 FROM sysobjects,syscolumns WHERE sysobjects.id = syscolumns.id
AND sysobjects.name = 'ApprovalTasks' AND syscolumns.name = 'GlobalApproverID')
BEGIN
ALTER TABLE ApprovalTasks ADD [GlobalApproverID] [int] NULL
PRINT 'Column ApprovalTasks.GlobalApproverID was added.'
ALTER TABLE [dbo].[ApprovalTasks] WITH NOCHECK ADD CONSTRAINT [FK_Approval_Tasks_GlobalApproverID] FOREIGN KEY([GlobalApproverID])
REFERENCES [dbo].[Users] ([UserID])
ALTER TABLE [dbo].[ApprovalTasks] CHECK CONSTRAINT [FK_Approval_Tasks_GlobalApproverID]
END
-- [ApprovalsView]
IF EXISTS (SELECT * FROM sys.fulltext_indexes fti WHERE fti.object_id = OBJECT_ID(N'[dbo].[ApprovalsView]'))
BEGIN
DROP FULLTEXT INDEX ON [dbo].[ApprovalsView]
PRINT 'FULLTEXT INDEX on [ApprovalsView] was dropped.'
END
GO
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[ApprovalsView]') AND name = N'IX_ApprovalTaskID')
BEGIN
DROP INDEX IX_ApprovalTaskID ON [dbo].[ApprovalsView] WITH ( ONLINE = OFF )
PRINT 'INDEX IX_ApprovalTaskID was dropped.'
END
GO
IF EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[ApprovalsView]'))
DROP VIEW [dbo].[ApprovalsView]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[ApprovalsView]
WITH SCHEMABINDING
AS
SELECT at.ApprovalTaskID,
at.ApproverID,
at.DueDate,
at.Status,
ats.ApprovalTaskStatusTranslationKey AS StatusText,
at.ApprovedRejectedDate,
at.Reason,
at.OrganizationID,
ord.Name AS OrderName,
ord.TotalPrice,
ord.SubmitDate,
ord.OrdererID,
usr.FirstName AS OrdererFirstName,
usr.LastName AS OrdererLastName,
ordi.Items_Name AS ItemName,
ordi.Items_Description AS ItemDescription,
ordi.OtherInformation AS ItemInformation,
oir.RecipientFullName,
CONVERT(nvarchar(250), oir.DeliveryAddress) As DeliveryAddress,
ti.Description
FROM dbo.ApprovalTasks at
INNER JOIN
dbo.ApprovalTaskStatuses ats ON ats.ApprovalTaskStatusID = at.Status
INNER JOIN
dbo.Orders_Items_Recipients oir ON oir.TicketID = at.TicketID
INNER JOIN
dbo.Orders_Items ordi ON ordi.Orders_ItemsID = oir.Orders_ItemsID
INNER JOIN
dbo.Orders ord ON ordi.OrderID = ord.OrderID
INNER JOIN
dbo.Users usr ON ord.OrdererID = usr.UserID
INNER JOIN
dbo.Tickets ti ON ti.TicketID = at.TicketID
GO
CREATE UNIQUE CLUSTERED INDEX [IX_ApprovalTaskID] ON [dbo].[ApprovalsView]
(
[ApprovalTaskID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
GO
CREATE FULLTEXT INDEX ON [dbo].[ApprovalsView](
[DeliveryAddress] LANGUAGE [Neutral],
[ItemDescription] LANGUAGE [Neutral],
[ItemInformation] LANGUAGE [Neutral],
[ItemName] LANGUAGE [Neutral],
[OrdererFirstName] LANGUAGE [Neutral],
[OrdererLastName] LANGUAGE [Neutral],
[OrderName] LANGUAGE [Neutral],
[Reason] LANGUAGE [Neutral],
[RecipientFullName] LANGUAGE [Neutral])
KEY INDEX [IX_ApprovalTaskID] ON [ApprovalSearchCatalog]
WITH CHANGE_TRACKING AUTO
GO
ALTER FULLTEXT CATALOG [ApprovalSearchCatalog] rebuild
PRINT 'Catalog [ApprovalSearchCatalog] task to rebuild fulltext index was sent.'
-- STORED PROCEDURES
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ReceiveApprovalTasksFromQueue]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[ReceiveApprovalTasksFromQueue]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
EXEC dbo.sp_executesql #statement = N'
-- =============================================
-- Author: Petr Klozik
-- Create date: 19.11.2008
-- Description: Gets approvals which DueDate is over ReferenceDate (now)
-- =============================================
CREATE Procedure [dbo].[ReceiveApprovalTasksFromQueue]
#Limit int
As
BEGIN
SET NOCOUNT ON;
If Not #Limit Is Null Set RowCount #Limit
-- Status: WaitingForApproval = 1
Select Tasks.ApprovalTaskID
From ApprovalTasks Tasks
Where Status = 1 And DueDate < GetDate()
END
'
GO
GRANT EXECUTE ON [dbo].[ReceiveApprovalTasksFromQueue] TO [OMT_IntegrationRole]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[UpdateApprovalTaskInfo]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[UpdateApprovalTaskInfo]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
EXEC dbo.sp_executesql #statement = N'
-- =============================================
-- Author: Klozik Petr
-- Create date: 2008-11-25
-- Description: Updates Approval task info to DB
-- =============================================
CREATE PROCEDURE [dbo].[UpdateApprovalTaskInfo]
#ApprovalTaskID int,
#DueDate datetime,
#ApprovalRejectDate datetime,
#Reason nvarchar(1024),
#Status int,
#GlobalApproverID int
AS
BEGIN
SET NOCOUNT ON;
Update ApprovalTasks
Set DueDate = #DueDate,
ApprovedRejectedDate = #ApprovalRejectDate,
Reason = #Reason,
Status = #Status,
GlobalApproverID = #GlobalApproverID
Where ApprovalTaskID = #ApprovalTaskID
END
'
GO
GRANT EXECUTE ON [dbo].[UpdateApprovalTaskInfo] TO [OMT_IntegrationRole]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[GetUserById]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[GetUserById]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
EXEC dbo.sp_executesql #statement = N'
-- =============================================
-- Author: Klozik Petr
-- Create date: 2008-12-04
-- Description: Gets user row by the specified ID.
-- =============================================
CREATE PROCEDURE [dbo].[GetUserById]
(
#UserID int
)
AS
BEGIN
SELECT
UserID,
RTRIM(SID) [SID],
RTRIM(OMTGUID) [OMTGUID],
RTRIM(UserAccount) [UserAccount],
RTRIM(Email) [Email],
RTRIM(FirstName) [FirstName],
RTRIM(LastName) [LastName],
RTRIM(Country) [Country],
RTRIM(City) [City],
RTRIM(PostalNumber) [PostalNumber],
RTRIM(StreetAddress) [StreetAddress],
RTRIM(PhoneNumber) PhoneNumber,
Modified,
Deleted,
Uploaded,
UploadCode,
UploadStatus,
RTRIM(Users.ADUserAccount) AS ADUserAccount
FROM
[dbo].[Users]
WHERE
UserID = #UserID
END
'
GO
GRANT EXECUTE ON [dbo].[GetUserById] TO [OMT_IntegrationRole]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[GetApprovalTaskInfoById]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[GetApprovalTaskInfoById]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
EXEC dbo.sp_executesql #statement = N'
-- =============================================
-- Author: Petr Klozik
-- Create date: 19.11.2008
-- Description: Gets approvals which DueDate is over ReferenceDate (now)
-- =============================================
CREATE Procedure [dbo].[GetApprovalTaskInfoById]
#ApprovalTaskID int
As
BEGIN
SET NOCOUNT ON;
Declare #OrganizationID int
Declare #CurrentApproverID int
Declare #NewApproverID int
Declare #NewOrganizationID int
Select #OrganizationID = OrganizationID, #CurrentApproverID = ApproverID
From ApprovalTasks
Where ApprovalTaskID = #ApprovalTaskID
Set #NewApproverID = (
Select Top 1 o.GlobalApproverID
From Organizations o
Inner Join OrganizationDescendants od On od.OrganizationID = o.OrganizationID
Where od.DescendantID = #OrganizationID
And Not(o.GlobalApproverID Is Null)
Order By o.OrganizationLevel Desc
)
If Not(#NewApproverID Is Null)
Begin
Set #NewOrganizationID = (
Select OrganizationID
from Organizations
Where GlobalApproverID = #NewApproverID)
End
Select Tasks.*, Tickets.Description AS TicketDescription,
Tickets.RequestorID, Tickets.OrdererID,
#NewApproverID AS OrgGlobalApproverID,
#NewOrganizationID AS OrgGlobalApproverOrganizationID
From ApprovalTasks Tasks
inner join Tickets Tickets on Tasks.TicketID = Tickets.TicketID
Where ApprovalTaskID = #ApprovalTaskID
END
'
GO
GRANT EXECUTE ON [dbo].[GetApprovalTaskInfoById] TO [OMT_IntegrationRole]
GO
Lucky guess: any update triggers defined?
2nd lucky guess: ApprovalsView is an indexed view whose index is violated after updating the ApprovalTask table.
look at the definition of the index IX_ApprovalTaskID
Is it possible there is a unique key constraint on ApprovalTaskID, StatusID which would mean there is another row in the table with Status = 2 & ApprovalTaskID = 48
I agree with user Learning, it looks like there's a FOR UPDATE trigger on ApprovalTasks that is inserting an ApprovalTaskID into ApprovalView
Try running DISABLE TRIGGER ALL ON ApprovalTasks and re-run the update
Since the error is coming from the object dbo.ApprovalsView , the problem is with a trigger on ApprovalsTask which is trying to update that table. I really think that ApprovalsView is a table and not a view. But you must have already checked for that.
It looks like a view has been created which is either of, or includes, the table you are updating and that the error occurs when the view is being updated with the changes.
Perhaps the view contains data from different tables which is incompatible, or has stricter constraints set?