Число транзакций после EXECUTE указывает на несовпадающее количество операторов BEGIN и COMMIT. Предыдущий счет

Я получаю это исключение о коммитах и ​​откате, но не уверен, что именно не так с моей Хранимой процедурой. Я прочитал ответы на другие подобные вопросы и не могу найти, где именно запутывается количество коммитов.

Итак, это хранимая процедура, которую я использую:

-- this is a procedure used for the purge utility. This procedure uses the parameters of a date and lets user select
-- if the leads that should be purge must be closed either before, on or since that date.
-- operator: 0-->less 1-->equal 2-->greater
-- @closed: closing date
-- leadscount: returns the count of leads deleted

IF OBJECT_ID ('LEAD_PURGE', 'P') IS NOT NULL
   DROP PROCEDURE LEAD_PURGE
go

CREATE PROCEDURE LEAD_PURGE
@purgextns INT,
@leadscount INT OUTPUT
AS
BEGIN
BEGIN TRANSACTION
CREATE TABLE #ASSIGNMENTS_DELETED
(
    ID NUMERIC(19, 0)
    PRIMARY KEY (ID)
)

CREATE TABLE #MAPRESULTS_DELETED
(
    ID NUMERIC(19, 0)
    PRIMARY KEY (ID)
)

CREATE TABLE #COMMAND_DELETED
(
    ID NUMERIC(19, 0)
    PRIMARY KEY (ID)
)

CREATE TABLE #PROGRESS_STATUS_DELETED
(
    ID NUMERIC(19, 0)
    PRIMARY KEY (ID)
)

CREATE TABLE #DETAILS_DELETED
(
    ID NUMERIC(19, 0)
    PRIMARY KEY (ID)
)

CREATE TABLE #NEEDS_DELETED
(
    ID NUMERIC(19, 0)
    PRIMARY KEY (ID)
)

insert into #ASSIGNMENTS_DELETED
select SEQID FROM ASSIGNMENT WHERE LEADSEQ IN (SELECT ID FROM PURGE_LEAD);

SELECT @leadscount = (SELECT COUNT(*) FROM PURGE_LEAD);

INSERT INTO #MAPRESULTS_DELETED
SELECT ID FROM MAPRESULT WHERE ASSIGNMENTSEQ IN (SELECT ID FROM #ASSIGNMENTS_DELETED)

INSERT INTO #COMMAND_DELETED
SELECT ID FROM EXECUTERULECOMMAND WHERE MAPRESULTID IN (SELECT ID FROM #MAPRESULTS_DELETED)

INSERT INTO #PROGRESS_STATUS_DELETED
SELECT PROGRESS_STATUS_ID FROM COMMAND WHERE ID IN (SELECT ID FROM #COMMAND_DELETED)

INSERT INTO #DETAILS_DELETED
SELECT DETAILID FROM LEAD WHERE SEQID IN (SELECT ID FROM PURGE_LEAD)

INSERT INTO #NEEDS_DELETED
SELECT NEEDSID FROM LEAD WHERE SEQID IN (SELECT ID FROM PURGE_LEAD)



DELETE FROM PROGRESS_STATUS WHERE ID IN (SELECT ID FROM #PROGRESS_STATUS_DELETED)

DELETE FROM EXECUTERULECOMMAND WHERE ID IN (SELECT ID FROM #COMMAND_DELETED)

DELETE FROM COMMAND WHERE ID IN (SELECT ID FROM #COMMAND_DELETED)

DELETE FROM SIMPLECONDITIONAL WHERE RESULT IN (SELECT ID FROM #MAPRESULTS_DELETED)

DELETE FROM MAPPREDICATE WHERE ROWBP IN (SELECT ID FROM MAPROW WHERE RESULT IN (SELECT ID FROM #MAPRESULTS_DELETED))

DELETE FROM MAPROW WHERE RESULT IN (SELECT ID FROM #MAPRESULTS_DELETED)

DELETE FROM MAPRESULT WHERE ID IN (SELECT ID FROM #MAPRESULTS_DELETED)

DELETE FROM ASSIGNMENTATTACHMENTS WHERE ASSIGNMENTSEQ IN (SELECT ID FROM #ASSIGNMENTS_DELETED)

DELETE FROM LEADOBSERVER WHERE ASSIGNSEQ IN (SELECT ID FROM #ASSIGNMENTS_DELETED)

DELETE FROM MAPDESTINATIONS WHERE SUGGESTEDASSIGNID IN 
    (SELECT ID FROM SUGGESTEDASSIGNMENT WHERE ASSIGNMENT_SEQID IN (SELECT ID FROM #ASSIGNMENTS_DELETED))

DELETE FROM SUGGESTEDASSIGNMENT WHERE ASSIGNMENT_SEQID IN (SELECT ID FROM #ASSIGNMENTS_DELETED)

DELETE FROM PRODUCTINTEREST WHERE LEADSEQ IN (SELECT ID FROM PURGE_LEAD)



CREATE TABLE #SALE_DELETED_EX
(
    ID NUMERIC(19, 0)
    PRIMARY KEY (ID)
)
INSERT into #SALE_DELETED_EX SELECT SALEEXSEQ FROM SALE WHERE SEQID IN (SELECT SALEID FROM LEADSALES WHERE LEADID IN (SELECT ID FROM PURGE_LEAD))


DELETE FROM SALE WHERE SEQID IN (SELECT SALEID FROM LEADSALES WHERE LEADID IN (SELECT ID FROM PURGE_LEAD))


DELETE FROM SALEEXTENSIONS WHERE 
    SEQID IN (SELECT ID FROM #SALE_DELETED_EX)

DELETE FROM LEADSALES WHERE LEADID IN (SELECT ID FROM PURGE_LEAD)


DELETE FROM NOTES WHERE OBJECTID IN (SELECT ID FROM #NEEDS_DELETED) OR OBJECTID IN (SELECT ID FROM #DETAILS_DELETED)

DELETE FROM HISTORYRECORD WHERE OBJECTID IN (SELECT ID FROM #DETAILS_DELETED)

DELETE FROM DETAIL WHERE SEQID IN (SELECT ID FROM #NEEDS_DELETED UNION SELECT ID FROM #DETAILS_DELETED)

DELETE FROM MESSAGES WHERE PROVIDERID IN (SELECT ID FROM PURGE_LEAD)

DELETE FROM ASSIGNMENT WHERE LEADSEQ IN (SELECT ID FROM PURGE_LEAD)

DELETE FROM LEAD WHERE SEQID IN (SELECT ID FROM PURGE_LEAD)

CREATE TABLE #PURGE_LEAD_E
(
    ID NUMERIC(19, 0)
    PRIMARY KEY (ID)
)

INSERT into #PURGE_LEAD_E Select SEQID FROM LEADEXTENSIONS WHERE 
    SEQID NOT IN (SELECT LEADEXSEQ FROM LEAD)

if @purgextns = 1 begin
    DELETE FROM LEADEXTENSIONS WHERE 
        SEQID  IN (SELECT ID FROM PURGE_LEAD_E)
end


DELETE FROM PURGE_LEAD;

DROP TABLE #ASSIGNMENTS_DELETED

DROP TABLE #MAPRESULTS_DELETED

DROP TABLE #COMMAND_DELETED

DROP TABLE #PROGRESS_STATUS_DELETED

DROP TABLE #DETAILS_DELETED

DROP TABLE #NEEDS_DELETED

DROP TABLE #PURGE_LEAD_E

DROP TABLE #SALE_DELETED_EX

COMMIT
END
go

Теперь я вызываю эту процедуру в следующем коде:

    try {
        c = new ConnectionHelper().getConnection();
        String sql = "";
        if (shouldPurgeExtns) {
            progressModel.makeProgress("progress.deleting.dependents");
            purgeMultiselect(c, LEAD, isMSSQL);
        }
        sql = "{CALL " + TOPLinkManager.getSchemaPrefix()
                + "LEAD_PURGE (?,?)}";
        cs = c.prepareCall(sql);
        cs.setInt(1, shouldPurgeExtns ? 0 : 1);
        cs.registerOutParameter(2, java.sql.Types.INTEGER);
        cs.executeUpdate();
        int rowcount = cs.getInt(2);
        cs.close();
        progressModel.makeProgress("progress.recording.history");
        recordHistory(c, isMSSQL, LEAD, DateTypeDecorator.CLOSED, date,
                rowcount);
        done(progressModel);
        c.close();
        return true;
    } catch (Exception e) {
        Logs.main.error("Error Purging Leads", e);
        throw new Exception(e.getMessage());
    }

И я получаю исключение на линии, которые говорят int rowcount = cs.getInt(2);

Исключение составляет:

com.microsoft.sqlserver.jdbc.SQLServerException: Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 0, current count = 1.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:196)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1454)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.processResults(SQLServerStatement.java:1083)
    at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getOutParameter(SQLServerCallableStatement.java:112)
    at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getterGetParam(SQLServerCallableStatement.java:387)

Пожалуйста, помогите мне. в com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getValue(SQLServerCallableStatement.java:393) в com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getInt(SQLServerCallableStatement.gee..java:283)

РЕДАКТИРОВАТЬ:

так как я сам ответил на этот вопрос... Я хотел бы немного изменить вопрос сейчас.

Почему не было выброшено исключение в методе execute???

5 ответов

Решение

Извините ребята! Спасибо за все ваши усилия. В конце концов, это была очень маленькая ошибка с моей стороны в хранимой процедуре:

Посмотрите на строку:

if @purgextns = 1 begin
    DELETE FROM LEADEXTENSIONS WHERE 
        SEQID  IN (SELECT ID FROM PURGE_LEAD_E)
end

Так должно быть #PURGE_LEAD_E

Все ваши ответы помогли мне по-другому взглянуть на разработку процедур магазина. Большое спасибо!

Ваш COMMIT не ударил, вероятно, из-за ошибки. Транзакция не будет откатываться автоматически

Лучший способ (и лучшая практика) - добавить обработку ошибок SQL

CREATE PROCEDURE LEAD_PURGE
  @purgextns INT,
  @leadscount INT OUTPUT
AS
SET NOCOUNT, XACT_ABORT ON;

BEGIN TRY
  BEGIN TRANSACTION

  CREATE TABLE #ASSIGNMENTS_DELETED
  (
      ID NUMERIC(19, 0)
      PRIMARY KEY (ID)
  )

  ...
  DROP TABLE #SALE_DELETED_EX

  COMMIT TRANSACTION
END TRY
BEGIN CATCH
  IF XACT_STATE() <> 0 
      ROLLBACK TRANSACTION
  RAISERROR ('it broke', 16, 1)
END CATCH
go

Подробнее о том, что здесь происходит, см. Мой ответ здесь. Вложенные хранимые процедуры, содержащие шаблон TRY CATCH ROLLBACK?

Примечание: вам не нужно отбрасывать временные таблицы, поскольку они выходят из области видимости при выходе из хранимой процедуры

Попробуйте добавить в начале процедуры

SET XACT_ABORT ON

Или же

Оберните ваши заявления

begin try 
  BEGIN TRANSACTION 
 Your TSQL code

  COMMIT
end try 
begin catch 
  ROLLBACK
  RAISERROR('Gotcha!', 16, 1)
end catch

Чтобы проверить, сколько незафиксированных BEGIN TRAN открыт тест @@TRANCOUNT системная переменная

Обычно это происходит, когда транзакция запущена и либо не зафиксирована, либо не является откатом.

Если в вашей хранимой процедуре возникает ошибка, это может заблокировать таблицы базы данных, поскольку транзакция не завершена из-за некоторых ошибок времени выполнения при отсутствии обработки исключений. Вы можете использовать обработку исключений, как показано ниже. SET XACT_ABORT

SET XACT_ABORT ON
SET NoCount ON
Begin Try 
     BEGIN TRANSACTION 
        //Insert ,update queries    
     COMMIT
End Try 
Begin Catch 
     ROLLBACK
End Catch

Как именно переменная @leadscount содержит количество удаленных лидов?

Это единственное место, где я вижу, что его используют:

SELECT @leadscount = (SELECT COUNT (*) FROM PURGE_LEAD);

В любом случае, чтобы проверить это, почему бы вам не запустить приведенный выше код вне контекста транзакции?

Если вам действительно нужно, чтобы оно было внутри транзакции, попробуйте загрузить значение в табличную переменную (создайте таблицу только с одним столбцом). Поскольку они не участвуют в транзакциях, вы можете проверить, является ли транзакция вашей реальной проблемой.

Другие вопросы по тегам