Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Можно ли использовать хранимую функцию в триггере?  [new]
Joss
Member

Откуда: г. Минск
Сообщений: 5126
Работаю с MS SQL 2000. Создал функцию в базе
CREATE FUNCTION dbo.fn_CurrentOrg
RETURNS INT
AS
BEGIN
      SELECT     IdOrg
      FROM         dbo.tblCurrentOrg
END
Пробую вызвать её из триггера
CREATE trigger trDateInsert
on dbo.tblDocums
for insert
not for replication
as
set nocount on
set rowcount 0
update dbo.tblDocums 
set DateIns =cast(getdate() as smalldatetime) , IdOrgCur=fn_CurrentOrg
from inserted i where i.idDocums=tblDocums.idDocums
Не вызывается. Выдает ошибку 195: Is not a recognized function name (нераспознанное имя функции)
22 апр 08, 17:38    [5581572]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
Glory
Member

Откуда:
Сообщений: 104760
Все UDF вызываются так <owner>.fn_CurrentOrg(<parameters>)
22 апр 08, 17:39    [5581582]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74925
автор
CREATE FUNCTION dbo.fn_CurrentOrg
RETURNS INT
AS
BEGIN
SELECT IdOrg
FROM dbo.tblCurrentOrg
END


Такая функция впринципе не м.б. создана, ибо синтаксически неверна.

автор
Не вызывается.


Вызов скалярной функции должен делаться обязятельно с префиксом схемы.
22 апр 08, 17:40    [5581594]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
Joss
Member

Откуда: г. Минск
Сообщений: 5126
Да, когда добавил dbo синтаксический контроль сработал.
CREATE trigger trDateInsert
on dbo.tblDocums
for insert
not for replication
as
set nocount on
set rowcount 0
update dbo.tblDocums 
set DateIns =cast(getdate() as smalldatetime) , IdOrgCur=dbo.fn_CurrentOrg()
from inserted i where i.idDocums=tblDocums.idDocums
Но при попытке добавить запись появилось сообщение.

Invalid object name 'dbo.fn_CurrentOrg'

И ещё вопрос. Как правильно создать функцию. Я её создаю в Access и она работает, возвращает нужное значение. А как это сделать в SQL Server - не нашел.
22 апр 08, 18:11    [5581754]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
Hamlet
Member

Откуда: Armenia
Сообщений: 573
Картинка с другого сайта.Можно посмотреть на функцию, созданное в Access-е?
22 апр 08, 18:33    [5581863]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
Joss
Member

Откуда: г. Минск
Сообщений: 5126
Проблема решена
Для разработки хранимой функции воспользовался QA. Правильный вид функции.
CREATE FUNCTION dbo.fnCurrentOrg()
RETURNS INT
AS
BEGIN
   return   (SELECT IdOrg FROM dbo.tblCurrentOrg)
END
Надо было в RETURNS поставить INT и всё получилось. Средствами Access изменить не получалось.

to Hamlet

Вот функция созданная в Access (ошибка в RETURNS надо INT а не TABLE)
ALTER  FUNCTION dbo.fnCurrentOrg()
RETURNS TABLE
AS
RETURN ( SELECT     IdOrg
FROM         dbo.tblCurrentOrg )
22 апр 08, 18:56    [5581956]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Joss
(ошибка в RETURNS надо INT а не TABLE)
Не надо! Проблем не оберёшься. Не юзайте скалярные функции. Лучше так:
CREATE TRIGGER [dbo].[trDateInsert] ON [dbo].[tblDocums]
FOR INSERT NOT FOR REPLICATION AS BEGIN
	SET NOCOUNT ON
	UPDATE	D
	SET	 DateIns	= Convert(SmallDateTime,GetDate())
		,IdOrgCur	= L.IdOrg
	FROM	           inserted		I
		      JOIN dbo.tblDocums	D ON D.IDDocums = I.IDDocums
		CROSS JOIN dbo.tblCurrentOrg	L
END
GO
Или
CREATE TRIGGER [dbo].[trDateInsert] ON [dbo].[tblDocums]
FOR INSERT NOT FOR REPLICATION AS BEGIN
	SET NOCOUNT ON
	UPDATE	D
	SET	 DateIns	= (SELECT IdOrg FROM dbo.tblCurrentOrg)
		,IdOrgCur	= L.IdOrg
	FROM	     inserted		I
		JOIN dbo.tblDocums	D ON D.IDDocums = I.IDDocums
END
GO
Или
CREATE FUNCTION [dbo].[fn_CurrentOrg] (
) RETURNS TABLE AS RETURN (
	SELECT	IdOrg
	FROM	dbo.tblCurrentOrg
)
GO
CREATE TRIGGER [dbo].[trDateInsert] ON [dbo].[tblDocums]
FOR INSERT NOT FOR REPLICATION AS BEGIN
	SET NOCOUNT ON
	UPDATE	D
	SET	 DateIns	= Convert(SmallDateTime,GetDate())
		,IdOrgCur	= L.IdOrg
	FROM	           inserted		I
		      JOIN dbo.tblDocums	D ON D.IDDocums = I.IDDocums
		CROSS JOIN dbo.fn_CurrentOrg()	L
END
GO
23 апр 08, 01:38    [5582717]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
Joss
Member

Откуда: г. Минск
Сообщений: 5126
to Mnior

у меня раньше был Ваш второй вариант. Но потом захотел облегчить себе жизнь, так как значение
(SELECT IdOrg FROM dbo.tblCurrentOrg)
используется во многих местах, решил заменить его фунтцией
CREATE FUNCTION dbo.fnCurrentOrg()
RETURNS INT
AS
BEGIN
   return   (SELECT IdOrg FROM dbo.tblCurrentOrg)
END
Чтоб упростить написание процедур и т.п. Опыт небольшой, отсюда вопрос. Какие могут возникнуть проблемы со скалярными функциями?

И в догонку. Если выборка
(SELECT IdOrg FROM dbo.tblCurrentOrg)
возвращает NULL, что маловероятно, но может получиться, то надо эту запись удалить (или отменить добавление) и выдать соответствующее сообщение. Как это сделать?

Может можно как-то настроить триггер, чтобы он срабатывал до вставки?
23 апр 08, 11:52    [5584115]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
iap
Member

Откуда: Москва
Сообщений: 46999
Joss
Может можно как-то настроить триггер, чтобы он срабатывал до вставки?
Можно написать триггер ВМЕСТО вставки - INSTEAD OF INSERT
23 апр 08, 11:57    [5584161]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Joss
Но потом захотел облегчить себе жизнь, так как значение используется во многих местах, решил заменить его фунтцией
Что то я особого облегчения не вижу.
Joss
Какие могут возникнуть проблемы со скалярными функциями?
Они могут выполнятся для каждой строки, хотя возвращают одно и тоже. А всё потому, что скалярные функции компилируемый объект, как процедура (её даже через EXEC вызвать можно). Inline функция - это вьюха с параметрами. Вьюхи не компилятся, они "встаиваюся" как буд-то препроцессорная директива. И тогда оптимизатор запросов выкинет её вверх, чтоб раз выполнилось.
Joss
Если выборка возвращает NULL, то надо отменить добавление и выдать соответствующее сообщение. Как это сделать?
Вам триггер ваще не нужен. Курите Default Constaint на колонки таблицы. А также поставте на колонку NOT NULL.
23 апр 08, 17:09    [5586783]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
Serg_ShariK
Member

Откуда:
Сообщений: 1
ребята, хелп!) совсем запутался. пишу такой тригер:
CREATE trigger Number_Of_Empty
on dbo.Passenger
FOR INSERT, UPDATE
AS
BEGIN
	declare @FlightID int
	declare @Col int
	SET @Col =  dbo.fn_Number_Of_Empty_FC (313);
	IF @Col=0 
		BEGIN
			declare @Mes nvarchar(max)
			SELECT @Mes='Все билеты первого класса проданы!	'
			RAISERROR(@Mes,16,1)
			ROLLBACK TRANSACTION	l
		END
END

он компилируется! но при попытке добавить что-либо в таблицу Passenger, ругается, что
автор
Сообщение 4121, уровень 16, состояние 1, процедура Number_Of_Empty, строка 12
Не удалось найти столбец "dbo", определяемую пользователем функцию или агрегатную функцию "dbo.fn_Number_Of_Empty_FC". Также возможно, имя является неоднозначным.

Что за бред?? функция сама по себе нормально выполняется
10 дек 13, 00:43    [15268032]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
aleks2
Guest
Serg_ShariK
Что за бред?? функция сама по себе нормально выполняется

Апять в Access-е?

CREATE trigger Number_Of_Empty
on dbo.Passenger
FOR INSERT, UPDATE
AS
BEGIN
	IF dbo.fn_Number_Of_Empty_FC (313) = 0 
	BEGIN
		RAISERROR('Все билеты первого класса проданы!', 16, 1)
		ROLLBACK TRANSACTION
	END
END
10 дек 13, 05:52    [15268237]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли использовать хранимую функцию в триггере?  [new]
iap
Member

Откуда: Москва
Сообщений: 46999
Корректно ли вообще проверять наличие непроданных билетов ПОСЛЕ вставки пассажира?
Его билет, получается, тоже посчитался. И оказался последним. Это нормально. Зачем же RAISERROR?
10 дек 13, 10:24    [15268997]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить