Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMITS - sql-server

I have the following error when I run a stored procedure in SQL:
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.
What does this mean? How could I solve it?
Thank you very much.
/****** Object: StoredProcedure [SingleDirectory].[SPTADIR_EntityIdentification] Script Date: 26/04/2021 9:37:41 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [SingleDirectory].[SPTADIR_EntityIdentification]
-- Add the parameters for the stored procedure here
#xmlEntity nvarchar(MAX) = NULL
AS
SET XACT_ABORT ON
BEGIN TRAN
BEGIN TRY
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE
#handle int,
#currentDateTime datetime
-- =============================================
--- Protection Against Concurrent Executions
-- =============================================
DECLARE #RC INT
DECLARE #message VARCHAR(500)
SELECT #message = CONVERT(VARCHAR(30), GETDATE(), 121) + ': Try to obtain a lock ..'
--RAISERROR(#message, 0, 1) WITH NOWAIT;
EXEC #RC = sp_getapplock
#Resource = '[SingleDirectory].[SPTADIR_EntityIdentification]',
#LockMode = 'Exclusive',
#LockOwner = 'Transaction',
#LockTimeout = 6000 -- 0.1 minute
IF #RC < 0
BEGIN
IF ##TRANCOUNT > 0 ROLLBACK TRAN;
SELECT #message = CONVERT(VARCHAR(30), GETDATE(), 121) + ': Sorry, could not obtain a lock within the timeout period, return code was ' + CONVERT(VARCHAR(30), #RC) + '.'
--RAISERROR(#message, 0, 1) WITH NOWAIT;
RETURN #RC
END
ELSE
BEGIN
SELECT #message = CONVERT(VARCHAR(30), GETDATE(), 121) + ': AppLock obtained ..'
--RAISERROR(#message, 0, 1) WITH NOWAIT;
END
-- ******************************
-- 1.- Creates tables
-- ******************************
-- TADIR_Entity identification
CREATE TABLE [#tmpEntity] (
[EntityId] [int] NULL,
[EntityType] [int] NOT NULL,
[VendorId] [int] NULL,
[ProviderEntityId] [varchar](100) COLLATE Latin1_General_100_CI_AS_SC NULL,
[FiscalId] [varchar](15) COLLATE Latin1_General_100_CI_AS_SC NULL,
[BusinessName] [nvarchar](150) COLLATE Latin1_General_100_CI_AS_SC NULL,
[AddressName] [varchar](100) COLLATE Latin1_General_100_CI_AS_SC NULL,
[PostalCode] [varchar](10) COLLATE Latin1_General_100_CI_AS_SC NULL,
[CityName] [varchar](50) COLLATE Latin1_General_100_CI_AS_SC NULL,
[CountryDescr] [varchar](50) COLLATE Latin1_General_100_CI_AS_SC NULL,
[StateId] [int] NULL,
[PhoneNbr] [varchar](20) COLLATE Latin1_General_100_CI_AS_SC NULL,
[SystemId] [int] NULL,
[ActiveFlag] [bit] NOT NULL,
[ISO2Value] [varchar](2) COLLATE Latin1_General_100_CI_AS_SC NULL,
[ISO3Value] [varchar](3) COLLATE Latin1_General_100_CI_AS_SC NULL,
[InfoBusinessTypeId] [int] NULL
)
CREATE CLUSTERED INDEX INDEXEntityId ON [#tmpEntity] (EntityId)
CREATE NONCLUSTERED INDEX INDEXProviderEntityId ON [#tmpEntity] (ISO2Value, ProviderEntityId, EntityId)
CREATE NONCLUSTERED INDEX INDEXFiscalId ON [#tmpEntity] (ISO2Value, FiscalId, EntityId)
-- New TADIR_Entity
CREATE TABLE [#tmpEntityInserted] (
[EntityId] [int] NULL,
[VendorId] [int] NULL,
[ProviderEntityId] [varchar](100) COLLATE Latin1_General_100_CI_AS_SC NULL
)
CREATE CLUSTERED INDEX INDEXProviderEntityId ON [#tmpEntityInserted] (VendorId, ProviderEntityId)
-- TADIR_EntityIDs
CREATE TABLE [#tmpEntityIDs] (
[EntityId] [int] NULL,
[VendorId] [int] NULL,
[ProviderEntityId] [varchar](100) COLLATE Latin1_General_100_CI_AS_SC NULL,
[IDType] [tinyint] NULL,
[IdentificationValue] [varchar](50) COLLATE Latin1_General_100_CI_AS_SC NULL
)
CREATE NONCLUSTERED INDEX INDEXProviderEntityId ON [#tmpEntityIDs] (VendorId, ProviderEntityId)
CREATE NONCLUSTERED INDEX INDEXEntityId ON [#tmpEntityIDs] (EntityId, IDType)
-- ******************************
-- 2.- Parses XML and inserts into [#tmpEntity] and [#tmpEntityIDs]
-- ******************************
-- XML
CREATE TABLE [#tmpEntityXml] (
[EntityId] [int] NULL,
[EntityType] [int] NOT NULL,
[VendorId] [int] NULL,
[ProviderEntityId] [varchar](100) COLLATE Latin1_General_100_CI_AS_SC NULL,
[FiscalId] [varchar](15) COLLATE Latin1_General_100_CI_AS_SC NULL,
[BusinessName] [nvarchar](150) COLLATE Latin1_General_100_CI_AS_SC NULL,
[AddressName] [varchar](100) COLLATE Latin1_General_100_CI_AS_SC NULL,
[PostalCode] [varchar](10) COLLATE Latin1_General_100_CI_AS_SC NULL,
[CityName] [varchar](50) COLLATE Latin1_General_100_CI_AS_SC NULL,
[CountryDescr] [varchar](50) COLLATE Latin1_General_100_CI_AS_SC NULL,
[StateId] [int] NULL,
[PhoneNbr] [varchar](20) COLLATE Latin1_General_100_CI_AS_SC NULL,
[SystemId] [int] NULL,
[ActiveFlag] [bit] NOT NULL,
[ISO2Value] [varchar](2) COLLATE Latin1_General_100_CI_AS_SC NULL,
[ISO3Value] [varchar](3) COLLATE Latin1_General_100_CI_AS_SC NULL,
[InfoBusinessTypeId] [int] NULL,
[IDType] [tinyint] NULL,
[IdentificationValue] [varchar](50) COLLATE Latin1_General_100_CI_AS_SC NULL
)
exec sp_xml_preparedocument #handle OUTPUT, #xmlEntity
INSERT INTO [#tmpEntityXml] (
[EntityId],
[EntityType],
[VendorId],
[ProviderEntityId],
[FiscalId],
[BusinessName],
[AddressName],
[PostalCode],
[CityName],
[CountryDescr],
[StateId],
[PhoneNbr],
[SystemId],
[ActiveFlag],
[ISO2Value],
[ISO3Value],
[InfoBusinessTypeId],
[IDType],
[IdentificationValue])
SELECT (CASE WHEN EntityId = 0 THEN NULL ELSE EntityId END) AS EntityId,
EntityType,
(CASE WHEN VendorId = 0 THEN NULL ELSE VendorId END) AS VendorId,
(CASE WHEN ProviderEntityId IS NULL THEN NULL ELSE ProviderEntityId END) AS ProviderEntityId,
FiscalId,
BusinessName,
AddressName,
PostalCode,
CityName,
CountryDescr,
(CASE WHEN StateId = 0 THEN NULL ELSE StateId END) AS StateId,
PhoneNbr,
(CASE WHEN SystemId = 0 THEN NULL ELSE SystemId END) AS SystemId,
ActiveFlag,
ISO2Value,
ISO3Value,
(CASE WHEN InfoBusinessTypeId = 0 THEN NULL ELSE InfoBusinessTypeId END) AS InfoBusinessTypeId,
(CASE WHEN IDType = 0 THEN NULL ELSE IDType END) AS IDType,
IdentificationValue
FROM OPENXML (#handle, 'ArrayOfIdentificationEntity/IdentificationEntity',3)
WITH (
EntityId int 'EntityId',
EntityType int 'EntityType',
VendorId int 'VendorId',
ProviderEntityId varchar(100) 'ProviderEntityId',
FiscalId varchar(15) 'FiscalId',
BusinessName nvarchar(150) 'BusinessName',
AddressName varchar(100) 'AddressName',
PostalCode varchar(10) 'PostalCode',
CityName varchar(50) 'CityName',
CountryDescr varchar(50) 'CountryDescr',
StateId int 'StateId',
PhoneNbr varchar(20) 'PhoneNbr',
SystemId int 'SystemId',
ActiveFlag bit 'ActiveFlag',
ISO2Value varchar(2) 'ISO2Value',
ISO3Value varchar(3) 'ISO3Value',
InfoBusinessTypeId int 'InfoBusinessTypeId',
IDType tinyint 'IDType',
IdentificationValue varchar(50) 'IdentificationValue') AS fbEntity
EXEC sp_xml_removedocument #handle
UPDATE [#tmpEntityXml]
SET EntityId = [SingleDirectory].[TADIR_Entity].EntityId
FROM [SingleDirectory].[TADIR_Entity]
INNER JOIN [#tmpEntityXml]
ON ([SingleDirectory].[TADIR_Entity].[VendorId] = [#tmpEntityXml].[VendorId]
AND [SingleDirectory].[TADIR_Entity].[ProviderEntityId] = [#tmpEntityXml].[ProviderEntityId] AND [SingleDirectory].[TADIR_Entity].EntityType = [#tmpEntityXml].EntityType)
UPDATE [#tmpEntityXml]
SET EntityId = [SingleDirectory].[TADIR_Entity].EntityId
FROM [SingleDirectory].[TADIR_Entity]
INNER JOIN [#tmpEntityXml]
ON ([SingleDirectory].[TADIR_Entity].[VendorId] = [#tmpEntityXml].[VendorId]
AND [SingleDirectory].[TADIR_Entity].FiscalId = [#tmpEntityXml].FiscalId AND [SingleDirectory].[TADIR_Entity].EntityType = [#tmpEntityXml].EntityType)
-- Inserts tmpEntity
INSERT INTO [#tmpEntity]
([EntityId], [EntityType], [VendorId], [ProviderEntityId],
[FiscalId], [BusinessName], [AddressName], [PostalCode],
[CityName], [CountryDescr], [StateId], [PhoneNbr],
[SystemId], [ActiveFlag], [ISO2Value], [ISO3Value],
[InfoBusinessTypeId])
SELECT DISTINCT [EntityId], [EntityType], [VendorId], [ProviderEntityId],
[FiscalId], [BusinessName], [AddressName], [PostalCode],
[CityName], [CountryDescr], [StateId], [PhoneNbr], [SystemId],
[ActiveFlag], [ISO2Value], [ISO3Value], [InfoBusinessTypeId]
FROM [#tmpEntityXml]
WHERE VendorId IS NOT NULL AND ProviderEntityId IS NOT NULL AND ISO2Value IS NOT NULL
-- Inserts tmpEntityIDs
INSERT INTO [#tmpEntityIDs]
([EntityId], [VendorId], [ProviderEntityId], [IDType], [IdentificationValue])
SELECT DISTINCT [EntityId], [VendorId], [ProviderEntityId], [IDType], [IdentificationValue]
FROM [#tmpEntityXml]
WHERE VendorId IS NOT NULL AND ProviderEntityId IS NOT NULL AND ISO2Value IS NOT NULL AND
IDType IS NOT NULL AND IdentificationValue IS NOT NULL
-- Drops table
DROP TABLE [#tmpEntityXml];
-- ******************************
-- 3.- TADIR_Entity
-- ******************************
-- 3.1.- Update TADIR_Entity (when necessary)
UPDATE [SingleDirectory].[TADIR_Entity]
SET [ActiveFlag] = [#tmpEntity].[ActiveFlag],
[AddressName] = (CASE WHEN [#tmpEntity].[AddressName] IS NOT NULL THEN [#tmpEntity].[AddressName] ELSE [SingleDirectory].[TADIR_Entity].[AddressName] END),
[BusinessName] = (CASE WHEN [#tmpEntity].[BusinessName] IS NOT NULL THEN [#tmpEntity].[BusinessName] ELSE [SingleDirectory].[TADIR_Entity].[BusinessName] END),
[CityName] = (CASE WHEN [#tmpEntity].[CityName] IS NOT NULL THEN [#tmpEntity].[CityName] ELSE [SingleDirectory].[TADIR_Entity].[CityName] END),
[CountryDescr] = (CASE WHEN [#tmpEntity].[CountryDescr] IS NOT NULL THEN [#tmpEntity].[CountryDescr] ELSE [SingleDirectory].[TADIR_Entity].[CountryDescr] END),
[EntityType] = [#tmpEntity].[EntityType],
[FiscalId] = (CASE WHEN [#tmpEntity].[FiscalId] IS NOT NULL THEN [#tmpEntity].[FiscalId] ELSE [SingleDirectory].[TADIR_Entity].[FiscalId] END),
[ISO2Value] = (CASE WHEN [#tmpEntity].[ISO2Value] IS NOT NULL THEN [#tmpEntity].[ISO2Value] ELSE [SingleDirectory].[TADIR_Entity].[ISO2Value] END),
[ISO3Value] = (CASE WHEN [#tmpEntity].[ISO3Value] IS NOT NULL THEN [#tmpEntity].[ISO3Value] ELSE [SingleDirectory].[TADIR_Entity].[ISO3Value] END),
[InfoBusinessTypeId] = (CASE WHEN [#tmpEntity].[InfoBusinessTypeId] IS NOT NULL THEN [#tmpEntity].[InfoBusinessTypeId] ELSE [SingleDirectory].[TADIR_Entity].[InfoBusinessTypeId] END),
[PhoneNbr] = (CASE WHEN [#tmpEntity].[PhoneNbr] IS NOT NULL THEN [#tmpEntity].[PhoneNbr] ELSE [SingleDirectory].[TADIR_Entity].[PhoneNbr] END),
[PostalCode] = (CASE WHEN [#tmpEntity].[PostalCode] IS NOT NULL THEN [#tmpEntity].[PostalCode] ELSE [SingleDirectory].[TADIR_Entity].[PostalCode] END),
[ProviderEntityId] = (CASE WHEN [#tmpEntity].[ProviderEntityId] IS NOT NULL THEN [#tmpEntity].[ProviderEntityId] ELSE [SingleDirectory].[TADIR_Entity].[ProviderEntityId] END),
[StateId] = (CASE WHEN [#tmpEntity].[StateId] NOT LIKE 0 THEN [#tmpEntity].[StateId] ELSE [SingleDirectory].[TADIR_Entity].[StateId] END),
[SystemId] = (CASE WHEN [SingleDirectory].[TADIR_Entity].[SystemId] IS NULL THEN [#tmpEntity].[SystemId] ELSE [SingleDirectory].[TADIR_Entity].[SystemId] END),
[VendorId] = [#tmpEntity].[VendorId],
[UpdateDate] = GETUTCDATE()
FROM [SingleDirectory].[TADIR_Entity]
INNER JOIN [#tmpEntity]
ON ([SingleDirectory].[TADIR_Entity].[EntityId] = [#tmpEntity].[EntityId])
WHERE ([SingleDirectory].[TADIR_Entity].[ActiveFlag] IS NULL AND [#tmpEntity].[ActiveFlag] IS NOT NULL) OR ([SingleDirectory].[TADIR_Entity].[ActiveFlag] IS NOT NULL AND [#tmpEntity].[ActiveFlag] IS NULL) OR [SingleDirectory].[TADIR_Entity].[ActiveFlag]
NOT LIKE [#tmpEntity].[ActiveFlag]
OR ( [#tmpEntity].[AddressName] IS NOT NULL AND ([SingleDirectory].[TADIR_Entity].[AddressName] IS NULL OR [SingleDirectory].[TADIR_Entity].[AddressName] NOT LIKE [#tmpEntity].[AddressName]))
OR ( [#tmpEntity].[BusinessName] IS NOT NULL AND ([SingleDirectory].[TADIR_Entity].[BusinessName] IS NULL OR [SingleDirectory].[TADIR_Entity].[BusinessName] NOT LIKE [#tmpEntity].[BusinessName]))
OR ( [#tmpEntity].[CityName] IS NOT NULL AND ([SingleDirectory].[TADIR_Entity].[CityName] IS NULL OR [SingleDirectory].[TADIR_Entity].[CityName] NOT LIKE [#tmpEntity].[CityName]))
OR ( [#tmpEntity].[CountryDescr] IS NOT NULL AND ([SingleDirectory].[TADIR_Entity].[CountryDescr] IS NULL OR [SingleDirectory].[TADIR_Entity].[CountryDescr] NOT LIKE [#tmpEntity].[CountryDescr]))
OR ( [SingleDirectory].[TADIR_Entity].[EntityType] IS NULL AND [#tmpEntity].[EntityType] IS NOT NULL) OR ([SingleDirectory].[TADIR_Entity].[EntityType] IS NOT NULL AND [#tmpEntity].[EntityType] IS NULL) OR [SingleDirectory].[TADIR_Entity].[EntityType] NOT LIKE [#tmpEntity].[EntityType]
OR ( [#tmpEntity].[FiscalId] IS NOT NULL AND ([SingleDirectory].[TADIR_Entity].[FiscalId] IS NULL OR [SingleDirectory].[TADIR_Entity].[FiscalId] NOT LIKE [#tmpEntity].[FiscalId]))
OR ( [#tmpEntity].[ISO2Value] IS NOT NULL AND ([SingleDirectory].[TADIR_Entity].[ISO2Value] IS NULL OR [SingleDirectory].[TADIR_Entity].[ISO2Value] NOT LIKE [#tmpEntity].[ISO2Value]))
OR ( [#tmpEntity].[ISO3Value] IS NOT NULL AND ([SingleDirectory].[TADIR_Entity].[ISO3Value] IS NULL OR [SingleDirectory].[TADIR_Entity].[ISO3Value] NOT LIKE [#tmpEntity].[ISO3Value]))
OR ( [#tmpEntity].[InfoBusinessTypeId] IS NOT NULL AND ([SingleDirectory].[TADIR_Entity].[InfoBusinessTypeId] IS NULL OR [SingleDirectory].[TADIR_Entity].[InfoBusinessTypeId] NOT LIKE [#tmpEntity].[InfoBusinessTypeId]))
OR ( [#tmpEntity].[PhoneNbr] IS NOT NULL AND ([SingleDirectory].[TADIR_Entity].[PhoneNbr] IS NULL OR [SingleDirectory].[TADIR_Entity].[PhoneNbr] NOT LIKE [#tmpEntity].[PhoneNbr]))
OR ( [#tmpEntity].[PostalCode] IS NOT NULL AND ([SingleDirectory].[TADIR_Entity].[PostalCode] IS NULL OR [SingleDirectory].[TADIR_Entity].[PostalCode] NOT LIKE [#tmpEntity].[PostalCode]))
OR ( [SingleDirectory].[TADIR_Entity].[ProviderEntityId] IS NULL AND [#tmpEntity].[ProviderEntityId] IS NOT NULL) OR ([SingleDirectory].[TADIR_Entity].[ProviderEntityId] IS NOT NULL AND [#tmpEntity].[ProviderEntityId] IS NULL) OR [SingleDirectory].[TADIR_Entity].[ProviderEntityId] NOT LIKE [#tmpEntity].[ProviderEntityId]
OR ( [#tmpEntity].[StateId] NOT LIKE 0 AND ([SingleDirectory].[TADIR_Entity].[StateId] IS NULL OR [SingleDirectory].[TADIR_Entity].[StateId] NOT LIKE [#tmpEntity].[StateId]))
OR ([SingleDirectory].[TADIR_Entity].[SystemId] IS NULL)
OR ( [SingleDirectory].[TADIR_Entity].[VendorId] IS NULL AND [#tmpEntity].[VendorId] IS NOT NULL) OR ( [SingleDirectory].[TADIR_Entity].[VendorId] IS NOT NULL AND [#tmpEntity].[VendorId] IS NULL) OR [SingleDirectory].[TADIR_Entity].[VendorId] NOT LIKE [#tmpEntity].[VendorId]
-- 3.2.- INSERTS into TADIR_Entity not identified emtotoes
SET #currentDateTime = GETUTCDATE()
-- INSERT INTO TADIR_Entity
INSERT INTO [SingleDirectory].[TADIR_Entity] ([EntityType],
[VendorId],
[ProviderEntityId],
[FiscalId],
[BusinessName],
[AddressName],
[PostalCode],
[CityName],
[CountryDescr],
[StateId],
[PhoneNbr],
[SystemId],
[ActiveFlag],
[ISO2Value],
[ISO3Value],
[InfoBusinessTypeId],
[CreationDate],
[UpdateDate])
OUTPUT INSERTED.EntityId, INSERTED.VendorId, INSERTED.ProviderEntityId INTO [#tmpEntityInserted]
SELECT [#tmpEntity].[EntityType],
[#tmpEntity].[VendorId],
[#tmpEntity].[ProviderEntityId],
[#tmpEntity].[FiscalId],
[#tmpEntity].[BusinessName],
[#tmpEntity].[AddressName],
[#tmpEntity].[PostalCode],
[#tmpEntity].[CityName],
[#tmpEntity].[CountryDescr],
[#tmpEntity].[StateId],
[#tmpEntity].[PhoneNbr],
[#tmpEntity].[SystemId],
[#tmpEntity].[ActiveFlag],
[#tmpEntity].[ISO2Value],
[#tmpEntity].[ISO3Value],
[#tmpEntity].[InfoBusinessTypeId],
#currentDateTime,
#currentDateTime
FROM [#tmpEntity]
WHERE [#tmpEntity].[EntityId] IS NULL
-- UPDATE [#tmpEntityXml].[EntityId]
UPDATE [#tmpEntity]
SET [EntityId] = [#tmpEntityInserted].[EntityId]
FROM [#tmpEntity]
INNER JOIN [#tmpEntityInserted]
ON ([#tmpEntity].[ProviderEntityId] = [#tmpEntityInserted].[ProviderEntityId]
AND [#tmpEntity].[VendorId] = [#tmpEntityInserted].[VendorId])
-- 3.3.- Update EntityId ON [#tmpEntityIDs]
UPDATE [#tmpEntityIDs]
SET [EntityId] = [#tmpEntity].[EntityId]
FROM [#tmpEntityIDs]
INNER JOIN [#tmpEntity]
ON ([#tmpEntityIDs].[VendorId] = [#tmpEntity].[VendorId]
AND [#tmpEntityIDs].[ProviderEntityId] = [#tmpEntity].[ProviderEntityId]
AND [#tmpEntityIDs].[EntityId] IS NULL)
-- ******************************
-- 4.- TADIR_EntityIDs
-- ******************************
-- 4.1.- DELETE old values
DELETE [SingleDirectory].[TADIR_EntityIDs]
FROM [SingleDirectory].[TADIR_EntityIDs]
INNER JOIN [#tmpEntity]
ON ([SingleDirectory].[TADIR_EntityIDs].[EntityId] = [#tmpEntity].[EntityId])
LEFT JOIN [#tmpEntityIDs]
ON ([SingleDirectory].[TADIR_EntityIDs].[EntityId] = [#tmpEntityIDs].[EntityId]
AND [SingleDirectory].[TADIR_EntityIDs].[IDType] = [#tmpEntityIDs].[IDType])
WHERE [#tmpEntityIDs].[EntityId] IS NULL
-- 4.2.- UPDATE values
UPDATE [SingleDirectory].[TADIR_EntityIDs]
SET [IdentificationValue] = [#tmpEntityIDs].[IdentificationValue]
FROM [SingleDirectory].[TADIR_EntityIDs]
INNER JOIN [#tmpEntityIDs]
ON ([#tmpEntityIDs].[EntityId] = [SingleDirectory].[TADIR_EntityIDs].[EntityId] AND
[#tmpEntityIDs].[IDType] = [SingleDirectory].[TADIR_EntityIDs].[IDType])
WHERE [#tmpEntityIDs].[IdentificationValue] NOT LIKE [SingleDirectory].[TADIR_EntityIDs].[IdentificationValue]
-- 4.3.- INSERT values
INSERT INTO [SingleDirectory].[TADIR_EntityIDs] ([EntityId],
[IDType],
[IdentificationValue])
SELECT [#tmpEntityIDs].[EntityId],
[#tmpEntityIDs].[IDType],
[#tmpEntityIDs].[IdentificationValue]
FROM [#tmpEntityIDs]
LEFT JOIN [SingleDirectory].[TADIR_EntityIDs]
ON ([#tmpEntityIDs].[EntityId] = [SingleDirectory].[TADIR_EntityIDs].[EntityId]
AND [#tmpEntityIDs].[IDType] = [SingleDirectory].[TADIR_EntityIDs].[IDType])
WHERE [SingleDirectory].[TADIR_EntityIDs].[EntityId] IS NULL
-- ******************************
-- 5.- Loads the return results.
-- ******************************
SELECT DISTINCT [SingleDirectory].[TADIR_Entity].*, [SingleDirectory].[TADIR_EntityIDs].[IDType], [SingleDirectory].[TADIR_EntityIDs].[IdentificationValue]
FROM [SingleDirectory].[TADIR_Entity]
INNER JOIN [#tmpEntity]
ON ([SingleDirectory].[TADIR_Entity].[EntityId] = [#tmpEntity].[EntityId] )
LEFT JOIN [SingleDirectory].[TADIR_EntityIDs]
ON ([SingleDirectory].[TADIR_Entity].[EntityId] = [SingleDirectory].[TADIR_EntityIDs].[EntityId])
WHERE [#tmpEntity].[EntityId] IS NOT NULL
-- ******************************
-- 6.- Free memory
-- ******************************
DROP INDEX INDEXEntityId ON [#tmpEntity]
DROP INDEX INDEXProviderEntityId ON [#tmpEntity]
DROP INDEX INDEXFiscalId ON [#tmpEntity]
DROP TABLE [#tmpEntity]
DROP INDEX INDEXProviderEntityId ON [#tmpEntityInserted]
DROP TABLE [#tmpEntityInserted]
DROP INDEX INDEXProviderEntityId ON [#tmpEntityIDs]
DROP INDEX INDEXEntityId ON [#tmpEntityIDs]
DROP TABLE [#tmpEntityIDs]
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRAN;
INSERT INTO [Log].[tasip_errorlogdb]
(errorcode,
errorstatusvalue,
procedurevalue,
descriptionmessagetext,
wrongtracecode,
date)
VALUES (Error_number(),
Error_state(),
Error_procedure(),
Error_message(),
Error_line(),
Getutcdate());
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH
IF ##TRANCOUNT > 0
COMMIT TRAN;

Related

Executing a stored procedure by picking SQL variable from a list in T-SQL without using Cursor

I have a list of values, and i need the variable to pick it up one by one and execute the commands below. I need to achieve something like below in T-SQL. Is it possible without cursors?
SET NOCOUNT ON;
DECLARE #IPA VARCHAR(10)
FOR #IPA IN ['ADV, 'AC','AHA','ALPEB','AG','APCWEB]
IF OBJECT_ID('[ESProcess].[dbo].[EJ_Test]') IS NOT NULL
DROP TABLE [ESProcess].[dbo].[EJ_Test]
CREATE TABLE [ESProcess].[dbo].[EJ_Test]
(
[PRIM] [varchar](50) NULL,
[CLAIM_ID] [varchar](100) NULL,
[P_CLAIMNO] [varchar](100) NULL,
[Pro] [varchar](3) NULL,
[VALUE] [varchar](50) NULL,
[ErrorCode] [int] NULL,
[DESCRIP] [varchar](500) NULL,
[FILENAME] [varchar](300) NULL
)
INSERT INTO [ESProcess].[dbo].[EJ_Test]
SELECT
PRIM,a.CLAIM_ID,P_CLAIMNO, Pro, u.VALUE,
NULL AS ErrorCode, NULL AS DESCRIP, [FILENAME]
FROM
[SPID].[#IPA].[dbo].837_in_1 a
JOIN
[SPID].[#IPA].[dbo].[837_In_U] u ON a.ED_ID = u.M_ID
WHERE
a.CREATEDATE >= '20221001'
AND u.FNO = '20'
AND Pro = 'D'
END
Here. Note that drop-creating the table means that at the end you will only have data from APCWEB.
SET NOCOUNT ON;
DECLARE #IPA VARCHAR(10)
declare #sql nvarchar(max)
create table #ipas
(
ord int
,ipa varchar(10)
)
insert #ipas(ord,ipa) values
(1,'ADV')
,(2,'AC')
,(3,'AHA')
,(4,'ALPEB')
,(5,'AG')
,(6,'APCWEB')
declare ipa_cursor cursor local fast_forward for
select ipa from #ipas order by ord
open ipa_cursor
while 1=1
begin
fetch next from ipa_cursor into #IPA
if ##fetch_status<>0 break
set #sql=N''+
'IF OBJECT_ID(''[ESProcess].[dbo].[EJ_Test]'') IS NOT NULL
DROP TABLE [ESProcess].[dbo].[EJ_Test]
CREATE TABLE [ESProcess].[dbo].[EJ_Test]
(
[PRIM] [varchar](50) NULL,
[CLAIM_ID] [varchar](100) NULL,
[P_CLAIMNO] [varchar](100) NULL,
[Pro] [varchar](3) NULL,
[VALUE] [varchar](50) NULL,
[ErrorCode] [int] NULL,
[DESCRIP] [varchar](500) NULL,
[FILENAME] [varchar](300) NULL
)
INSERT INTO [ESProcess].[dbo].[EJ_Test]
SELECT
PRIM,a.CLAIM_ID,P_CLAIMNO, Pro, u.VALUE,
NULL AS ErrorCode, NULL AS DESCRIP, [FILENAME]
FROM
[SPID].'+quotename(#IPA)+'.[dbo].837_in_1 a
JOIN
[SPID].'+quotename(#IPA)+'.[dbo].[837_In_U] u ON a.ED_ID = u.M_ID
WHERE
a.CREATEDATE >= ''20221001''
AND u.FNO = ''20''
AND Pro = ''D'''
exec sp_executesql #sql
end -- cursor while
close ipa_cursor
deallocate ipa_cursor

After Trigger for Update and Insert failing

I am writing a trigger for keeping audit record for one table for Insert and Update records.
CREATE TABLE [dbo].[AppLog](
[TableName] [varchar](32) NOT NULL,
[ColumnName] [varchar](32) NOT NULL,
[RecordId] [varchar](20) NOT NULL,
[OldValue] [varchar](2000) NULL,
[NewValue] [varchar](2000) NULL,
[UpdatedBy] [varchar](200) NULL,
[UpdatedOn] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Persons](
[Personid] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](255) NOT NULL,
[FirstName] [varchar](255) NULL,
[Age] [int] NULL
) ON [PRIMARY]
GO
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT
AS
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,UpdatedBy ,UpdatedOn )
SELECT 'Persons', 'LastName', COALESCE(i.Personid,NULL),
d.LastName, i.LastName, CURRENT_USER, GETDATE()
FROM Persons pv
LEFT JOIN INSERTED i ON pv.Personid = i.Personid
LEFT JOIN DELETED d ON pv.Personid = d.Personid;
GO
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('Satish','Parida',40);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('SKP','Tada',90);
The last insert is failing as it is trying to insert null to recordid column in applog table, could someone explain or fix the issue.
The statement that is failing is the one below:
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('SKP','Tada',90);
This is because in your Trigger you are using Persons are your "base" table and the performing a LEFT JOIN to both inserted and deleted. As result when you try to perform the above INSERT, values from the previous INSERT are used as well in the trigger's dataset. The person 'Parida' doesn't appear in the table inserted for your second INSERT, and so COALESCE(i.Personid,NULL) returns NULL; as I mentioned in my comment, there' no point using COALESCE to return NULL, as if an expression's value evaluates to NULL it will return NULL. As RecordID (which is what COALESCE(i.Personid,NULL) is being inserted into) can't have the value NULL the INSERT fails and the whole transaction is rolled back.
I suspect that what you want for your trigger is the below:
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT
AS BEGIN
INSERT INTO AppLog (TableName,
ColumnName,
RecordId,
OldValue,
NewValue,
UpdatedBy,
UpdatedOn)
SELECT 'Persons',
'LastName',
i.Personid,
d.LastName,
i.LastName,
CURRENT_USER,
GETDATE()
FROM inserted AS i
LEFT JOIN deleted AS d ON i.Personid = d.Personid;
END;
inserted will always have at least 1 row for an UPDATE or an INSERT. inserted would not for a DELETE, but your trigger won't fire on that DML event so using inserted as the "base" table seems the correct choice.
Following code should work
CREATE TABLE [dbo].[AppLog](
[TableName] [varchar](32) NOT NULL,
[ColumnName] [varchar](32) NOT NULL,
[RecordId] [varchar](20) NOT NULL,
[OldValue] [varchar](2000) NULL,
[NewValue] [varchar](2000) NULL,
[UpdatedBy] [varchar](200) NULL,
[UpdatedOn] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Persons](
[Personid] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](255) NOT NULL,
[FirstName] [varchar](255) NULL,
[Age] [int] NULL
) ON [PRIMARY]
GO
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT
AS
if exists(SELECT * from inserted) and exists (SELECT * from deleted)
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,UpdatedBy ,UpdatedOn )
SELECT 'Persons', 'LastName', COALESCE(i.Personid,NULL),
d.LastName, i.LastName, CURRENT_USER, GETDATE()
FROM Persons pv
INNER JOIN INSERTED i ON pv.Personid = i.Personid
INNER JOIN DELETED d ON pv.Personid = d.Personid;
END
If exists (Select * from inserted) and not exists(Select * from deleted)
begin
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,UpdatedBy ,UpdatedOn )
SELECT
'Persons', 'LastName',i.Personid,NULL,i.LastName,CURRENT_USER,GETDATE()
FROM
inserted AS i
END
GO
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('Satish','Parida',40);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('SKP','Tada',90);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('abc','def',90);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('gg','hh',90);
UPDATE dbo.Persons SET LastName='Paridachanged' WHERE Personid=1
SELECT * FROM Persons
SELECT * FROM AppLog
USE KnockKnockDev;
GO
IF OBJECT_ID('dbo.AuditRecord', 'TR') IS NOT NULL
DROP TRIGGER dbo.AuditRecord;
GO
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT, DELETE
AS
DECLARE #Action as char(1)
DECLARE #Count as int
DECLARE #TableName as char(32)
DECLARE #ColumnName as char (32)
SET #TableName = 'Persons'
SET #ColumnName = 'LastName'
SET #Action = 'I' -- Set Action to 'I'nsert by default.
SELECT #Count = COUNT(*) FROM DELETED
IF #Count > 0
BEGIN
SELECT #Count = COUNT(*) FROM INSERTED
IF #Count > 0
SET #Action = 'U' -- Set Action to 'U'pdated.
ELSE
SET #Action = 'D' -- Set Action to 'D'eleted.
END
IF #Action = 'I'
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,Action ,UpdatedBy ,UpdatedOn )
SELECT #TableName, #ColumnName, Personid,
NULL, LastName, #Action, CURRENT_USER, GETDATE()
FROM INSERTED;
END
ELSE IF #Action = 'D'
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,Action ,UpdatedBy ,UpdatedOn )
SELECT #TableName, #ColumnName, Personid,
LastName, NULL, #Action, CURRENT_USER, GETDATE()
FROM DELETED;
END
ELSE
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,Action ,UpdatedBy ,UpdatedOn )
SELECT #TableName, #ColumnName, i.Personid,
d.LastName, i.LastName, #Action, CURRENT_USER, GETDATE()
FROM Persons pv
INNER JOIN INSERTED i ON pv.Personid = i.Personid
INNER JOIN DELETED d ON pv.Personid = d.Personid;
END
GO

Computed column slows down query performance in SQL Server 2012

In my select statement, the column DisplayStatus is a computed column that significantly slows down the performance.
I tried to make it PERSISTENT but it tells me that table need to be dropped and recreated again. I cannot do that, I am not the owner of those tables.
Scalar function (pretty complex) is responsible for computed column.
My select statement:
declare
#EffDateFrom datetime ='2017-02-01',
#EffDateTo datetime ='2017-08-28'
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
IF OBJECT_ID('tempdb..#Data') IS NOT NULL
DROP TABLE #Data
CREATE TABLE #Data
(
QuoteID int NOT NULL,
[EffectiveDate] [datetime] NULL,
[Submitted] [int] NULL,
[Quoted] [int] NULL,
[Bound] [int] NULL,
[Exonerated] [int] NULL,
[ProducerLocationId] [int] NULL,
[ProducerName] [varchar](300) NULL,
[BusinessType] [varchar](50) NULL,
[DisplayStatus] [varchar](50) NULL, --This is the problem
[Agent] [varchar] (50) NULL,
[ProducerContactGuid] uniqueidentifier NULL
)
INSERT INTO #Data
SELECT
tblQuotes.QuoteID,
tblQuotes.EffectiveDate,
CASE
WHEN lstQuoteStatus.QuoteStatusID >= 1
THEN 1
ELSE 0
END AS Submitted,
CASE
WHEN lstQuoteStatus.QuoteStatusID = 2 OR
lstQuoteStatus.QuoteStatusID = 3 OR
lstQuoteStatus.QuoteStatusID = 202
THEN 1
ELSE 0
END AS Quoted,
CASE WHEN lstQuoteStatus.Bound = 1 THEN 1 ELSE 0 END AS Bound,
CASE WHEN lstQuoteStatus.QuoteStatusID = 3 THEN 1 ELSE 0 END AS Exonareted,
tblQuotes.ProducerLocationID,
P.Name + ' / '+ P.City as [ProducerName],
CASE
WHEN tblQuotes.PolicyTypeID = 1 THEN 'New Business'
WHEN tblQuotes.PolicyTypeID = 3 THEN 'Rewrite'
END AS BusinessType,
tblQuotes.DisplayStatus, -------------This is the problem
tblProducerContacts.FName +' '+ tblProducerContacts.LName as Agent,
tblProducerContacts.ProducerContactGUID
FROM
tblQuotes
INNER JOIN
lstQuoteStatus ON tblQuotes.QuoteStatusID = lstQuoteStatus.QuoteStatusID
INNER JOIN
tblProducerLocations P ON P.ProducerLocationID = tblQuotes.ProducerLocationID
INNER JOIN
tblProducerContacts ON dbo.tblQuotes.ProducerContactGuid = tblProducerContacts.ProducerContactGUID
WHERE
tblQuotes.EffectiveDate >= #EffDateFrom
AND tblQuotes.EffectiveDate <= #EffDateTo
AND dbo.tblQuotes.LineGUID = '6E00868B-FFC3-4CA0-876F-CC258F1ED22D'--Surety
AND tblQuotes.OriginalQuoteGUID IS NULL
SELECT * FROM #Data
Is any other workaround to bring this column without slowing down the performance?
Execution Plan:

Converting a working script into Stored procedure

Posted this question yesterday and got a solution as well. The solution script works fine as-is but when I converted it into a stored procedure it gives wrong results. Not able to identify where exactly I am messing up with the code.
Table Schema:
CREATE TABLE [dbo].[VMaster](
[VID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[VName] [varchar](30) NOT NULL
)
GO
CREATE TABLE [dbo].[TblMaster](
[SID] [int] IDENTITY(1,1) NOT NULL Primary Key,
[VID] [int] NOT NULL,
[CreatedDate] [datetime] default (getdate()) NOT NULL,
[CharToAdd] [varchar](10) NOT NULL,
[Start] [int] NOT NULL,
[End] [int] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[TblDetails](
[DetailsID] [int] IDENTITY(1,1) NOT NULL Primary Key,
[SID] [int] NOT NULL,
[Sno] [int] NOT NULL,
[ConcatenatedText] [varchar](20) NOT NULL,
[isIssued] [bit] default (0) NOT NULL,
[isUsed] [bit] default (0) NOT NULL
)
GO
ALTER TABLE [dbo].[TblMaster] WITH CHECK ADD CONSTRAINT [fk_SI_id] FOREIGN KEY([VID])
REFERENCES [dbo].[VMaster] ([VID])
GO
ALTER TABLE [dbo].[TblMaster] CHECK CONSTRAINT [fk_SI_id]
GO
Working solution:
CREATE FUNCTION [dbo].[udf-Create-Range-Number] (#R1 money,#R2 money,#Incr money)
-- Syntax Select * from [dbo].[udf-Create-Range-Number](0,100,2)
Returns
#ReturnVal Table (RetVal money)
As
Begin
With NumbTable as (
Select NumbFrom = #R1
union all
Select nf.NumbFrom + #Incr
From NumbTable nf
Where nf.NumbFrom < #R2
)
Insert into #ReturnVal(RetVal)
Select NumbFrom from NumbTable Option (maxrecursion 32767)
Return
End
Declare #Table table (SID int,VID int,CreateDate DateTime,CharToAdd varchar(25),Start int, [End] Int)
Insert Into #Table values
(1,1,'2016-06-30 19:56:14.560','ABC',1,5),
(2,1,'2016-06-30 19:56:14.560','XYZ',10,20),
(3,2,'2016-06-30 19:56:14.560','P1',10,15)
Declare #Min int,#Max int
Select #Min=min(Start),#Max=max([End]) From #Table
Select B.SID
,Sno = A.RetVal
,ConcetratedText = concat(B.CharToAdd,A.RetVal)
From (Select RetVal=Cast(RetVal as int) from [dbo].[udf-Create-Range-Number](#Min,#Max,1)) A
Join #Table B on A.RetVal Between B.Start and B.[End]
Order By B.Sid,A.RetVal
Stored procedure (This generates more records than the working solution!!)
CREATE PROCEDURE [dbo].[Add_Details]
(
#VID INT,
#CreatedDate DATETIME,
#CharToAdd VARCHAR(10),
#Start INT,
#End INT
)
AS
SET NOCOUNT ON
BEGIN
DECLARE #SID INT
INSERT INTO [dbo].[TblMaster] (VID, CreatedDate, CharToAdd, Start, [End])
VALUES (#VID, #CreatedDate, #CharToAdd, #Start, #End)
SET #SID = SCOPE_IDENTITY()
DECLARE #Min INT, #Max INT
SELECT #Min = #Start, #Max = #End
INSERT INTO [dbo].[TblDetails] (SID, Sno, [ConcatenatedText])
SELECT #SID
,Sno = A.RetVal
,ConcatenatedText = CONCAT(B.CharToAdd,A.RetVal)
FROM (SELECT RetVal = CAST(RetVal AS INT) FROM [dbo].[udf-Create-Range-Number](#Min,#Max,1)) A
JOIN dbo.TblMaster B ON A.RetVal BETWEEN B.Start AND B.[End]
ORDER BY B.SID,A.RetVal
END
GO
Declare #tmp datetime
Set #tmp = getdate()
EXEC [dbo].[Add_Details]
#VID = 1,
#CreatedDate = #tmp,
#CharToAdd = 'ABC',
#Start = 1,
#End = 5
EXEC [dbo].[Add_Details]
#VID = 1,
#CreatedDate = #tmp,
#CharToAdd = 'XYZ',
#Start = 10,
#End = 20
EXEC [dbo].[Add_Details]
#VID = 2,
#CreatedDate = #tmp,
#CharToAdd = 'P1',
#Start = 10,
#End = 15
Output of working script:
Output of the stored procedure:
You need to filter by VID on the second insert. It's picking up rows from previous executions. Since it only picks up other rows where the ranges are overlapping it doesn't always do it. Run the procedure a few more times and you'll see the duplication amplified a lot more. The reason it didn't do this in the original code was because you were using a temp table that was recreated each time you ran it.
INSERT INTO [dbo].[TblDetails] (SID, Sno, [ConcatenatedText])
SELECT #SID
,Sno = A.RetVal
,ConcatenatedText = CONCAT(B.CharToAdd,A.RetVal)
FROM (
SELECT RetVal = CAST(RetVal AS INT)
FROM [dbo].[udf-Create-Range-Number](#Min,#Max,1)) A
JOIN dbo.TblMaster B ON A.RetVal BETWEEN B.Start AND B.[End]
WHERE B.VID = #VID -- <<<---------
)
On a side note I would highly recommend changing that function to type int rather than money.

View that joins 2 tables of similar structure will not Update (because it contains a derived or constant field)

I'm getting an error:
Msg 4406, Level 16, State 1, Line 5
Update or insert of view or function 'dbo.vwEmployeeAll' failed because it contains a derived or constant field.
Yet, I have no derived or constant in my view.
The columns in my view all exist. It's fairly straightforward in the example below.
-- START TSQL
SET NOCOUNT ON
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'vwEmployeeAll' and TABLE_TYPE = N'VIEW' )
BEGIN
DROP VIEW [dbo].[vwEmployeeAll]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[EmployeeDeprecated]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[Employee]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Department' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[Department]
END
GO
CREATE TABLE [dbo].[Department](
[DepartmentUUID] [uniqueidentifier] NOT NULL,
[TheVersionProperty] [timestamp] NOT NULL,
[DepartmentName] [nvarchar](80) NULL,
[CreateDate] [datetime] NOT NULL
)
ALTER TABLE dbo.[Department] ADD CONSTRAINT PK_Department PRIMARY KEY NONCLUSTERED ([DepartmentUUID])
GO
ALTER TABLE [dbo].[Department] ADD CONSTRAINT CK_DepartmentName_Unique UNIQUE ([DepartmentName])
GO
CREATE TABLE [dbo].[Employee] (
/* [EmployeeUUID] [uniqueidentifier] NOT NULL, */
[EmployeeSurrogateKey] int not null IDENTITY(1,2),
[ParentDepartmentUUID] [uniqueidentifier] NOT NULL,
[TheVersionProperty] [timestamp] NOT NULL,
[SSN] [nvarchar](11) NOT NULL,
[LastName] [varchar](64) NOT NULL,
[FirstName] [varchar](64) NOT NULL,
[CreateDate] [datetime] NOT NULL,
[UpdateDate] [datetime] NOT NULL,
[HireDate] [datetime] NOT NULL
)
GO
ALTER TABLE dbo.Employee ADD CONSTRAINT PK_Employee PRIMARY KEY NONCLUSTERED (EmployeeSurrogateKey)
GO
ALTER TABLE [dbo].[Employee] ADD CONSTRAINT CK_Employee_SSN_Unique UNIQUE (SSN)
GO
ALTER TABLE [dbo].[Employee] ADD CONSTRAINT FK_EmployeeToDepartment FOREIGN KEY (ParentDepartmentUUID) REFERENCES dbo.Department (DepartmentUUID)
GO
/*
ALTER TABLE [dbo].[Employee]
ADD CONSTRAINT [CK_Employee_PK_IsOdd] CHECK ( ( [EmployeeSurrogateKey] % 2 ) != 0)
GO
*/
CREATE TABLE [dbo].[EmployeeDeprecated] (
/*[EmployeeDeprecatedUUID] [uniqueidentifier] NOT NULL,*/
[EmployeeDeprecatedSurrogateKey] int not null IDENTITY(2,2),
[ParentDepartmentUUID] [uniqueidentifier] NOT NULL,
[TheVersionProperty] [timestamp] NOT NULL,
[SSN] [nvarchar](11) NOT NULL,
[LastName] [varchar](64) NOT NULL,
[FirstName] [varchar](64) NOT NULL,
[CreateDate] [datetime] NOT NULL,
[UpdateDate] [datetime] NOT NULL,
[HireDate] [datetime] NOT NULL
)
GO
ALTER TABLE dbo.[EmployeeDeprecated] ADD CONSTRAINT PK_EmployeeDeprecated PRIMARY KEY NONCLUSTERED (EmployeeDeprecatedSurrogateKey)
GO
ALTER TABLE [dbo].[EmployeeDeprecated] ADD CONSTRAINT CK_EmployeeDeprecated_SSN_Unique UNIQUE (SSN)
GO
ALTER TABLE [dbo].[EmployeeDeprecated] ADD CONSTRAINT FK_EmployeeDeprecatedToDepartment FOREIGN KEY (ParentDepartmentUUID) REFERENCES dbo.Department (DepartmentUUID)
GO
/*
ALTER TABLE [dbo].[EmployeeDeprecated]
ADD CONSTRAINT [CK_EmployeeDeprecated_PK_IsEven] CHECK ( ( [EmployeeDeprecatedSurrogateKey] % 2 ) = 0)
GO
*/
CREATE VIEW dbo.vwEmployeeAll AS
Select
EmployeeSurrogateKey,ParentDepartmentUUID,TheVersionProperty,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate
from dbo.Employee
UNION --ALL
Select
/* EmployeeSurrogateKey = */
EmployeeDeprecatedSurrogateKey ,ParentDepartmentUUID,TheVersionProperty,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate
from dbo.EmployeeDeprecated
GO
declare #DepartmentUUID001 uniqueidentifier
select #DepartmentUUID001 = 'DDDDDDDD-0000-0000-0000-000000000101'
declare #DepartmentUUID002 uniqueidentifier
select #DepartmentUUID002 = 'DDDDDDDD-0000-0000-0000-000000000102'
INSERT INTO dbo.Department (DepartmentUUID , DepartmentName , CreateDate )
Select #DepartmentUUID001 , 'Department One' , CURRENT_TIMESTAMP
UNION
Select #DepartmentUUID002 , 'Department Two' , CURRENT_TIMESTAMP
/*
declare #EmployeeUUID001 uniqueidentifier
select #EmployeeUUID001 = 'EEEEEEEE-0000-0000-0000-000000001001'
declare #EmployeeUUID00A uniqueidentifier
select #EmployeeUUID00A = 'EEEEEEEE-0000-0000-AAAA-000000009001'
*/
INSERT INTO dbo.Employee (/*EmployeeUUID,*/ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate)
Select /*#EmployeeUUID001 ,*/ #DepartmentUUID001 , '111-11-1111' , 'Smith', 'John' , CURRENT_TIMESTAMP , CURRENT_TIMESTAMP , '01/01/2001'
INSERT INTO dbo.EmployeeDeprecated(/*EmployeeDeprecatedUUID,*/ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate)
Select /*#EmployeeUUID00A ,*/ #DepartmentUUID002 , '888-88-8888' , 'Jones', 'Mary' , CURRENT_TIMESTAMP , CURRENT_TIMESTAMP , '02/02/2002'
GO
Select * from dbo.vwEmployeeAll
Update dbo.vwEmployeeAll Set UpdateDate = CURRENT_TIMESTAMP
EDIT:
Timestamp throws it for a loop.
Partitioned view 'ViewUpdateableDB.dbo.vwEmployeeAll' is not updatable because table '[ViewUpdateableDB].[dbo].[Employee]' has a timestamp column.
You can't update data in a view that uses a UNION when your primary keys are Identity. You must have a Partitioning Column. Otherwise, how would it know which table to update?
IE, you are using 2 tables that have a primary key on an identity field. They could have a {PK} = 1 in both tables. How would SQL Server know which table to update.
Here is a working example...with "UNION ALL" and a Partitioning Column.
I am posting this, because there is a specific way to get it to work....despite the msdn documentation.
A computation. The column cannot be computed from an expression that
uses other columns. Columns that are formed by using the set operators
UNION, UNION ALL, CROSSJOIN, EXCEPT, and INTERSECT amount to a
computation and are also not updatable.
http://msdn.microsoft.com/en-us/library/ms187956%28v=sql.110%29.aspx
So Steve's answer is correct based on the documentation and under most scenarios, but by using a partitioning-column there is a way to make it work.
The script/example below worked with Developer Edition (which is Enterprise Version without the licensing) and I tested it against SqlExpress ( Microsoft SQL Server 2012 - 11.0.2100.60 (X64)
Express Edition (64-bit) on Windows NT 6.1 (Build 7601: Service Pack 1)
)
Select ##VERSION
-- START TSQL
SET NOCOUNT ON
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'vwEmployeeAll' and TABLE_TYPE = N'VIEW' )
BEGIN
DROP VIEW [dbo].[vwEmployeeAll]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[EmployeeDeprecated]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[Employee]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Department' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[Department]
END
GO
CREATE TABLE [dbo].[Department](
[DepartmentUUID] [uniqueidentifier] NOT NULL,
[TheVersionProperty] [timestamp] NOT NULL,
[DepartmentName] [nvarchar](80) NULL,
[CreateDate] [datetime] NOT NULL
)
ALTER TABLE dbo.[Department] ADD CONSTRAINT PK_Department PRIMARY KEY NONCLUSTERED ([DepartmentUUID])
GO
ALTER TABLE [dbo].[Department] ADD CONSTRAINT CK_DepartmentName_Unique UNIQUE ([DepartmentName])
GO
CREATE TABLE [dbo].[Employee] (
/* [EmployeeUUID] [uniqueidentifier] NOT NULL, */
[EmployeeSurrogateKey] int not null IDENTITY(101,2),
[EmployeeTablePartitionOrdinal] int not null,
[ParentDepartmentUUID] [uniqueidentifier] NOT NULL,
/*[TheVersionProperty] [timestamp] NOT NULL,*/
[SSN] [nvarchar](11) NOT NULL,
[LastName] [varchar](64) NOT NULL,
[FirstName] [varchar](64) NOT NULL,
[CreateDate] [datetime] NOT NULL,
[UpdateDate] [datetime] NOT NULL,
[HireDate] [datetime] NOT NULL
)
GO
ALTER TABLE dbo.Employee ADD CONSTRAINT PK_Employee PRIMARY KEY NONCLUSTERED (EmployeeSurrogateKey,EmployeeTablePartitionOrdinal)
GO
ALTER TABLE [dbo].[Employee] ADD CONSTRAINT CK_Employee_SSN_Unique UNIQUE (SSN)
GO
ALTER TABLE [dbo].[Employee] ADD CONSTRAINT FK_EmployeeToDepartment FOREIGN KEY (ParentDepartmentUUID) REFERENCES dbo.Department (DepartmentUUID)
GO
/*
ALTER TABLE [dbo].[Employee]
ADD CONSTRAINT [CK_Employee_PK_IsOdd] CHECK ( ( [EmployeeSurrogateKey] % 2 ) != 0)
GO
*/
/*
ALTER TABLE [dbo].[Employee] WITH CHECK ADD CONSTRAINT [CK_Employee_PK_IsOdd]
CHECK ( ( [EmployeeSurrogateKey] % 2 ) != 0)
GO
*/
ALTER TABLE [dbo].[Employee] WITH CHECK ADD CONSTRAINT [CK_EmployeeTablePartitionOrdinal_Is_One]
CHECK ( [EmployeeTablePartitionOrdinal] = 1 )
GO
CREATE TABLE [dbo].[EmployeeDeprecated] (
/*[EmployeeDeprecatedUUID] [uniqueidentifier] NOT NULL,*/
[EmployeeDeprecatedSurrogateKey] int not null IDENTITY(102,2),
[EmployeeTablePartitionOrdinal] int not null,
[ParentDepartmentUUID] [uniqueidentifier] NOT NULL,
/*[TheVersionProperty] [timestamp] NOT NULL,*/ /* Partitioned view 'ViewUpdateableDB.dbo.vwEmployeeAll' is not updatable because table '[ViewUpdateableDB].[dbo].[Employee]' has a timestamp column. */
[SSN] [nvarchar](11) NOT NULL,
[LastName] [varchar](64) NOT NULL,
[FirstName] [varchar](64) NOT NULL,
[CreateDate] [datetime] NOT NULL,
[UpdateDate] [datetime] NOT NULL,
[HireDate] [datetime] NOT NULL
)
GO
ALTER TABLE dbo.[EmployeeDeprecated] ADD CONSTRAINT PK_EmployeeDeprecated PRIMARY KEY NONCLUSTERED (EmployeeDeprecatedSurrogateKey,EmployeeTablePartitionOrdinal)
GO
ALTER TABLE [dbo].[EmployeeDeprecated] ADD CONSTRAINT CK_EmployeeDeprecated_SSN_Unique UNIQUE (SSN)
GO
ALTER TABLE [dbo].[EmployeeDeprecated] ADD CONSTRAINT FK_EmployeeDeprecatedToDepartment FOREIGN KEY (ParentDepartmentUUID) REFERENCES dbo.Department (DepartmentUUID)
GO
/*
ALTER TABLE [dbo].[EmployeeDeprecated]
ADD CONSTRAINT [CK_EmployeeDeprecated_PK_IsEven] CHECK ( ( [EmployeeDeprecatedSurrogateKey] % 2 ) = 0)
GO
*/
/*
ALTER TABLE [dbo].[EmployeeDeprecated] WITH CHECK ADD CONSTRAINT [CK_EmployeeDeprecated_PK_IsEven]
CHECK ( ( [EmployeeDeprecatedSurrogateKey] % 2 ) = 0)
GO
*/
ALTER TABLE [dbo].[EmployeeDeprecated] WITH CHECK ADD CONSTRAINT [CK_EmployeeTablePartitionOrdinal_Is_Two]
CHECK ( [EmployeeTablePartitionOrdinal] = 2 )
GO
CREATE VIEW dbo.vwEmployeeAll AS
Select
EmployeeSurrogateKey,EmployeeTablePartitionOrdinal,ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate
from dbo.Employee
UNION ALL
Select
EmployeeSurrogateKey =
EmployeeDeprecatedSurrogateKey,EmployeeTablePartitionOrdinal,ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate
from dbo.EmployeeDeprecated
GO
declare #DepartmentUUID001 uniqueidentifier
select #DepartmentUUID001 = 'DDDDDDDD-0000-0000-0000-000000000101'
declare #DepartmentUUID002 uniqueidentifier
select #DepartmentUUID002 = 'DDDDDDDD-0000-0000-0000-000000000102'
INSERT INTO dbo.Department (DepartmentUUID , DepartmentName , CreateDate )
Select #DepartmentUUID001 , 'Department One' , CURRENT_TIMESTAMP
UNION
Select #DepartmentUUID002 , 'Department Two' , CURRENT_TIMESTAMP
/*
declare #EmployeeUUID001 uniqueidentifier
select #EmployeeUUID001 = 'EEEEEEEE-0000-0000-0000-000000001001'
declare #EmployeeUUID00A uniqueidentifier
select #EmployeeUUID00A = 'EEEEEEEE-0000-0000-AAAA-000000009001'
*/
INSERT INTO dbo.Employee (/*EmployeeUUID,*/ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate,EmployeeTablePartitionOrdinal)
Select /*#EmployeeUUID001 ,*/ #DepartmentUUID001 , '111-11-1111' , 'Smith', 'John' , CURRENT_TIMESTAMP , CURRENT_TIMESTAMP , '01/01/2001' , 1
INSERT INTO dbo.EmployeeDeprecated(/*EmployeeDeprecatedUUID,*/ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate,EmployeeTablePartitionOrdinal)
Select /*#EmployeeUUID00A ,*/ #DepartmentUUID002 , '888-88-8888' , 'Jones', 'Mary' , CURRENT_TIMESTAMP , CURRENT_TIMESTAMP , '02/02/2002' , 2
GO
Select * from dbo.vwEmployeeAll
Update dbo.vwEmployeeAll Set UpdateDate = CURRENT_TIMESTAMP
Update dbo.vwEmployeeAll Set LastName = 'Henderson' where EmployeeSurrogateKey = 1
Update dbo.vwEmployeeAll Set UpdateDate = CURRENT_TIMESTAMP where EmployeeSurrogateKey = 2

Resources