powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Хр. процедура удаления приводит к работе триггера -> Не ловится ошибка.
7 сообщений из 7, страница 1 из 1
Хр. процедура удаления приводит к работе триггера -> Не ловится ошибка.
    #32028986
Sash
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Извините, если вопрос не совсем по теме.
Ситуация такая:
Родитель a - потомки b,c,d...(это таблицы). База построена на CONSTRAINT-ах PK, FK. (MSSQL 7.0)
Процедура удаления родителя(a) проверяет наличие ссылок в таблицах потомков b, c , d ... , и удаляет потомков перед удалением родителя и в конце процедуры удаляет запись из таблицы a . (транзакция в хр. процедуре)

Для таблицы родитель(a) существует триггер на удаление, он проверяет использование идентификаторов удаляемых родителей в текстовых строках, хранящихся в отдельной таблице.(Это формулы, в них могут в текстовом виде храниться иментификаторы переменных.)
Триггер откатывает операцию, если переменная(родитель) используется в какой-либо формуле.

Проблема в следующем:

При вызове хр. процедуры удаления из Visual Basic(ADO 2.6) объект Connection получает ошибку в Errors, но при этом не возникает Runtime-ошибки исполнения программы.
Однако если выполнить удаление из таблицы (а) через тот-же объект Command, но с помощью команды "DELETE a WHERE ...", то возникает Runtime-ошибка, и ловится обработчиком. Ошибка та-же самая, созданная в триггере.

Я могу конечно перенести всю логику из хр. процедуры в триггер и отказаться от процедуры, но однако из-за чего такое может происходить?
...
Рейтинг: 0 / 0
Хр. процедура удаления приводит к работе триггера -> Не ловится ошибка.
    #32028992
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну во первых интересно, что пишет QA ? Возникает ли в нем ошибка при вызове ХП ? Во вторых в тригере при откате неплохо бы писать RAISERROR с текстом ошибки для клиента. В третьих в ХП поставить после DELETE строку IF @@ERROR <> 0 RETURN (ну или код обработки ошибки). Кстати на заметку - если желательно автоматом прерывать ХП при возникновении ошибок системного уровня, генерируемого сервером (нарушение целостной ссылочности, ошибки constraint и т.д.), то в начале ХП можно поставить SET XACT_ABORT ON. Однако для генерирующихся юзерных ошибок оператором RAISERROR это не поможет, так что по любому лучше после критических выполнений операций над БД (INSERT, UPDATE, DELETE) писать обработку кода ошибки, иначе процедура просто продолжит свое выполнение и многое чего натворит, если повезет.
...
Рейтинг: 0 / 0
Хр. процедура удаления приводит к работе триггера -> Не ловится ошибка.
    #32029023
Sash
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
1. В QA все выглядит правильно - прерывается выполнение процедуры по ошибке, которую создает триггер.

2. В триггере я пишу:
...
--если найдена формула, использующая переменную
RAISERROR ('Удаление переменной не возможно. Переменная используется в расчетных формулах.', 16, 10)
ROLLBACK TRAN
RETURN
...

3. В процедуре удаления:

CREATE PROCEDURE DelVar
@cVarName varchar(33)
AS
...
BEGIN TRANSACTION
...
DELETE FROM cfVariable WHERE cVarName = @cVarName -- это центральная таблица переменных(родитель)
IF @@ERROR <> 0
BEGIN
ROLLBACK TRANSACTION
return(-1)
END

COMMIT
return(0)
GO

При таком вызове:
cmd.CommandText = "DELETE FROM cfVariable WHERE cVarName = '" & strVarName & "'"
cmd.CommandType = adCmdText
cmd.Execute

возникает Runtime-ошибка и ошибка находится в коллеции cmd.ActiveConnection.Errors.


Однако, когда вызываю из VB
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "DelVar"
cmd.Parameters.Refresh
cmd.Parameters("@cVarName") = strVarName
cmd.Execute

,то возвращаемое значение из процедуры(cmd.Parameters.Item(0)) = 0, хотя должно быть -1, и Runtime-ошибки не происходит.
Но при этом ошибка находится в коллекции cmd.ActiveConnection.Errors.
...
Рейтинг: 0 / 0
Хр. процедура удаления приводит к работе триггера -> Не ловится ошибка.
    #32029037
Sash
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Написал, отдельный скрипт, демонситирующий мой вопрос.
Каждый может попробовать вызвать хр. процедуру удаления через ADODB.Command (своей среды разработки клиентов) и убедиться, что Runtime-ошибка не возникнет и возвращаемое значение из хр. процедуры будет = 0.
Однако в коллекции cmd.ActiveConnection.Errors ошибка будет находиться.
1. Это так и должно работать, или я что-то делаю неправильно ?
2. Почему возвращаемое значение из хр. процедуры не -1 ?

use pubs
--DROP TABLE cfVariable
CREATE TABLE cfVariable(
VarID int NOT NULL IDENTITY(1,1),
cVarName varchar(33) NOT NULL,
UNIQUE(cVarName),
PRIMARY KEY(VarID))

--DROP TABLE cfCalcRule
CREATE TABLE cfCalcRule(
ID int NOT NULL IDENTITY (1,1),
left_id int NOT NULL,
left_field varchar(20) NULL,
right_val varchar(255),
PRIMARY KEY (ID),
FOREIGN KEY (left_id) REFERENCES cfVariable (VarID)
)
GO

--DROP TRIGGER tD_cfVariable
CREATE TRIGGER tD_cfVariable
ON cfVariable
FOR DELETE
AS

IF @@ROWCOUNT = 0 RETURN

-- переменные для хранения записи из курсора
DECLARE @VarID int
DECLARE @cVarName varchar(33)


DECLARE VDBVars CURSOR LOCAL FAST_FORWARD READ_ONLY
FOR SELECT cVarName FROM deleted

OPEN VDBVars

FETCH NEXT FROM VDBVars INTO @cVarName -- получаем первую запись из курсора

WHILE @@FETCH_STATUS = 0
BEGIN
IF EXISTS(SELECT 1 FROM cfCalcRule WHERE PATINDEX('%' + @cVarName + '%',cfCalcRule.right_val) <> 0)
BEGIN
RAISERROR ('Удаление переменной невозможно. Переменная используется в расчетных формулах.', 16, 10)
ROLLBACK TRAN
RETURN
END

FETCH NEXT FROM VDBVars INTO @cVarName -- переход к следующей запси
END

CLOSE VDBVars
DEALLOCATE VDBVars
GO

CREATE PROCEDURE DelVar
@cVarName varchar(33)
AS


DECLARE @VarID int

--Проверка входного параметра
IF (@cVarName IS NULL)
BEGIN
RETURN(-1)
END
--Определяем идентификатор переменной
SELECT @VarID=VarID FROM cfVariable WHERE cVarName = @cVarName
IF @@ROWCOUNT = 0 --Нет такой переменной в cfVariable
BEGIN
RETURN(-1)
END

BEGIN TRANSACTION

DELETE cfCalcRule WHERE left_id = @VarID

-- Удаление переменой из центральной таблицы
DELETE FROM cfVariable WHERE cVarName = @cVarName
IF @@ERROR <> 0 -- Я так понимаю, что это не отрабатывает.
BEGIN
ROLLBACK TRANSACTION
return(-1)
END

COMMIT
return(0)
GO

-------------------------------------------- ПРООВЕРКА -----------------------------------------------------------
-- Заполнение данными
--SELECT * FROM cfVariable
INSERT INTO cfVariable (cVarName)
VALUES ('testVar1')
GO

INSERT INTO cfVariable (cVarName)
VALUES ('testVar2')
GO

-- Добавление формулы в таблицу расчетных переменных
-- <имя переменной>.<имя поля> = <формула>
-- SELECT * FROM cfCalcRule
DECLARE @VarID int
SELECT @VarID = VarID FROM cfVariable WHERE cVarName = 'testVar1'

INSERT INTO cfCalcRule (left_id ,
left_field,
right_val)
VALUES (@VarID,
'val',
'testVar2 + 1000 / testVar2')
GO

-- Проверка удаления из cfVariable
DELETE cfVariable WHERE cVarName = 'testVar2'
GO

-- Проверка удаления с помощью хр. процедуры
DECLARE @RETURN_VALUE int
EXEC @RETURN_VALUE = DelVar @cVarName = 'testVar2'
PRINT '@RETURN_VALUE = ' + CONVERT(varchar(10),@RETURN_VALUE)
GO
...
Рейтинг: 0 / 0
Хр. процедура удаления приводит к работе триггера -> Не ловится ошибка.
    #32029078
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Только-что проверил.
Ошибка генерится в обоих случаях.

Я думаю, тут тонкости подключения - какой провайдер?
Или, может, поставить SET NOCOUNT ON в скрипты создания и в коннекте...
...
Рейтинг: 0 / 0
Хр. процедура удаления приводит к работе триггера -> Не ловится ошибка.
    #32029082
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лучше бы поменять местами в триггере RAISERROR и ROLLBACK - а то получается, что процедура ловит переменную @@ERROR, которая после ROLLBACK будет показывать 0 - так как эта команда нормально отрабатывается. Почему ошибка в VB не показывается, не знаю, так как не спец. Но как вариант могу предложить, если и при перестановке операторов не будет срабатывать, то в ХП в условие обработки ошибки еще раз вгонять RAISERROR - как говорится, не хочет по хорошему ...
...
Рейтинг: 0 / 0
Хр. процедура удаления приводит к работе триггера -> Не ловится ошибка.
    #32029145
Sash
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Поставил первой строкой в процедуре и в триггере SET NOCOUNT ON и теперь все работает.

Огромное спасибо всем за участие!
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Хр. процедура удаления приводит к работе триггера -> Не ловится ошибка.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]