Dynamic Cursor SQL Server - sql-server

I have this global cursor that is created by a string like this, however when execute, I get this error message :
A cursor with the name 'crsDTO' does not exist.
Code:
DECLARE #Cursor NVARCHAR(MAX);
SET #Cursor = 'DECLARE crsDTO CURSOR FOR SELECT p.ID, p.Price, p.Count FROM Business.Products';
exec sp_executesql #Cursor;
OPEN crsDTO; -- fails here <<<<<<<<
BEGIN TRY
FETCH NEXT FROM crsDTO INTO #ID, #Price, #Count;
WHILE 0 = ##fetch_status
BEGIN
PRINT(#ID)
FETCH NEXT FROM crsDTO INTO #ID, #Price, #Count;
END;
CLOSE crsDTO;
DEALLOCATE crsDTO;
END TRY
BEGIN CATCH
CLOSE crsDTO;
DEALLOCATE crsDTO;
END CATCH
I looked around everything looks to be fine.. and I can't find why it's not working.
UPDATE
This SP is going to bulk update either price or stock or both. i might be wrong and there might be alternative way which is much better than this i am open to all correction.
However this cursor is going to be filtered based on user opinion. it can change stock/prices(as percentage amount or basic amount) based on the filters.
so for example user wants bulk change the prices for only specific brandId or combination of BrandId/CategoryId and SupplierId or none of them(which means every product).
CREATE procedure [Business].[Product_BulkUpdate]
(
#PO_Error int OUTPUT,
#PO_ErrorMessage Nvarchar(Max) OUTPUT,
#PO_Step int OUTPUT,
#CallerUserId uniqueidentifier,
#CategoryId uniqueidentifier = null,
#BrandId uniqueidentifier = null,
#SupplierId uniqueidentifier = null,
#ProductName nvarchar(max) = null,
#Amount float = null,
#AmountPercentage float = null,
#IsInStock bit = null
)
as
DECLARE #ID Uniqueidentifier;
DECLARE #Price int;
DECLARE #Count int;
DECLARE #KW nvarchar(max);
DECLARE #Cursor nvarchar(max);
DECLARE #WhereClause nvarchar(max);
set #WhereClause = ' 1=1 ';
if (#ProductName is not null)
set #WhereClause =#WhereClause + ' And p.Name like N'''+'%'+cast(#ProductName as nvarchar(4000))+'%'+''' ';
if (#CategoryId is not null)
set #WhereClause =#WhereClause + ' And c.ID in (SELECT cf.id FROM Business.GetCategoryChilds('''+CAST(#CategoryId as nvarchar(50)) +''') cf) ';
if(#SupplierId is not null)
set #WhereClause = #WhereClause + ' AND p.SupplierId in (' + CAST(#SupplierId as nvarchar(50)) + ') ';
IF(#BrandId is not null)
set #WhereClause = #WhereClause + ' AND bb.ID in (' + CAST(#BrandId as nvarchar(50)) + ')';
SET #Cursor = ' DECLARE crsDTO cursor for
SELECT p.ID, p.Price, p.Count FROM Business.Products p
INNER JOIN Kernel.BaseEntity b on b.ID = p.ID AND b.IsDelete = 0
LEFT JOIN Business.Brand bb on bb.ID = p.BrandId
LEFT JOIN Business.Category c on c.ID = p.CategoryId
LEFT JOIN MarketPlace.Supplier s on s.SupplierId = p.SupplierId
WHERE '+#WhereClause+' AND c.CategoryTypeId = 10700';
begin
--- Auto generated procedure
SET NOCOUNT ON;
SET #PO_Error = 0;
SET #PO_Step = 0;
SET #PO_ErrorMessage = '';
BEGIN TRY
exec sp_executesql #Cursor;
SET #PO_Step = 1;
OPEN crsDTO;
BEGIN TRY
FETCH NEXT FROM crsDTO INTO #ID, #Price, #Count;
while 0 = ##fetch_status
BEGIN
IF(#IsInStock = 0) BEGIN
IF(#Amount is not null and #AmountPercentage is null) BEGIN
IF EXISTS (SELECT ID FROM Business.Products WHERE ID = #ID) BEGIN
UPDATE Business.Products SET
Price = #Price + #Amount
WHERE ID = #ID
END
END else IF(#AmountPercentage is not null and #Amount is null) BEGIN
IF EXISTS (SELECT ID FROM Business.Products WHERE ID = #ID) BEGIN
UPDATE Business.Products SET
Price = (#Price * (#AmountPercentage / 100))
WHERE ID = #ID
END
END
END ELSE IF(#IsInStock = 1) BEGIN
IF(#Amount is not null and #AmountPercentage is null) BEGIN
IF EXISTS (SELECT ID FROM Business.Products WHERE ID = #ID) BEGIN
UPDATE Business.Products SET
Price = #Price + #Amount,
Count = 0
WHERE ID = #ID
END
END else IF(#AmountPercentage is not null and #Amount is null) BEGIN
IF EXISTS (SELECT ID FROM Business.Products WHERE ID = #ID) BEGIN
UPDATE Business.Products SET
Price = (#Price * (#AmountPercentage / 100)),
Count = 0
WHERE ID = #ID
END
END ELSE IF(#Amount is null and #AmountPercentage is null) BEGIN
IF EXISTS (SELECT ID FROM Business.Products WHERE ID = #ID) BEGIN
UPDATE Business.Products SET
Count = 0
WHERE ID = #ID
END
END
END
SET #PO_Step = 2;
FETCH NEXT FROM crsDTO INTO #ID, #Price, #Count;
END;
CLOSE crsDTO;
DEALLOCATE crsDTO;
END TRY
BEGIN CATCH
CLOSE crsDTO;
DEALLOCATE crsDTO;
SET #PO_Error = ERROR_NUMBER();
SET #PO_ErrorMessage = ERROR_MESSAGE();
END CATCH
END TRY
BEGIN CATCH
SET #PO_Error = ERROR_NUMBER();
SET #PO_ErrorMessage = ERROR_MESSAGE();
END CATCH
END;

I would add check if cursor exists:
-- ....
BEGIN CATCH
IF CURSOR_STATUS('global','crsDTO')>=-1
BEGIN
CLOSE crsDTO;
DEALLOCATE crsDTO;
END
END CATCH
db<>fiddle demo
Using global cursor/row-by-row approach does not seems to be the best solution.

Related

Using transaction in cursor with try..catch

I have a large stored procedure which utilises a cursor. I want to put each instance of the cursor processing into a transaction, with a try-catch on the one insert, which on failure would terminate that transaction, back any inserts it did and then move to the next cursor instance. However, I am struggling with structuring this.
An example of what it looks like in brief is below. Basically I am trying to structure the try-catch for the patient insert to rollback the transaction and go onto the next cursor value when the patient insert fails.
Thanks
ALTER procedure [dbo].[Import_Archive_Record]
#PatientNumber varchar(10),
#PracticeId int
as
begin
DECLARE csr1 CURSOR for
select PatientNumber from ArchiveFull.dbo.ArchiveMasters where imported = 0 and PracticeId =
#PracticeId and PatientNumber = #PatientNumber
open csr1
fetch next from csr1 into #PatNo
while ##FETCH_STATUS = 0
begin
insert into Member....
select #memberId = SCOPE_IDENTITY()
print 'new member ' + cast(#memberId as varchar(10))
--insert patient
BEGIN TRY
select #initials = PatientInitials ,#surname = PatientSurname ,#name = PatientFirstname,
#DateOfBirth = DOBStr,#PatientCentury = DOBCen
from ArchiveFull.dbo.ArchiveMasters
where ArchiveFull.dbo.ArchiveMasters.PatientNumber = #PatNo
and imported = 0
and PracticeId = #PracticeId
set #patientID = null
select #patientID = id from Patient
where Initials = #initials
and Surname = #surname
and Name = #name
and MemberId = #memberId
print 'patientid ' + cast(#patientID as varchar(10))
set #DOB = dbo.getVisitdate(#PatientCentury,#DateOfBirth)
if #patientID is null
begin
insert into Patient(Name, Surname,Initials,MemberId,PostalSuburb,PostalCity,PostalCode,PostBox,Gender, DateofBirth,IDNumber,DependentCode,RelationToMember,AlternativesRelation,EMailAddress,CellPhone,Title)
select PatientFirstname,PatientSurname, coalesce(PatientInitials,'.'),#memberId,PatientAddress1, PatientAddress2, PatientAddress3,PatientAddress4,Gender,#DOB,PatientIDNumber,1,1,0,PatientEmail, CellNumber,PatientTitle
from ArchiveFull.dbo.ArchiveMasters
where PatientNumber = #PatNo
and imported = 0
END TRY
BEGIN CATCH
END CATCH
select #patientID = SCOPE_IDENTITY()
print 'new patientid ' + cast(#patientID as varchar(10))
end
set #BranchId = (select top 1 id from Branch where practiceid = #practiceId and ModalityRooms like concat('%', #BranchCode,'%'))
set #visitId = null
select #visitId = id from Visit
where BookingNumber = #PatNo
and BranchId = #BranchId
if #visitId is null
begin
declare #visitDate datetime
declare #century int
declare #date int
declare #DoctorCode nvarchar (max)
declare #DoctorSurname nvarchar (max)
declare #wca bit
select #century = Century, #date = ExamDateStr, #DoctorCode = RefDocCode, #DoctorSurname = RefDoc, #wca=WCA
from ArchiveFull.dbo.ArchiveMasters
where ArchiveFull.dbo.ArchiveMasters.PatientNumber = #PatNo
and imported = 0
and PracticeId = #PracticeId
update testlist
set century = #century, examdate = #date
where patno = #PatNo
set #visitDate = isnull(dbo.getVisitdate(#century,#date),'19000101')
set #DoctorId = null
set #DoctorId = dbo.getDoctorIdRadmin(#DoctorCode,#practiceId)
insert into Visit(Date,EndMonth, EndYear,NewBorn,HospitalClaim,WCA,WorkersComp,RAF,RoadAccidentFund,Examined,Booking,BookingNumber,PatientId,Notes,PreAuthorise,PreAuthNumber,BranchId,DoctorId, Receipted, ArchiveId)
select #visitDate, MONTH(#visitDate), YEAR(#visitdate) ,0,0,0,'',0,'',1,1,#PatNo,#patientID,'',0,AUTHNO,#BranchId,#DoctorId, 0, #archiveid
from ArchiveFull.dbo.ArchiveMasters
where ArchiveFull.dbo.ArchiveMasters.PatientNumber = #PatNo
and imported = 0
and PracticeId = #PracticeId
fetch next from csr1 into #PatNo
end
close csr1
deallocate csr1

Tuning Stored Procedure

How can you improve this without using a cursor? I was thinking using table variable would help, but am I going right direction doing so? I have omitted cursor and try to do it with table variable. Please help, here is the code.
IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'[dbo].[BatchProcessBridge_CustomerEvent]') AND [xtype] IN (N'P'))
BEGIN
DROP PROCEDURE [dbo].[BatchProcessBridge_CustomerEvent]
END
GO
CREATE PROCEDURE [dbo].[BatchProcessBridge_CustomerEvent]
(
#BatchJobTable Bridge_CustomerEventBatchJobTable READONLY,
#Name VARCHAR(50)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Lsn BINARY(10),
DECLARE #SeqVal BINARY(10),
DECLARE #Action VARCHAR(300),
DECLARE #CustId VARCHAR(MAX)
--using tabel variable. Cursor gives bad performance.
DECLARE #TEMP_TABLE TABLE ( [Lsn] BINARY(10), [SeqVal] BINARY(10), [Action] VARCHAR(300), [CustId] VARCHAR(MAX))
INSERT INTO #TEMP_TABLE
SELECT Lsn, SeqVal, [Action], [CustId] FROM #BatchJobTable
--DECLARE GetBatchJobCursor CURSOR FAST_FORWARD
--FOR
--SELECT Lsn, SeqVal, [Action], [CustId] FROM #BatchJobTable
--OPEN GetBatchJobCursor
--FETCH NEXT FROM GetBatchJobCursor INTO #Lsn, #SeqVal, #Action, #CustId
--WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRY
BEGIN TRANSACTION
IF (#Action = 'create')
BEGIN
-- Create.
INSERT INTO [Bridge_Customer]
(
[CustId]
,[PersonId]
,[DisplayName]
,[CreatedDate]
,[ModifiedDate]
)
SELECT
[CustId]
,[PersonId]
,[DisplayName]
,[CreatedDate]
,[ModifiedDate]
FROM
#BatchJobTable
WHERE
(Lsn = #Lsn) AND (SeqVal = #SeqVal)
END
ELSE IF (#Action = 'update')
BEGIN
-- Update.
UPDATE [Target]
SET
[Target].[CustId] = [Ref].[CustId]
,[Target].[PersonId] = [Ref].[PersonId]
,[Target].[DisplayName] = [Ref].[DisplayName]
,[Target].[CreatedDate] = [Ref].[CreatedDate]
,[Target].[ModifiedDate] = [Ref].[ModifiedDate]
FROM
[dbo].[Bridge_Customer] AS [Target]
INNER JOIN
(SELECT * FROM #BatchJobTable WHERE (Lsn = #Lsn) AND (SeqVal = #SeqVal)) AS [Ref]
ON
([Target].[CustId] = [Ref].[CustId])
END
ELSE IF (#Action = 'delete')
BEGIN
DELETE FROM [dbo].[Bridge_Customer] WHERE [CustId] = #CustId
END
-- Update last processed event.
EXEC [dbo].[UpdateLastProcessedEvent]
#Name = #Name,
#Lsn = #Lsn,
#SeqVal = #SeqVal
COMMIT TRANSACTION
END TRY
BEGIN CATCH
DECLARE #ErrorMessage NVARCHAR(4000);
DECLARE #ErrorSeverity INT;
DECLARE #ErrorState INT;
SELECT
#ErrorMessage = ERROR_MESSAGE(),
#ErrorSeverity = ERROR_SEVERITY(),
#ErrorState = ERROR_STATE();
-- Use RAISERROR inside the CATCH block to return error
-- information about the original error that caused
-- execution to jump to the CATCH block.
RAISERROR (#ErrorMessage, -- Message text.
#ErrorSeverity, -- Severity.
#ErrorState -- State.
);
ROLLBACK TRANSACTION
END CATCH
--FETCH NEXT FROM GetBatchJobCursor INTO #Lsn, #SeqVal, #Action, #CustId
END
--CLOSE GetBatchJobCursor
--DEALLOCATE GetBatchJobCursor
END
GO
A cursor is not necessary here; this is just basic SQL. Forgive any mistakes with my code as you haven't provided any DLL but I'm pretty sure you can just do this:
IF (#Action = 'create')
INSERT INTO Bridge_Customer
(
CustId
,PersonId
,DisplayName
,CreatedDate
,ModifiedDate
)
SELECT
CustId
,PersonId
,DisplayName
,CreatedDate
,ModifiedDate
FROM #BatchJobTable
ELSE IF (#Action = 'update')
UPDATE tgt
SET tgt.CustId = Ref.CustId
,tgt.PersonId = Ref.PersonId
,tgt.DisplayName = Ref.DisplayName
,tgt.CreatedDate = Ref.CreatedDate
,tgt.ModifiedDate = Ref.ModifiedDate
FROM dbo.Bridge_Customer AS tgt
INNER JOIN #BatchJobTable AS ref
ON (tgt.CustId = Ref.CustId)
ELSE IF (#Action = 'delete')
DELETE FROM dbo.Bridge_Customer
WHERE CustId IN (SELECT CustId FROM #BatchJobTable);
Personally, I would split this into three stored and call whichever one from the application layer. What you are doing is known as a "Catch All query" which is fine but, if you must go that route, read this: Catch All Queries (Gail Shaw)

Check if record exists, if yes “update” if not “insert” using cursor sql server

I have this trigger that after insert update and insert data in a table, using the if as paramter for the insert or update, at the same time i have another trigger after update that changes another register. The problem is that the first trigger when does the update it trigger the update trigger... So occours that I had to protect the first trigger by checking if there´s a register there before the insert BUT I have a cursor to insert the data in the middle of all this, after I did checking the insert of one register occurs BUT the others inside the cursor aren´t inserted in the table just one register of the list in the cursor... I cannot find the problem, please help...
this is my trigger:
ALTER TRIGGER [dbo].[tr_inclusao_dupla] ON [dbo].[tb_patrimonio]
AFTER INSERT
AS
BEGIN
begin try
IF EXISTS (SELECT * FROM INSERTED) AND EXISTS (SELECT * FROM DELETED)
BEGIN
declare #id as int
declare #count as int
declare #qtd as int
declare #emlote as bit
declare #nr_serie as varchar(100)
declare #nr_patrimonio as varchar(100)
declare #dm_identificado as bit
declare #nr_inventario as varchar(100)
set #nr_patrimonio = (select nr_patrimonio_efetivo from inserted)
set #nr_serie = (select nr_serie from inserted)
set #nr_inventario = (select nr_inventario from inserted)
/*single insert*/
if (#nr_patrimonio is not null or #nr_serie is not null or #nr_inventario is not null)
begin
set #emlote =0
declare registros cursor for
select cd_patrimonio , nr_qtd_lote,nr_serie, nr_patrimonio_efetivo from inserted
open registros
fetch next from registros into #id, #qtd, #nr_serie, #nr_patrimonio
while( ##fetch_status = 0)
begin
set #dm_identificado = 1
update tb_patrimonio set dm_identificado = #dm_identificado, dm_em_lote = #emlote
where cd_patrimonio = #id
end
fetch next from registros into #id, #qtd,#nr_serie, #nr_patrimonio
close registros
deallocate registros
end
END
ELSE
BEGIN
/*multiple insert*/
begin
set #emlote =0
set #dm_identificado = 0
declare registros2 cursor for
select cd_patrimonio , nr_qtd_lote,nr_serie, nr_patrimonio_efetivo from inserted
open registros2
fetch next from registros2 into #id, #qtd, #nr_serie, #nr_patrimonio
while( ##fetch_status = 0)
begin
print #qtd
set #count = 1
update tb_patrimonio set dm_identificado = #dm_identificado, dm_em_lote = #emlote
where cd_patrimonio = #id
while (#count <= (#qtd-1))
begin
INSERT INTO [dbo].[tb_patrimonio]
([dm_patrimonio]
,[dm_em_lote]
,[nr_qtd_lote]
,[cd_grupo_produto]
,[nm_patrimonio]
,[nr_patrimonio_efetivo]
,[nr_patrimonio_antigo]
,[nr_serie]
,[ds_descricao]
,[nr_lacre]
,[cd_barra]
,[dm_tipo_entrada]
,[nr_garantia]
,[cd_nota_fiscal]
,[ds_garantia]
,[img_patrimonio]
,[cd_situacao_patrimonio]
,[cd_orgao]
,[cd_local]
,[dm_situacao]
,[cd_usuario_inc]
,[cd_estado_patrimonio]
,[cd_tipo_posse]
,[cd_usuario_alt]
,[dt_alteracao]
,[cd_usuario]
,[dt_inclusao]
,[cd_estado_equipamento]
,[cd_fornecedor]
,[nr_termo]
,[img_termo]
,[dm_identificado]
,[dt_instalacao_equipamento]
,[nr_inventario])
SELECT
[dm_patrimonio]
,#emlote
,[nr_qtd_lote]
,[cd_grupo_produto]
,[nm_patrimonio]
,[nr_patrimonio_efetivo]
,[nr_patrimonio_antigo]
,[nr_serie]
,[ds_descricao]
,[nr_lacre]
,[cd_barra]
,[dm_tipo_entrada]
,[nr_garantia]
,[cd_nota_fiscal]
,[ds_garantia]
,[img_patrimonio]
,[cd_situacao_patrimonio]
,[cd_orgao]
,[cd_local]
,[dm_situacao]
,[cd_usuario_inc]
,[cd_estado_patrimonio]
,[cd_tipo_posse]
,[cd_usuario_alt]
,[dt_alteracao]
,[cd_usuario]
,[dt_inclusao]
,[cd_estado_equipamento]
,[cd_fornecedor]
,[nr_termo]
,[img_termo]
,#dm_identificado
,[dt_instalacao_equipamento]
,[nr_inventario]
FROM inserted where cd_patrimonio = #id
set #count = #count + 1
end
fetch next from registros2 into #id, #qtd,#nr_serie, #nr_patrimonio
end
close registros2
deallocate registros2
end
END
end try
begin catch
declare #errormessage nvarchar(4000)
declare #errorseverity int
declare #errorstate int
select
#errormessage = ERROR_MESSAGE(),
#errorseverity = ERROR_SEVERITY(),
#errorstate = ERROR_STATE()
raiserror (
#errormessage,
#errorseverity,
#errorstate
)
end catch end

removing all the characters except numbers

Could you please help me rewrite the following CP so when it reads from the file to remove any other characters except numbers:
what it does is read a file for example block.txt and addes each line into the table.
USE [db_Test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Cp_ImportBlackList]
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION Acbc
DECLARE #command nvarchar(max)
DECLARE #delcommand varchar(200)
DECLARE #txtfile nvarchar(200)
DECLARE #line nvarchar(2)
DECLARE #andreas nvarchar(200)
set #line='\n'
DECLARE #isExists INT
DECLARE #tempcol int
DECLARE MyCursor cursor fast_forward for
Select Users_ID from Prj_Users
open MyCursor
fetch next from MyCursor
into #tempcol
while ##fetch_status = 0
begin
set #txtfile = 'c:\BlackList\ ' + LTRIM(RTRIM(str(#tempcol))) + '.txt'
exec master.dbo.xp_fileexist #txtfile,
#isExists OUTPUT
if (#isExists =1)
begin
BEGIN TRY
BEGIN TRANSACTION ad
set #command=' BULK INSERT Prj_TempBlackList FROM ''' + #txtfile + ''''
set #command += ' WITH( ROWTERMINATOR = '''+ #line +''' )'
print #command
EXECUTE(#command)
delete Prj_TempBlackList where Tell in(select [BLList_TEll] from prj_BlackList where [BLList_UserID] = #tempcol)
insert into prj_BlackList select DISTINCT Tell,#tempcol from Prj_TempBlackList where Tell not in(select [BLList_TEll] from prj_BlackList where [BLList_UserID] = #tempcol)
delete from Prj_TempBlackList
set #delcommand ='del ' + #txtfile
exec xp_cmdshell #delcommand
print 'end'
COMMIT TRANSACTION ad
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION ad
SELECT ERROR_Message() AS ErrorNumber;
END CATCH
end
else
print 'no'
fetch next from MyCursor
into #tempcol
end
close MyCursor
deallocate MyCursor
set #txtfile = 'c:\BlackList\block.txt'
exec master.dbo.xp_fileexist #txtfile,
#isExists OUTPUT
if (#isExists =1)
begin
BEGIN TRY
BEGIN TRANSACTION ada
set #command=' BULK INSERT Prj_TempBlackList FROM ''' + #txtfile + ''''
set #command += ' WITH( ROWTERMINATOR = '''+#line+''' )'
EXECUTE(#command)
delete Prj_TempBlackList where Tell in(
select [BLList_TEll] from prj_BlackList where [BLList_UserID] is null)
insert into prj_BlackList SELECT DISTINCT Tell,null from
Prj_TempBlackList where Tell not in(
select [BLList_TEll] from prj_BlackList where [BLList_UserID] is null)
delete from Prj_TempBlackList
set #delcommand ='del ' + #txtfile
exec xp_cmdshell #delcommand
print 'yes'
COMMIT TRANSACTION ada
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION ada
SELECT ERROR_Message() AS ErrorNumber;
END CATCH
end
COMMIT TRANSACTION Acbc
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION Acbc
END CATCH
END
Try to avoid CURSORs and LOOPs!
This approach does it on the fly, but you really should think about if TSQL is the right tool...
DECLARE #tbl TABLE(ID INT IDENTITY, EvilString NVARCHAR(100));
INSERT INTO #tbl(EvilString) VALUES('ab23cd56jkl'),(' adfhasd l h45 hagf 78 l 9');
WITH RunningNumbers AS
(
SELECT ROW_NUMBER() OVER(ORDER BY A) AS Nmbr
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS tblA(A)
,(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS tblB(B)
,(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS tblC(C)
,(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS tblD(D)
,(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS tblE(E)
,(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS tblF(F)
)
,SingleChars AS
(
SELECT tbl.ID,rn.Nmbr,SUBSTRING(tbl.EvilString,rn.Nmbr,1) AS Chr
FROM #tbl AS tbl
CROSS APPLY (SELECT TOP(LEN(tbl.EvilString)) Nmbr FROM RunningNumbers) AS rn
)
SELECT ID,EvilString
,(
SELECT '' + Chr
FROM SingleChars AS sc
WHERE sc.ID=tbl.ID AND ASCII(Chr) BETWEEN 48 AND 57
ORDER BY sc.Nmbr
FOR XML PATH('')
) AS GoodString
FROM #tbl As tbl
The result
ID EvilString GoodString
1 ab23cd56jkl 2356
2 adfhasd l h45 hagf 78 l 9 45789

The current transaction cannot be committed and cannot support operations that write to the log file. Rollback the transaction

I'm encountering this error when running my script in SQL Server 2008. But when I restore my database in SQL Server 2012, it runs successfully and I did not encounter any errors.
The current transaction cannot be committed and cannot support operations that write to the log file. Rollback the transaction.
Here is my stored procedure:
CREATE PROCEDURE UpdateDependentViews
(
#TableName NVARCHAR(128),
#AllDependents bit = 1
)
AS
SET NOCOUNT ON;
CREATE TABLE #Dependencies
(
[Counter] [int] IDENTITY(1,1) NOT NULL,
[View_Name] [nvarchar](128),
) ON [PRIMARY];
CREATE INDEX Counter ON #Dependencies(Counter);
/* Get the first degree dependent views. */
INSERT INTO #Dependencies(View_Name)
SELECT V.[name] AS [View_Name]
FROM sys.sql_expression_dependencies SD
INNER JOIN sys.views V ON SD.referencing_id = V.object_id
INNER JOIN sys.objects D ON SD.referenced_id = D.object_id
WHERE SD.referencing_minor_id = 0
AND SD.referenced_minor_id = 0
AND SD.referencing_class = 1
AND D.type IN ('U', 'V')
AND D.is_ms_shipped = 0
AND V.is_ms_shipped = 0
AND D.[name] = #TableName
SELECT *
FROM sys.sql_expression_dependencies
WHERE referenced_entity_name IS NULL
/* Refresh the dependent views. */
DECLARE #ViewName NVARCHAR(128)
DECLARE #Counter INT
SET #Counter = 1;
DECLARE #Errors NVARCHAR(MAX)
SET #Errors = ''
WHILE EXISTS (SELECT [View_Name] FROM #Dependencies WHERE Counter = #Counter)
BEGIN
SELECT #ViewName = View_Name FROM #Dependencies WHERE Counter = #Counter;
/*Get Inner view dependencies */
IF ISNULL(#AllDependents, 0) = 1
BEGIN
IF ISNULL(#AllDependents, 0) = 1 AND EXISTS(SELECT 1
FROM sys.sql_expression_dependencies SD
INNER JOIN sys.objects D ON SD.referenced_id = D.object_id
WHERE SD.referencing_minor_id = 0
AND SD.referenced_minor_id = 0
AND SD.referencing_class = 1
AND D.type IN ('U', 'V')
AND D.is_ms_shipped = 0
AND D.[name] = #ViewName)
BEGIN
INSERT INTO #Dependencies(View_Name)
SELECT V.[name] AS [View_Name]
FROM sys.sql_expression_dependencies SD
INNER JOIN sys.views V
ON SD.referencing_id = V.object_id
INNER JOIN sys.objects D
ON SD.referenced_id = D.object_id
WHERE SD.referencing_minor_id = 0
AND SD.referenced_minor_id = 0
AND SD.referencing_class = 1
AND D.type IN ('U', 'V')
AND D.is_ms_shipped = 0
AND V.is_ms_shipped = 0
AND ISNULL(D.[name], '') <> ''
AND D.[name] = #ViewName
AND V.[name] NOT IN (SELECT View_Name FROM #Dependencies )
END
END;
/* Refresh the view */
BEGIN TRY
--BEGIN TRANSACTION
EXEC SP_REFRESHVIEW #ViewName
--COMMIT TRANSACTION
END TRY
BEGIN CATCH
--ROLLBACK TRANSACTION
IF EXISTS (SELECT 1 FROM [ISSIMODEL(15)].sys.objects WHERE [name] = #ViewName)
SET #Errors = #Errors + CHAR(13) + 'Error: Failed to RefreshView ' + #ViewName + '. Message: ' + ERROR_MESSAGE()
END CATCH
SET #Counter = #Counter + 1;
END;
IF ISNULL(#Errors, '') <> ''
RAISERROR (#Errors, 16, 1)
DROP TABLE #Dependencies;
This often occurs when you use TRY\CATCH block in your code:
Make sure you has this flow in your code:
DECLARE #ErrorMum INT
DECLARE #ErrorMessage VARCHAR(200)
DECLARE #Severity INT
DECLARE #State INT
BEGIN TRY
BEGIN TRAN T1
<Your Code goes here>
COMMIT TRAN T1
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0 BEGIN
ROLLBACK TRAN T1
END
SET #ErrorMum = ERROR_NUMBER()
SET #ErrorMessage = ERROR_MESSAGE()
SET #Severity = ERROR_SEVERITY()
SET #State = ERROR_STATE()
RAISERROR(#ErrorMessage, #Severity, #State)
END CATCH

Resources